基于源码深度解析
2026-04-06 | TensorRT Inference Engine
第一部分:基础概念
第二部分:核心组件
第三部分:核心实现
第四部分:运行时
TensorRT 是 NVIDIA 推出的高性能深度学习推理优化工具包,专门为 GPU 加速而设计。
TensorRT 采用 构建器-运行时 两阶段架构,将模型解析、优化与执行分离。
TensorRT Architecture ┌─────────────────────────────────────────────────────┐ │ 应用程序层 │ ├─────────────────────────────────────────────────────┤ │ TensorRT API Layer │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ IBuilder │ │ IRuntime │ │IExecutionContext│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ ├─────────────────────────────────────────────────────┤ │ 核心处理层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │NetworkDef │ │Engine │ │Plugin │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ ├─────────────────────────────────────────────────────┤ │ 硬件抽象层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │CUDA Driver │ │CUDA Stream │ │Memory Pool │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────┘
TensorRT 11.0 计划在 2026 年 Q2 发布,带来重大 API 改进和性能提升。
TensorRT 的推理优化流程通过多阶段优化实现最佳性能。
TensorRT Optimization Pipeline 1. 模型导入 ├─ ONNX Parser (解析 ONNX 模型) ├─ UFF Parser (解析 TensorFlow 模型) └─ Network Definition (创建网络定义) 2. 图优化 ├─ 层融合 (Layer Fusion) ├─ 常量折叠 (Constant Folding) ├─ 死代码消除 (Dead Code Elimination) └─ 算子替换 (Operator Replacement) 3. 精度优化 ├─ FP16 量化 ├─ INT8 校准 └─ 稀疏化优化 4. 引擎构建 ├─ 内存分配优化 ├─ CUDA 流优化 └─ Tensor Core 利用 5. 序列化部署 ├─ Engine 序列化 └─ 运行时加载
TensorRT 的核心组件包括构建器、运行时、插件系统等关键模块。
NvInfer.h 是 TensorRT 的核心头文件,定义了所有主要接口。
class NvInfer {
public:
// 构建器接口
IBuilder* createBuilder();
// 运行时接口
IRuntime* createInferRuntime(ILogger& logger);
// 版本信息
int32_t getInferLibVersion() const;
// 图优化
bool hasImplicitBatchDimension() const;
// 精度支持
bool supportsFormat(PluginTensorFormat format, DataType type) const;
// 特性检查
bool platformHasFastFp16() const;
bool platformHasFastInt8() const;
bool platformHasFp16Fma() const;
};
// 版本检查示例
if (nvInferLibVersion < NV_TENSORRT_VERSION) {
// 版本兼容性检查
}
构建器模式允许用户逐步构建和优化神经网络。
// 创建构建器 IBuilder* builder = createInferBuilder(logger); // 配置构建参数 builder->setMaxBatchSize(batchSize); builder->setMaxWorkspaceSize(1 << 30); // 1GB builder->setMinFindIterations(3); builder->setAverageFindIterations(1); // 创建网络定义 INetworkDefinition* network = builder->createNetworkV2(1U << int(NetworkDefinitionCreationFlag::kEXPLICIT_BATCH));
// 创建优化配置
IBuilderConfig* config = builder->createBuilderConfig();
// 设置精度
config->setFlag(BuilderFlag::kFP16);
config->setFlag(BuilderFlag::kINT8);
// 设置校准器
if (useInt8) {
config->setInt8Calibrator(calibrator);
}
// 设置内存池大小
config->setMaxWorkspaceSize(maxWorkspaceSize);
运行时模式专注于高性能推理执行,支持异步和多流执行。
Runtime Interface Structure ┌─────────────────────────────────────────────────────┐ │ IRuntime │ │ ┌─────────────────────────────────────────────────┐ │ │ │ createInferEngine(ILogger&) │ │ │ │ └── 返回 ICudaEngine* │ │ │ │ │ │ │ │ getEngine(engineName) │ │ │ │ └── 引擎管理 │ │ │ │ │ │ │ │ deserializeCudaEngine(serializedData) │ │ │ │ └── 反序列化引擎 │ │ │ └─────────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────┤ │ ICudaEngine │ │ ┌─────────────────────────────────────────────────┐ │ │ │ createExecutionContext() │ │ │ │ └── 返回 IExecutionContext* │ │ │ │ │ │ │ │ serialize() │ │ │ │ └── 序列化引擎为二进制 │ │ │ │ │ │ │ │ getEngineInfo() │ │ │ │ └── 获取引擎信息 │ │ │ └─────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────┘
IExecutionContext 管理推理执行,支持动态输入尺寸和多流执行。
class IExecutionContext {
public:
// 推理执行
bool enqueue(
void const* const* inputs,
void* const* outputs,
void* stream = nullptr
);
// 动态尺寸设置
bool setInputShape(
const char* name,
Dims32 const& dims
);
// 内存管理
void setInputBinding(int binding, void* buffer);
void setOutputBinding(int binding, void* buffer);
// 批处理
bool setOptimizationProfile(const IOptimizationProfile* profile);
// 查询接口
IEngine& getEngine() const;
int getNbBindings() const;
bool bindingIsInput(int binding) const;
DataType getBindingDataType(int binding) const;
Dims getBindingDimensions(int binding) const;
};
TensorRT 支持多种数据类型,包括 FP32、FP16、INT8 等。
enum class DataType {
kFLOAT = 0, // 32-bit 浮点数
kHALF = 1, // 16-bit 浮点数
kINT8 = 2, // 8-bit 整数
kINT32 = 3, // 32-bit 整数
kBOOL = 4, // 布尔值
kUINT8 = 5 // 8-bit 无符号整数
};
// 数据类型特性
struct TypeProperties {
size_t size; // 字节大小
bool isInt; // 是否为整数类型
bool isFloat; // 是否为浮点类型
bool isSigned; // 是否为有符号类型
};
// 检查精度支持
bool hasFastFp16 = nvInfer->platformHasFastFp16();
bool hasFastInt8 = nvInfer->platformHasFastInt8();
// 选择最佳精度
DataType selectOptimalPrecision(const ModelConfig& config) {
if (config.enableInt8 && hasFastInt8) {
return DataType::kINT8;
}
if (config.enableFp16 && hasFastFp16) {
return DataType::kHALF;
}
return DataType::kFLOAT;
}
Logger 接口处理 TensorRT 的日志输出,支持不同级别的日志信息。
class ILogger {
public:
enum class Severity {
kINTERNAL_ERROR = 0, // 致命错误
kERROR = 1, // 错误
kWARNING = 2, // 警告
kINFO = 3, // 信息
kVERBOSE = 4 // 详细信息
};
virtual ~ILogger() {}
virtual void log(Severity severity, const char* msg) noexcept = 0;
};
// 示例 Logger 实现
class TensorRTLogger : public ILogger {
public:
void log(Severity severity, const char* msg) noexcept override {
const char* severityStr = "UNKNOWN";
switch (severity) {
case Severity::kINTERNAL_ERROR: severityStr = "ERROR"; break;
case Severity::kERROR: severityStr = "ERROR"; break;
case Severity::kWARNING: severityStr = "WARNING"; break;
case Severity::kINFO: severityStr = "INFO"; break;
case Severity::kVERBOSE: severityStr = "VERBOSE"; break;
}
printf("[%s] %s\n", severityStr, msg);
}
};
I/O 排序优化用于提高内存访问效率,减少缓存未命中。
I/O 优化策略
┌─────────────────────────────────────────────────────┐
│ 输入排序优化 │
├─────────────────────────────────────────────────────┤
│ • NHWC → NCHW 转换 │
│ • 内存连续性优化 │
│ • 缓存行对齐 │
│ │
│ 输出排序优化 │
├─────────────────────────────────────────────────────┤
│ • 张量维度重排 │
│ • 内存预取优化 │
│ • 写合并优化 │
│ │
│ 实现接口 │
├─────────────────────────────────────────────────────┤
│ enum class TensorFormat { │
│ kLINEAR, │
│ kCHW4, │
│ kHWC8, │
│ kDLA_LINEAR, │
│ kDLA_HWC4 │
│ }; │
│ │
│ bool isTensorFormatSupported( │
│ TensorFormat format, │
│ DataType type │
│ ); │
└─────────────────────────────────────────────────────┘
动态批处理支持不同输入尺寸的推理,提高资源利用率。
动态批处理实现
// 创建优化配置
IOptimizationProfile* profile = builder->createOptimizationProfile();
// 设置输入尺寸范围
profile->setDimensions(
"input",
OptSelection::kMIN,
Dims4{1, 3, 224, 224}
);
profile->setDimensions(
"input",
OptSelection::kOPT,
Dims4{8, 3, 224, 224}
);
profile->setDimensions(
"input",
OptSelection::kMAX,
Dims4{32, 3, 224, 224}
);
// 运行时动态设置
context->setInputShape("input", dims);
bool success = context->enqueueV2(...);
// 批处理优化
if (batchSize == 1) {
// 单样本优化
context->setOptimizationProfile(profile);
} else {
// 批处理优化
context->setOptimizationProfile(batchProfile);
}
INetworkDefinition 定义神经网络的结构和计算图。
class INetworkDefinition {
public:
// 层操作
ILayer* addActivation(
const char* name,
ActivationType type,
Weights* weights = nullptr,
int nbWeights = 0
);
ILayer* addConvolution(
const char* name,
int nbOutputMaps,
DimsHW kernelSize,
int nbGroups,
Weights* kernelWeights,
int nbKernelWeights,
Weights* biasWeights = nullptr
);
ILayer* addFullyConnected(
const char* name,
int outputSize,
Weights* weights,
int nbWeights,
Weights* bias = nullptr
);
// 输入/输出定义
ITensor* addInput(
const char* name,
DataType type,
Dims const& dims
);
ITensor* getOutput(int index) const;
int getNbLayers() const;
int getNbInputs() const;
int getNbOutputs() const;
};
构建器 API 提供了创建和优化网络的高级接口。
// 创建构建器
IBuilder* builder = createInferBuilder(logger);
// 配置构建参数
builder->setMaxBatchSize(32);
builder->setMaxWorkspaceSize(1 << 30);
builder->setMinFindIterations(1);
builder->setAverageFindIterations(1);
// 设置优化标志
builder->setFlag(BuilderFlag::kFP16);
builder->setFlag(BuilderFlag::kINT8);
// 创建网络定义
INetworkDefinition* network =
builder->createNetworkV2(1U << int(NetworkDefinitionCreationFlag::kEXPLICIT_BATCH));
// 创建构建配置 IBuilderConfig* config = builder->createBuilderConfig(); // 设置工作空间 config->setMaxWorkspaceSize(1 << 30); // 设置精度 config->setFlag(BuilderFlag::kFP16); config->setFlag(BuilderFlag::kINT8); // 设置校准器 config->setInt8Calibrator(calibrator); // 构建引擎 ICudaEngine* engine = builder->buildEngineWithConfig(*network, *config); // 序列化引擎 IHostMemory* serializedEngine = engine->serialize();
网络解析器将不同格式的模型转换为 TensorRT 的网络定义。
解析器接口结构
┌─────────────────────────────────────────────────────┐
│ 解析器基类 │
│ IParser (抽象接口) │
├─────────────────────────────────────────────────────┤
│ ONNX 解析器 │
│ class OnnxParser : public IParser { │
│ public: │
│ bool parse(const char* modelFile, │
│ INetworkDefinition& network); │
│ bool parse(const void* serializedData, │
│ size_t size, │
│ INetworkDefinition& network); │
│ int getNbInputs() const; │
│ int getNbOutputs() const; │
│ Dims getInputDimensions(int index) const; │
│ Dims getOutputDimensions(int index) const; │
│ }; │
├─────────────────────────────────────────────────────┤
│ UFF 解析器 │
│ class UffParser : public IParser { │
│ public: │
│ bool parse(const char* uffFile, │
│ INetworkDefinition& network, │
│ const IUffParser::CustomPlugin* │
│ customPlugin = nullptr); │
│ void registerInput(const char* name, │
│ Dims dims, │
│ UffInputMode mode = │
│ UffInputMode::kLINEAR); │
│ }; │
└─────────────────────────────────────────────────────┘
ONNX 解析器将 ONNX 模型转换为 TensorRT 的网络定义。
ONNX 解析示例
// 创建 ONNX 解析器
OnnxParser parser{createInferParser(logger)};
// 解析 ONNX 模型
bool success = parser.parse(
"model.onnx",
*network
);
// 设置输入维度
parser.registerInput(
"input",
Dims4{1, 3, 224, 224},
TensorFormat::kLINEAR
);
// 设置输出维度
parser.registerOutput("output");
// 检查解析结果
if (!success) {
std::cout << "ONNX parsing failed" << std::endl;
return false;
}
// 获取输入/输出信息
int nbInputs = parser.getNbInputs();
int nbOutputs = parser.getNbOutputs();
std::cout << "Input tensors: " << nbInputs << std::endl;
std::cout << "Output tensors: " << nbOutputs << std::endl;
// 获取维度信息
Dims inputDims = parser.getInputDimensions(0);
Dims outputDims = parser.getOutputDimensions(0);
UFF 解析器将 TensorFlow 模型转换为 TensorRT 的网络定义。
UFF 解析示例
// 创建 UFF 解析器
UffParser parser;
// 注册输入
parser.registerInput(
"input_tensor",
DimsCHW{3, 224, 224},
UffInputMode::kLINEAR
);
// 注册输出
parser.registerOutput("output_node/Softmax");
// 解析 UFF 模型
bool success = parser.parse(
"model.uff",
*network,
nullptr
);
// 添加 TensorFlow 兼容层
if (!success) {
// 尝试不同的输入名称
parser.registerInput(
"Placeholder",
DimsCHW{3, 224, 224},
UffInputMode::kLINEAR
);
success = parser.parse("model.uff", *network, nullptr);
}
// 处理自定义操作
if (!success) {
// 创建自定义插件
CustomPlugin* plugin = new CustomPlugin();
parser.parse("model.uff", *network, plugin);
}
TensorRT 通过图优化技术提升推理性能,包括层融合、常量折叠等。
图优化算法 ┌─────────────────────────────────────────────────────┐ │ 层融合优化 │ ├─────────────────────────────────────────────────────┤ │ • Conv + Bias + Activation │ │ • Conv + BatchNorm + Activation │ │ • Fully Connected + Activation │ │ • Pooling + Activation │ │ │ │ 常量折叠 │ ├─────────────────────────────────────────────────────┤ │ • 预计算常量运算 │ │ • 消除冗余计算 │ │ • 算子简化 │ │ │ │ 死代码消除 │ ├─────────────────────────────────────────────────────┤ │ • 移除未使用的层 │ │ • 优化控制流 │ │ • 条件执行优化 │ │ │ │ 算子替换 │ ├─────────────────────────────────────────────────────┤ │ • TensorFlow → CUDA 算子 │ │ • 专用 CUDA kernel 替换 │ │ • Tensor Core 优化算子 │ └─────────────────────────────────────────────────────┘
层融合是 TensorRT 的核心技术之一,通过合并多个层来提高性能。
常见的融合模式 1. Conv + Bias + ReLU ├─ Convolution: X * W + b ├─ Bias: Y = X + b └─ ReLU: Y = max(Y, 0) 融合后: Y = max(X * W + b + b', 0) 2. Conv + BatchNorm + ReLU ├─ Convolution: X * W + b ├─ BatchNorm: Y = γ * (Y - μ) / σ + β └─ ReLU: Y = max(Y, 0) 融合后: Y = max((X * W + b - μ) * γ / σ + β, 0) 3. Fully Connected + Bias + ReLU 与 Conv 融合类似,使用矩阵乘法
// 设置融合策略
IBuilderConfig* config = builder->createBuilderConfig();
// 启用层融合
config->setFlag(BuilderFlag::kSTRICT_TYPES);
// 自定义融合规则
if (builder->platformHasFp16Fma()) {
config->setFlag(BuilderFlag::kFP16);
}
// 创建优化配置
IOptimizationProfile* profile =
builder->createOptimizationProfile();
// 设置输入范围
profile->setDimensions("input", OptSelection::kMIN, Dims4{1, 3, 224, 224});
profile->setDimensions("input", OptSelection::kOPT, Dims4{8, 3, 224, 224});
profile->setDimensions("input", OptSelection::kMAX, Dims4{32, 3, 224, 224});
INT8 精度校准是 TensorRT 的关键技术,通过校准过程最小化精度损失。
INT8 校准流程
class Int8Calibrator : public IInt8Calibrator {
private:
std::string datasetPath;
int currentBatch;
std::vector> inputBuffers;
Weights scalingFactors;
public:
Int8Calibrator(const std::string& dataset,
int batchSize,
int inputSize)
: datasetPath(dataset)
, currentBatch(0)
, inputSize(inputSize)
, batchSize(batchSize) {
// 准备输入缓冲区
inputBuffers.resize(batchSize);
for (int i = 0; i < batchSize; i++) {
inputBuffers[i] = allocateBuffer(inputSize);
}
}
virtual ~Int8Calibrator() {
for (auto& buffer : inputBuffers) {
freeBuffer(buffer);
}
}
// 获取校准数据
virtual int getBatchSize() const override { return batchSize; }
virtual bool getBatch(void* bindings[],
char* names[],
int nbBindings) override {
if (currentBatch >= totalBatches) {
return false;
}
// 加载校准数据
for (int i = 0; i < batchSize; i++) {
loadSample(currentBatch * batchSize + i,
inputBuffers[i]);
bindings[i] = inputBuffers[i].data();
}
currentBatch++;
return true;
}
// 提供缩放因子
virtual const void* getCalibrationTable(
const char* name,
size_t& length) override {
// 计算量化缩放因子
computeScalingFactors();
length = scalingFactors.count;
return scalingFactors.values;
}
};
// 使用校准器
builderConfig->setInt8Calibrator(&calibrator);
TensorRT 提供多种量化策略,支持不同的精度需求和硬件特性。
enum class QuantizationFlag {
kNONE = 0, // 无量化
kFORCE_FP32 = 1, // 强制 FP32
kFORCE_FP16 = 2, // 强制 FP16
kFORCE_INT8 = 4, // 强制 INT8
kPER_TENSOR = 8, // 每张量量化
kPER_CHANNEL = 16, // 每通道量化
kCALIBRATE = 32 // 需要校准
};
// 量化配置
struct QuantizationConfig {
DataType targetDataType; // 目标数据类型
QuantizationFlag flags; // 量化标志
float calibrationThreshold; // 校准阈值
int calibrationSamples; // 校准样本数
std::string calibrationPath; // 校准数据路径
};
// 量化策略选择函数
QuantizationConfig selectQuantizationStrategy(
const ModelConfig& model,
const HardwareInfo& hardware) {
QuantizationConfig config;
// 基于硬件特性选择
if (hardware.hasFastInt8) {
config.targetDataType = DataType::kINT8;
config.flags = QuantizationFlag::kCALIBRATE;
} else if (hardware.hasFastFp16) {
config.targetDataType = DataType::kHALF;
config.flags = QuantizationFlag::kFORCE_FP16;
} else {
config.targetDataType = DataType::kFLOAT;
config.flags = QuantizationFlag::kFORCE_FP32;
}
// 设置校准参数
config.calibrationSamples = 500;
config.calibrationThreshold = 1.0f;
return config;
}
INT8 校准过程确定最佳量化参数,最小化精度损失。
INT8 校准算法 ┌─────────────────────────────────────────────────────┐ │ 校准算法 │ ├─────────────────────────────────────────────────────┤ │ 1. 数据收集 │ │ ├─ 收集代表性输入数据 │ │ ├─ 数据预处理和归一化 │ │ └─ 存储校准数据集 │ │ │ │ 2. 统计分析 │ │ ├─ 计算激活值的分布 │ │ ├─ 确定动态范围 │ │ └─ 统计极值和分位数 │ │ │ │ 3. 量化参数计算 │ │ ├─ 均值估计 │ │ ├─ 方差估计 │ │ ├─ 缩放因子计算 │ │ └─ 偏移量计算 │ │ │ │ 4. 精度验证 │ │ ├─ 在校准数据上测试 │ │ ├─ 计算量化误差 │ │ └─ 调整校准参数 │ │ │ │ 5. 参数应用 │ │ ├─ 生成缩放表 │ │ ├─ 应用到模型 │ │ └─ 部署优化模型 │ └─────────────────────────────────────────────────────┘
FP16 优化利用 GPU 的半精度计算能力,提高推理吞吐量。
FP16 优化策略
class Fp16Optimization {
public:
// 检查硬件支持
static bool isSupported(const HardwareInfo& hardware) {
return hardware.hasFp16Fma &&
hardware.hasFp16Denormals &&
hardware.hasFp16Rounding;
}
// 选择适合的层
static bool canUseFp16(ILayer* layer) {
switch (layer->getType()) {
case LayerType::kCONVOLUTION:
case LayerType::kFULLY_CONNECTED:
case LayerType::kACTIVATION:
case LayerType::kPOOLING:
return true;
case LayerType::kDECONVOLUTION:
case LayerType::kPLUGIN:
case LayerType::kCONSTANT:
return false;
default:
return canUseFp16ForLayer(layer);
}
}
// FP16 优化配置
static void configureFp16Optimization(
IBuilderConfig* config,
const ModelConfig& model) {
if (isSupported(model.hardware)) {
config->setFlag(BuilderFlag::kFP16);
// 禁用不支持 FP16 的层
for (auto layer : model.layers) {
if (!canUseFp16(layer)) {
config->setFlag(layer, BuilderFlag::kFP32);
}
}
}
}
};
Plugin 系统允许用户自定义算子,扩展 TensorRT 的功能。
Plugin 系统架构 ┌─────────────────────────────────────────────────────┐ │ Plugin 接口 │ │ IPluginV3 (最新版本) │ ├─────────────────────────────────────────────────────┤ │ 核心方法 │ │ virtual int getNbOutputs() const; │ │ virtual Dims getOutputDimensions( │ │ int outputIndex, │ │ const Dims* inputs, │ │ int nbInputs); │ │ │ │ virtual int initialize( │ │ const void* serialData, │ │ size_t serialLength); │ │ │ │ virtual void terminate(); │ │ │ │ virtual size_t getWorkspaceSize( │ │ const Dims* inputs, │ │ int nbInputs) const; │ │ │ │ virtual int enqueue( │ │ void const* const* inputs, │ │ void* const* outputs, │ │ void* workspace, │ │ cudaStream_t stream); │ └─────────────────────────────────────────────────────┘
IPluginV3 是 TensorRT 11.0 的最新插件接口,相比 IPluginV2 有重大改进。
IPluginV3 主要改进 1. 更好的类型安全 ├─ 强类型网络支持 ├─ 精确的维度计算 └─ 编译时错误检查 2. 增强的功能支持 ├─ 动态输入尺寸 ├─ 输出形状推断 └─ 多输出支持 3. 性能优化 ├─ 减少内存分配 ├─ 优化数据传输 └─ CUDA 流优化 4. 序列化改进 ├─ 二进制序列化 ├─ 版本控制 └─ 向后兼容
class MyCustomPlugin : public IPluginV3 {
private:
PluginFieldCollection fc_;
PluginField* fields_;
DataType dataType_;
public:
MyCustomPlugin(const PluginFieldCollection& fc)
: fc_(fc) {
// 解析参数
for (int i = 0; i < fc.nbFields; i++) {
if (strcmp(fc.fields[i].name, "dataType") == 0) {
dataType_ = static_cast(
fc.fields[i].data);
}
}
}
// 实现核心方法
Dims getOutputDimensions(int index,
const Dims* inputs,
int nbInputs) override {
// 根据输入计算输出维度
Dims dims = inputs[0];
dims.d[0] *= 2; // 示例:输出维度加倍
return dims;
}
int enqueue(void const* const* inputs,
void* const* outputs,
void* workspace,
cudaStream_t stream) override {
// 实现核心计算逻辑
return cudaCustomKernel(
inputs[0], outputs[0], workspace, stream);
}
};
自定义层允许用户实现特定的神经网络层,扩展 TensorRT 的能力。
自定义层实现步骤
1. 继承 IPluginV3
class CustomLayer : public IPluginV3 {
public:
// 构造函数
CustomLayer(const PluginFieldCollection& fc);
// 核心方法
Dims getOutputDimensions(int index,
const Dims* inputs,
int nbInputs) override;
int enqueue(void const* const* inputs,
void* const* outputs,
void* workspace,
cudaStream_t stream) override;
// 序列化
size_t getSerializationSize() const override;
void serialize(void* buffer) const override;
};
2. 注册插件
class CustomPluginFactory : public IPluginFactory {
public:
IPluginV3* createPlugin(const char* name,
const PluginFieldCollection* fc,
const char* pluginType) override {
if (strcmp(pluginType, "CustomLayer") == 0) {
return new CustomLayer(*fc);
}
return nullptr;
}
};
3. 使用插件
IBuilder* builder = createInferBuilder(logger);
PluginFactory factory;
// 添加自定义层
ILayer* layer = network->addPluginV2(
input,
factory.createPlugin("customLayer", fields)
);
插件注册机制允许 TensorRT 发现和使用自定义插件。
插件注册流程
// 1. 定义插件字段
PluginFieldCollection fc;
PluginField fields[] = {
PluginField("alpha", &alpha,
PluginFieldType::kFLOAT32, 1),
PluginField("beta", &beta,
PluginFieldType::kFLOAT32, 1),
PluginField("activation", &activationStr,
PluginFieldType::kCHAR, 1)
};
fc.nbFields = 3;
fc.fields = fields;
// 2. 创建插件
PluginFactory factory;
IPluginV3* plugin = factory.createPlugin(
"CustomActivation",
&fc
);
// 3. 注册插件到网络
ILayer* layer = network->addPluginV2(
input,
plugin
);
// 4. 配置插件参数
layer->setPrecision(DataType::kFP16);
layer->setOutputType(0, DataType::kFP16);
// 5. 设置优化配置
IBuilderConfig* config = builder->createBuilderConfig();
config->setFlag(BuilderFlag::kFP16);
config->setFlag(BuilderFlag::kFP16_FMA);
// 6. 构建引擎
ICudaEngine* engine = builder->buildEngineWithConfig(
*network,
*config
);
运行时引擎负责推理执行,支持序列化/反序列化和高性能执行。
运行时引擎结构
class RuntimeEngine {
private:
ICudaEngine* engine_;
IExecutionContext* context_;
std::vector inputBuffers_;
std::vector outputBuffers_;
public:
RuntimeEngine(const std::string& serializedEngine) {
// 1. 创建运行时
IRuntime* runtime = createInferRuntime(logger_);
// 2. 反序列化引擎
engine_ = runtime->deserializeCudaEngine(
serializedEngine.data(),
serializedEngine.size()
);
// 3. 创建执行上下文
context_ = engine_->createExecutionContext();
// 4. 准备缓冲区
prepareBuffers();
}
~RuntimeEngine() {
cleanup();
}
// 推理执行
bool inference(const std::vector& inputs,
const std::vector& outputs,
cudaStream_t stream = nullptr) {
// 绑定输入/输出
for (size_t i = 0; i < inputs.size(); i++) {
context_->setInputBinding(i, inputs[i]);
}
for (size_t i = 0; i < outputs.size(); i++) {
context_->setOutputBinding(i, outputs[i]);
}
// 执行推理
return context_->enqueue(
inputs.size(),
inputs.data(),
outputs.data(),
stream
);
}
// 性能统计
ProfilerResult getProfilerResult() {
return context_->getProfiler().getResult();
}
};
序列化机制允许将优化后的引擎保存为二进制文件,实现部署优化。
序列化实现
// 序列化引擎
IHostMemory* serializedEngine = engine->serialize();
// 保存到文件
std::ofstream file("optimized.engine",
std::ios::binary);
file.write(serializedEngine->data(),
serializedEngine->size());
file.close();
// 反序列化引擎
IRuntime* runtime = createInferRuntime(logger_);
std::ifstream file("optimized.engine",
std::ios::binary);
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector buffer(size);
file.read(buffer.data(), size);
ICudaEngine* engine = runtime->deserializeCudaEngine(
buffer.data(), size, nullptr
);
// 内存管理
serializedEngine->destroy();
engine->destroy();
高效的内存管理是 TensorRT 高性能的关键,支持 CUDA 流优化。
内存管理策略 ┌─────────────────────────────────────────────────────┐ │ 内存池分配 │ ├─────────────────────────────────────────────────────┤ │ • 预分配内存池 │ │ • 避免频繁分配/释放 │ │ • 内存对齐优化 │ │ • 缓存行对齐 │ │ │ │ 设备内存 │ ├─────────────────────────────────────────────────────┤ │ • GPU 显存分配 │ │ • 零拷贝优化 │ │ • 内存复用策略 │ │ • 内存传输优化 │ │ │ │ 页面锁定内存 │ ├─────────────────────────────────────────────────────┤ │ • Host 端内存锁定 │ │ • 异传输优化 │ │ • 双缓冲策略 │ │ • 流式传输 │ │ │ │ 内存优化 │ ├─────────────────────────────────────────────────────┤ │ • 张量共享内存 │ │ • 常量优化 │ │ • 死代码消除 │ │ • 内存访问模式优化 │ └─────────────────────────────────────────────────────┘
CUDA 流优化是 TensorRT 高性能的核心,支持异步执行和重叠计算。
CUDA 流优化策略
// 创建多个 CUDA 流
cudaStream_t stream1, stream2, stream3;
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
cudaStreamCreate(&stream3);
// 流式执行
class StreamManager {
private:
std::vector streams_;
std::mutex streamMutex_;
public:
StreamManager(int numStreams) {
streams_.resize(numStreams);
for (auto& stream : streams_) {
cudaStreamCreate(&stream);
}
}
~StreamManager() {
for (auto& stream : streams_) {
cudaStreamDestroy(stream);
}
}
cudaStream_t getStream() {
std::lock_guard lock(streamMutex_);
// 轮询分配流
static int roundRobin = 0;
return streams_[roundRobin++ % streams_.size()];
}
};
// 使用流执行推理
bool enqueueWithStream(void const* const* inputs,
void* const* outputs,
StreamManager* streamManager) {
cudaStream_t stream = streamManager->getStream();
return context->enqueueV2(
inputs, outputs, stream
);
}
多流执行通过 CUDA 流实现真正的异步推理,最大化 GPU 利用率。
多流执行架构
┌─────────────────────────────────────────────────────┐
│ 异步流水线 │
├─────────────────────────────────────────────────────┤
│ Stream 0: 预处理 │
│ ├─ 数据传输 (Host → GPU) │
│ ├─ 数据预处理 (Normalize) │
│ └─ 触发 Stream 1 │
│ │
│ Stream 1: 推理 │
│ ├─ 网络前向计算 │
│ ├─ 激活函数计算 │
│ └─ 触发 Stream 2 │
│ │
│ Stream 2: 后处理 │
│ ├─ 输出数据处理 │
│ ├─ 结果后处理 (Post-Process) │
│ └─ 传输回 Host │
│ │
│ Stream 3: 清理 │
│ ├─ 内存管理 │
│ ├─ 结果汇总 │
│ └─ 下批准备 │
└─────────────────────────────────────────────────────┘
// 多流执行实现
bool multiStreamInference(
const std::vector& batches,
StreamManager* streamManager) {
for (const auto& batch : batches) {
// 多流执行
for (int i = 0; i < 4; i++) {
cudaStream_t stream = streamManager->getStream();
// 异步执行
switch (i) {
case 0: preprocessAsync(batch, stream); break;
case 1: inferAsync(batch, stream); break;
case 2: postprocessAsync(batch, stream); break;
case 3: cleanupAsync(batch, stream); break;
}
}
}
// 同步等待所有流完成
for (auto& stream : streamManager->getStreams()) {
cudaStreamSynchronize(stream);
}
return true;
}
IExecutionContext 是推理执行的核心接口,支持多种执行模式。
IExecutionContext 核心方法
class IExecutionContext {
public:
// 基础执行
bool enqueue(
void const* const* inputs, // 输入数据
void* const* outputs, // 输出数据
void* stream = nullptr // CUDA 流
);
bool enqueueV2(
void* const* bindings, // 绑定缓冲区
void* stream = nullptr // CUDA 流
);
// 动态尺寸设置
bool setInputShape(
const char* name, // 输入名称
Dims32 const& dims // 新的维度
);
bool setOptimizationProfile(
const IOptimizationProfile* profile // 优化配置
);
// 内存绑定
void setInputBinding(
int binding, // 绑定索引
void* buffer // 缓冲区指针
);
void setOutputBinding(
int binding, // 绑定索引
void* buffer // 缓冲区指针
);
// 查询接口
IEngine& getEngine() const;
int getNbBindings() const;
bool bindingIsInput(int binding) const;
DataType getBindingDataType(int binding) const;
Dims getBindingDimensions(int binding) const;
// 性能接口
bool getProfiler(bool enable);
ProfilerResult getProfilerResult() const;
};
// 使用示例
bool executeInference(IExecutionContext* context,
const std::vector& inputs,
const std::vector& outputs,
cudaStream_t stream = nullptr) {
// 绑定缓冲区
for (size_t i = 0; i < inputs.size(); i++) {
context->setInputBinding(i, inputs[i].data());
}
for (size_t i = 0; i < outputs.size(); i++) {
context->setOutputBinding(i, outputs[i].data());
}
// 执行推理
return context->enqueueV2(
inputs.data(), outputs.data(), stream
);
}
执行配置优化推理过程,支持动态尺寸、批处理优化等高级功能。
执行配置优化
class ExecutionConfig {
private:
OptimizationProfile* profile_;
int batchSize_;
DataType precision_;
cudaStream_t stream_;
public:
ExecutionConfig(OptimizationProfile* profile,
int batchSize,
DataType precision)
: profile_(profile)
, batchSize_(batchSize)
, precision_(precision) {
// 创建 CUDA 流
cudaStreamCreate(&stream_);
}
~ExecutionConfig() {
cudaStreamDestroy(stream_);
}
// 动态配置调整
void configureDynamicBatching(int batchSize) {
batchSize_ = batchSize;
// 调整输入维度
profile_->setDimensions(
"input",
OptSelection::kOPT,
Dims4{batchSize, 3, 224, 224}
);
}
// 精度配置
void configurePrecision(DataType precision) {
precision_ = precision;
// 更新数据类型
for (int i = 0; i < profile_->getNbBindings(); i++) {
if (profile_->bindingIsInput(i)) {
profile_->setBindingDataType(i, precision);
}
}
}
// 流配置
void configureStream(cudaStream_t stream) {
if (stream != nullptr) {
cudaStreamDestroy(stream_);
}
stream_ = stream;
}
// 推理执行
bool execute(IExecutionContext* context,
const std::vector& inputs,
const std::vector& outputs) {
// 设置优化配置
context->setOptimizationProfile(profile_);
// 执行推理
return context->enqueueV2(
inputs.data(), outputs.data(), stream_
);
}
};
设备内存管理是推理性能的关键,包括内存分配、复用和优化。
设备内存管理策略
class DeviceMemoryManager {
private:
std::vector memoryPool_;
std::mutex mutex_;
size_t totalMemory_;
public:
DeviceMemoryManager(size_t totalMemory)
: totalMemory_(totalMemory) {
// 预分配内存池
int numAllocations = 10;
size_t chunkSize = totalMemory / numAllocations;
for (int i = 0; i < numAllocations; i++) {
void* memory;
cudaMalloc(&memory, chunkSize);
memoryPool_.push_back(memory);
}
}
~DeviceMemoryManager() {
for (auto& memory : memoryPool_) {
cudaFree(memory);
}
}
// 内存分配
void* allocate(size_t size) {
std::lock_guard lock(mutex_);
// 查找合适的内存块
for (auto& memory : memoryPool_) {
// 检查内存块大小
size_t availableSize = getAvailableSize(memory);
if (availableSize >= size) {
return allocateFromChunk(memory, size);
}
}
// 分配新内存
void* newMemory;
cudaMalloc(&newMemory, size);
return newMemory;
}
// 内存释放
void deallocate(void* memory) {
std::lock_guard lock(mutex_);
// 回收到内存池
for (auto& pool : memoryPool_) {
if (isSameMemoryBlock(pool, memory)) {
deallocateToChunk(pool, memory);
return;
}
}
// 释放内存
cudaFree(memory);
}
// 内存复用
void* reuseMemory(size_t size) {
// 从内存池中复用
for (auto& memory : memoryPool_) {
if (canReuseMemory(memory, size)) {
return memory;
}
}
// 分配新内存
return allocate(size);
}
};
推理执行是 TensorRT 的核心功能,支持高性能、低延迟的推理。
推理执行流程
class InferenceExecutor {
private:
IExecutionContext* context_;
std::vector streams_;
std::vector inputBuffers_;
std::vector outputBuffers_;
public:
InferenceExecutor(IExecutionContext* context,
int numStreams = 4)
: context_(context) {
// 创建多个 CUDA 流
streams_.resize(numStreams);
for (auto& stream : streams_) {
cudaStreamCreate(&stream);
}
// 准备缓冲区
prepareBuffers();
}
// 批量推理
std::vector batchInference(
const std::vector& batches) {
std::vector results;
results.reserve(batches.size());
// 流式执行
for (size_t i = 0; i < batches.size(); i++) {
cudaStream_t stream = streams_[i % streams_.size()];
// 准备输入
prepareInput(batches[i], stream);
// 执行推理
bool success = context_->enqueueV2(
inputBuffers_.data(),
outputBuffers_.data(),
stream
);
if (success) {
// 处理输出
InferenceResult result = processOutput(
batches[i],
stream
);
results.push_back(result);
}
}
// 同步所有流
for (auto& stream : streams_) {
cudaStreamSynchronize(stream);
}
return results;
}
// 单样本推理
InferenceResult singleInference(const InputData& input) {
cudaStream_t stream = streams_[0];
// 准备输入
prepareInput(input, stream);
// 执行推理
bool success = context_->enqueueV2(
inputBuffers_.data(),
outputBuffers_.data(),
stream
);
if (success) {
// 处理输出
InferenceResult result = processOutput(input, stream);
return result;
}
return InferenceResult();
}
};
输出解析处理 TensorRT 的推理结果,支持多种数据格式和后处理。
输出解析实现
class OutputParser {
private:
std::vector outputTensors_;
std::vector postProcessors_;
public:
OutputParser(const std::vector& tensors)
: outputTensors_(tensors) {
// 初始化后处理器
for (const auto& tensor : tensors) {
postProcessors_.emplace_back(tensor);
}
}
// 解析输出
std::vector parseOutputs(
const std::vector& deviceOutputs,
const cudaStream_t stream) {
std::vector results;
results.reserve(outputTensors_.size());
for (size_t i = 0; i < outputTensors_.size(); i++) {
const auto& tensor = outputTensors_[i];
void* deviceOutput = deviceOutputs[i];
// 从 GPU 拷贝到 CPU
std::vector hostOutput(tensor.size());
cudaMemcpyAsync(
hostOutput.data(),
deviceOutput,
tensor.size() * sizeof(float),
cudaMemcpyDeviceToHost,
stream
);
// 后处理
ParsedOutput parsed = postProcessors_[i].process(
hostOutput, tensor
);
results.push_back(parsed);
}
return results;
}
// 异步解析
std::vector parseOutputsAsync(
const std::vector& deviceOutputs,
const cudaStream_t stream) {
std::vector results;
results.reserve(outputTensors_.size());
// 异步拷贝和后处理
for (size_t i = 0; i < outputTensors_.size(); i++) {
const auto& tensor = outputTensors_[i];
void* deviceOutput = deviceOutputs[i];
// 异步拷贝
std::vector hostOutput(tensor.size());
cudaMemcpyAsync(
hostOutput.data(),
deviceOutput,
tensor.size() * sizeof(float),
cudaMemcpyDeviceToHost,
stream
);
// 异步后处理
auto parsed = postProcessors_[i].processAsync(
hostOutput, tensor, stream
);
results.push_back(parsed);
}
return results;
}
};
TensorRT 提供多种性能优化技术,包括计算优化、内存优化等。
性能优化策略 ┌─────────────────────────────────────────────────────┐ │ 计算优化 │ ├─────────────────────────────────────────────────────┤ │ • 层融合优化 │ │ • 算子融合 │ │ • 张量核心利用 │ │ • 并行计算优化 │ │ │ │ 内存优化 │ ├─────────────────────────────────────────────────────┤ │ • 内存池分配 │ │ • 缓存行对齐 │ │ • 零拷贝优化 │ │ • 内存访问模式优化 │ │ │ │ 流优化 │ ├─────────────────────────────────────────────────────┤ │ • 多流执行 │ │ • 异步执行 │ │ • 流式处理 │ │ • 重叠计算和传输 │ │ │ │ 精度优化 │ ├─────────────────────────────────────────────────────┤ │ • FP16 优化 │ │ • INT8 量化 │ │ • 稀疏化优化 │ │ • 动态精度调整 │ └─────────────────────────────────────────────────────┘
缓存机制优化引擎构建和推理过程,避免重复计算。
缓存实现策略
class EngineCache {
private:
std::string cachePath_;
std::unordered_map cache_;
public:
EngineCache(const std::string& cachePath)
: cachePath_(cachePath) {
// 加载现有缓存
loadCache();
}
// 获取缓存引擎
ICudaEngine* getCachedEngine(
const std::string& modelHash,
const IBuilderConfig* config) {
std::string cacheKey = generateCacheKey(modelHash, config);
auto it = cache_.find(cacheKey);
if (it != cache_.end()) {
return it->second;
}
return nullptr;
}
// 缓存引擎
void cacheEngine(
const std::string& modelHash,
const IBuilderConfig* config,
ICudaEngine* engine) {
std::string cacheKey = generateCacheKey(modelHash, config);
// 序列化引擎
IHostMemory* serializedEngine = engine->serialize();
// 保存到缓存
saveCache(cacheKey, serializedEngine);
// 添加到内存缓存
cache_[cacheKey] = engine;
}
// 生成缓存键
std::string generateCacheKey(
const std::string& modelHash,
const IBuilderConfig* config) {
std::stringstream ss;
ss << modelHash << "_";
ss << config->getMaxBatchSize() << "_";
ss << static_cast(config->getPrecision()) << "_";
ss << config->getMaxWorkspaceSize();
return ss.str();
}
};
模型优化通过技术手段提升推理性能,包括剪枝、量化等技术。
模型优化技术 ┌─────────────────────────────────────────────────────┐ │ 模型剪枝 │ ├─────────────────────────────────────────────────────┤ │ • 结构化剪枝 │ │ • 非结构化剪枝 │ │ • 剪枝敏感度分析 │ │ • 剪枝-微调循环 │ │ │ │ 模型量化 │ ├─────────────────────────────────────────────────────┤ │ • 权重量化 │ │ • 激活值量化 │ │ • 动态量化 │ │ • 混合精度量化 │ │ │ │ 知识蒸馏 │ ├─────────────────────────────────────────────────────┤ │ • 温度蒸馏 │ │ • 特征蒸馏 │ │ • 关系蒸馏 │ │ • 深度蒸馏 │ │ │ │ 模型压缩 │ ├─────────────────────────────────────────────────────┤ │ • 矩阵分解 │ │ • 低秩近似 │ │ • 张量分解 │ │ • 模型共享 │ └─────────────────────────────────────────────────────┘
Tensor Core 利用 GPU 的张量核心进行矩阵运算,大幅提升性能。
Tensor Core 优化策略
// Tensor Core 配置
class TensorCoreOptimizer {
public:
// 检查硬件支持
static bool hasTensorCoreSupport() {
return nvmlDeviceGetPowerManagementLimit(
deviceId, &limit) == NVML_SUCCESS;
}
// 配置张量核心
static void configureTensorCore(
IBuilderConfig* config) {
if (hasTensorCoreSupport()) {
// 启用张量核心
config->setFlag(BuilderFlag::kTENSOR_CORE);
// 配置精度
config->setFlag(BuilderFlag::kFP16);
config->setFlag(BuilderFlag::kFP32);
// 设置批处理大小
config->setMaxBatchSize(8);
// 配置工作空间
config->setMaxWorkspaceSize(1 << 30);
}
}
// 优化层配置
static void optimizeLayerForTensorCore(
ILayer* layer) {
// 对于卷积层
if (layer->getType() == LayerType::kCONVOLUTION) {
// 设置批处理大小为 8 的倍数
auto dims = layer->getOutputDimensions(0);
dims.d[0] = ((dims.d[0] + 7) / 8) * 8;
// 配置精度
layer->setPrecision(DataType::kFP16);
layer->setOutputType(0, DataType::kFP16);
}
// 对于全连接层
if (layer->getType() == LayerType::kFULLY_CONNECTED) {
// 输出维度对齐
auto dims = layer->getOutputDimensions(0);
dims.d[0] = ((dims.d[0] + 7) / 8) * 8;
layer->setPrecision(DataType::kFP16);
layer->setOutputType(0, DataType::kFP16);
}
}
// 性能验证
static bool validateTensorCorePerformance(
IExecutionContext* context) {
// 执行基准测试
auto result = context->getProfiler().getResult();
// 检查 Tensor Core 使用率
return result.tensorCoreUtilization > 0.8f;
}
};
稀疏推理利用稀疏矩阵特性减少计算量和内存占用。
稀疏推理实现
// 稀疏矩阵表示
class SparseMatrix {
private:
std::vector values_; // 非零值
std::vector indices_; // 列索引
std::vector rowPtr_; // 行指针
int rows_, cols_; // 矩阵维度
public:
SparseMatrix(int rows, int cols)
: rows_(rows), cols_(cols) {}
// 添加稀疏元素
void addElement(int row, int col, float value) {
values_.push_back(value);
indices_.push_back(col);
rowPtr_.push_back(values_.size() - 1);
}
// 稀疏矩阵乘法
std::vector sparseMultiply(
const std::vector& x) {
std::vector result(rows_, 0.0f);
for (int i = 0; i < rows_; i++) {
for (int j = rowPtr_[i]; j < (i < rows_-1 ? rowPtr_[i+1] : values_.size()); j++) {
result[i] += values_[j] * x[indices_[j]];
}
}
return result;
}
// 稀疏度计算
float getSparsity() const {
return static_cast(values_.size()) / (rows_ * cols_);
}
};
// 稀疏神经网络优化
class SparseNeuralNetwork {
public:
// 剪枝稀疏化
void pruneNetwork(float threshold) {
// 权重量化
for (auto& weight : weights_) {
if (std::abs(weight) < threshold) {
weight = 0.0f;
}
}
}
// 稀疏矩阵乘法
std::vector forward(
const std::vector& input) {
// 使用稀疏矩阵乘法
return sparseMatrix_.sparseMultiply(input);
}
};
异步执行利用 CUDA 流实现真正的并行推理,最大化 GPU 利用率。
异步执行实现
class AsyncInferenceEngine {
private:
std::vector streams_;
std::vector contexts_;
std::queue taskQueue_;
std::thread processingThread_;
std::mutex mutex_;
std::condition_variable cv_;
public:
AsyncInferenceEngine(int numStreams = 4) {
// 创建 CUDA 流
for (int i = 0; i < numStreams; i++) {
cudaStream_t stream;
cudaStreamCreate(&stream);
streams_.push_back(stream);
// 创建执行上下文
IExecutionContext* context = engine_->createExecutionContext();
contexts_.push_back(context);
}
// 启动处理线程
processingThread_ = std::thread(&AsyncInferenceEngine::processTasks, this);
}
~AsyncInferenceEngine() {
// 停止处理线程
{
std::lock_guard lock(mutex_);
stopProcessing_ = true;
}
cv_.notify_one();
processingThread_.join();
// 清理资源
for (auto& stream : streams_) {
cudaStreamDestroy(stream);
}
for (auto& context : contexts_) {
context->destroy();
}
}
// 异步提交推理任务
Future submitAsync(
const InferenceTask& task) {
auto promise = std::make_shared>();
auto future = promise->get_future();
// 添加到任务队列
{
std::lock_guard lock(mutex_);
taskQueue_.push(InferenceQueueItem{task, promise});
}
// 通知处理线程
cv_.notify_one();
return future;
}
// 处理任务
void processTasks() {
while (true) {
InferenceQueueItem item;
// 获取任务
{
std::unique_lock lock(mutex_);
cv_.wait(lock, [this] { return !taskQueue_.empty() || stopProcessing_; });
if (stopProcessing_ && taskQueue_.empty()) {
return;
}
item = taskQueue_.front();
taskQueue_.pop();
}
// 执行推理
executeTask(item);
}
}
// 执行任务
void executeTask(const InferenceQueueItem& item) {
// 选择可用的流和上下文
int streamIndex = getNextAvailableStream();
cudaStream_t stream = streams_[streamIndex];
IExecutionContext* context = contexts_[streamIndex];
// 执行推理
bool success = context->enqueueV2(
item.task.inputs.data(),
item.task.outputs.data(),
stream
);
// 设置结果
if (success) {
item.promise->set_value(InferenceResult{true, item.task.outputs});
} else {
item.promise->set_value(InferenceResult{false, {}});
}
}
};
完善的错误处理机制确保 TensorRT 的稳定性和可靠性。
错误处理策略
class TensorRTErrorHandler {
public:
// 错误类型枚举
enum class ErrorType {
kMEMORY_ERROR, // 内存错误
kCUDA_ERROR, // CUDA 错误
kINFERENCE_ERROR, // 推理错误
kMODEL_ERROR, // 模型错误
kCONFIG_ERROR // 配置错误
};
// 错误处理接口
class IErrorHandler {
public:
virtual ~IErrorHandler() = default;
virtual void handleError(
ErrorType type,
const std::string& message,
int code) = 0;
virtual void handleWarning(
const std::string& message,
int code) = 0;
};
// 错误处理器实现
class DefaultErrorHandler : public IErrorHandler {
public:
void handleError(ErrorType type,
const std::string& message,
int code) override {
std::cerr << "[ERROR] " << toString(type)
<< ": " << message
<< " (Code: " << code << ")" << std::endl;
// 错误恢复
switch (type) {
case ErrorType::kMEMORY_ERROR:
recoverFromMemoryError();
break;
case ErrorType::kCUDA_ERROR:
recoverFromCudaError();
break;
case ErrorType::kINFERENCE_ERROR:
recoverFromInferenceError();
break;
default:
std::cerr << "Unknown error type: "
<< static_cast(type) << std::endl;
}
}
void handleWarning(const std::string& message,
int code) override {
std::cerr << "[WARNING] " << message
<< " (Code: " << code << ")" << std::endl;
}
private:
std::string toString(ErrorType type) {
switch (type) {
case ErrorType::kMEMORY_ERROR: return "Memory";
case ErrorType::kCUDA_ERROR: return "CUDA";
case ErrorType::kINFERENCE_ERROR: return "Inference";
case ErrorType::kMODEL_ERROR: return "Model";
case ErrorType::kCONFIG_ERROR: return "Configuration";
default: return "Unknown";
}
}
void recoverFromMemoryError() {
// 释放不必要内存
cleanupUnusedMemory();
// 重新分配内存
reallocateMemory();
}
void recoverFromCudaError() {
// 重置 CUDA 设备
cudaDeviceReset();
// 重新初始化流
recreateStreams();
}
void recoverFromInferenceError() {
// 重新构建引擎
rebuildEngine();
// 重置执行上下文
resetExecutionContext();
}
};
};
TensorRT 提供多种调试工具和技巧,帮助开发者优化性能和解决问题。
调试工具和技巧 ┌─────────────────────────────────────────────────────┐ │ 性能分析工具 │ ├─────────────────────────────────────────────────────┤ │ • Nsight Systems │ │ • Nsight Compute │ │ • TensorRT Profiler │ │ • CUDA Profiler │ │ │ │ 调试模式 │ ├─────────────────────────────────────────────────────┤ │ • 详细日志模式 │ │ • 内存调试模式 │ │ • 执行跟踪模式 │ │ • 精度验证模式 │ │ │ │ 常见问题 │ ├─────────────────────────────────────────────────────┤ │ • 内存不足错误 │ │ • 推理失败 │ │ • 精度问题 │ │ • 兼容性问题 │ │ │ │ 调试策略 │ ├─────────────────────────────────────────────────────┤ │ • 分步调试 │ │ • 性能基准测试 │ │ • 内存泄漏检测 │ │ • 多进程调试 │ └─────────────────────────────────────────────────────┘
性能分析帮助开发者理解推理瓶颈,优化模型和实现。
性能分析实现
class TensorRTProfiler {
private:
std::unordered_map layerProfiles_;
std::vector kernelProfiles_;
cudaEvent_t startEvent_, endEvent_;
public:
TensorRTProfiler() {
cudaEventCreate(&startEvent_);
cudaEventCreate(&endEvent_);
}
~TensorRTProfiler() {
cudaEventDestroy(startEvent_);
cudaEventDestroy(endEvent_);
}
// 开始分析
void beginLayer(const std::string& layerName) {
cudaEventRecord(startEvent_);
}
// 结束分析
void endLayer(const std::string& layerName) {
cudaEventRecord(endEvent_);
cudaEventSynchronize(endEvent_);
float elapsedTime;
cudaEventElapsedTime(&elapsedTime, startEvent_, endEvent_);
// 更新层配置文件
auto& profile = layerProfiles_[layerName];
profile.totalTime += elapsedTime;
profile.callCount++;
profile.maxTime = std::max(profile.maxTime, elapsedTime);
profile.minTime = std::min(profile.minTime, elapsedTime);
}
// 生成性能报告
PerformanceReport generateReport() const {
PerformanceReport report;
report.totalTime = 0.0f;
for (const auto& [layerName, profile] : layerProfiles_) {
LayerReport layerReport;
layerReport.name = layerName;
layerReport.totalTime = profile.totalTime;
layerReport.averageTime = profile.totalTime / profile.callCount;
layerReport.maxTime = profile.maxTime;
layerReport.minTime = profile.minTime;
layerReport.callCount = profile.callCount;
report.totalTime += profile.totalTime;
report.layers.push_back(layerReport);
}
// 排序层按时间
std::sort(report.layers.begin(), report.layers.end(),
[](const LayerReport& a, const LayerReport& b) {
return a.totalTime > b.totalTime;
});
return report;
}
// 识别瓶颈
std::vector identifyBottlenecks(
float threshold = 0.1f) const {
auto report = generateReport();
std::vector bottlenecks;
for (const auto& layer : report.layers) {
float layerRatio = layer.totalTime / report.totalTime;
if (layerRatio > threshold) {
bottlenecks.push_back(layer.name);
}
}
return bottlenecks;
}
};
TensorRT 的最佳实践确保高性能、稳定性和可维护性。
构建优化建议 1. 选择合适的精度 ├─ FP16: 平衡性能和精度 ├─ INT8: 最高性能,需校准 └─ FP32: 最高精度,性能较低 2. 优化配置 ├─ 合理设置批处理大小 ├─ 充分利用工作空间 └─ 启用层融合优化 3. 内存管理 ├─ 使用内存池 ├─ 避免频繁分配 └─ 启用内存共享 4. 错误处理 ├─ 完善的错误检查 ├─ 优雅的错误恢复 └─ 详细的日志记录
执行优化建议 1. 异步执行 ├─ 多流并行 ├─ 重叠计算和传输 └─ 批处理优化 2. 缓存机制 ├─ 引擎缓存 ├─ 模型缓存 └─ 结果缓存 3. 性能监控 ├─ 实时性能分析 ├─ 资源使用监控 └─ 瓶颈识别 4. 扩展性 ├─ 水平扩展 ├─ 动态负载均衡 └─ 容错机制
TensorRT 的学习资源和进阶内容。
扩展学习资源 ┌─────────────────────────────────────────────────────┐ │ 官方文档 │ ├─────────────────────────────────────────────────────┤ │ • TensorRT Developer Guide │ │ • TensorRT API Reference │ │ • TensorRT Release Notes │ │ • TensorRT Samples │ │ │ │ 深度学习框架 │ ├─────────────────────────────────────────────────────┤ │ • TensorFlow + TensorRT │ │ • PyTorch + TensorRT │ │ • ONNX Runtime Integration │ │ • Custom Plugin Development │ │ │ │ 性能优化 │ ├─────────────────────────────────────────────────────┤ │ • CUDA Programming Guide │ │ • Tensor Core Programming │ │ • Memory Optimization Techniques │ │ • Multi-GPU Programming │ │ │ │ 实践案例 │ ├─────────────────────────────────────────────────────┤ │ • Computer Vision Applications │ │ • Natural Language Processing │ │ • Recommendation Systems │ │ • Real-time Inference Systems │ └─────────────────────────────────────────────────────┘
TensorRT 是 NVIDIA 推出的高性能深度学习推理优化工具包,通过多阶段优化技术实现极致的推理性能。
TensorRT 将持续推动 AI 推理性能边界,为下一代 AI 应用提供强大的计算基础设施。