tensorrt基本流程

复制代码
构建四件套:Builder + Network + Parser + Config → Engine
推理三件套:Runtime + Engine + Context → 结果

构建阶段(离线):

bash 复制代码
auto builder = createInferBuilder(logger);
auto network = builder->createNetworkV2(...);
auto parser = createParser(*network, logger);
parser->parseFromFile("model.onnx", ...);
auto config = builder->createBuilderConfig();
config->setFlag(kFP16);
config->setMaxWorkspaceSize(1_GiB);
auto engine = builder->buildSerializedNetwork(*network, *config);
saveToFile(engine, "model.engine");

推理阶段(在线):

bash 复制代码
auto runtime = createInferRuntime(logger);
auto engine = runtime->deserializeCudaEngine(data, size);
auto context = engine->createExecutionContext(); // 每线程一个
// 分配 buffer → memcpy in → execute → memcpy out

TensorRT 的执行流程是高性能推理的核心。下面我将以 C++ 中解析 ONNX 模型 → 生成 Engine → 加载并推理 为例,完整、清晰地解释 TensorRT 的标准工作流程,包括每个阶段的作用和创建方式。

🧩 整体流程概览(两阶段)

TensorRT 推理分为两个独立阶段:

阶段 目的 是否必须每次运行? 输出
1. 构建阶段(Build Phase) 将 ONNX 转为优化后的 TensorRT Engine ❌ 只需一次(可离线) .engine 文件
2. 推理阶段(Inference Phase) 加载 Engine,执行前向计算 ✅ 每次推理都要 推理结果

💡 最佳实践:构建一次,推理多次(Engine 可序列化保存,避免重复构建)


🔧 第一阶段:构建 Engine(从 ONNX 到 .engine)

步骤 1:创建 Builder

cpp 复制代码
auto builder = std::unique_ptr<nvinfer1::IBuilder>(
    nvinfer1::createInferBuilder(logger)
);
  • 作用:TensorRT 的"总工程师",负责创建网络和配置优化。
  • 参数 :需要一个 ILogger(日志回调)。

步骤 2:创建 Network Definition

cpp 复制代码
const auto explicitBatch = 1U << static_cast<uint32_t>(
    nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH
);
auto network = std::unique_ptr<nvinfer1::INetworkDefinition>(
    builder->createNetworkV2(explicitBatch)
);
  • 作用:定义计算图(节点、输入输出、算子)。
  • 注意 :ONNX 使用显式 batch,必须开启 kEXPLICIT_BATCH
  • 💡 几乎所有现代模型(ONNX/TensorFlow/PyTorch 导出)都必须使用 kEXPLICIT_BATCH!
  • 告诉 TensorRT:batch 维度是张量 shape 的一部分(即 shape 形如 [N, C, H, W])
    这是 ONNX、PyTorch 导出模型的标准格式

步骤 3:创建 Parser 并解析 ONNX

cpp 复制代码
auto parser = std::unique_ptr<nvonnxparser::IParser>(
    nvonnxparser::createParser(*network, logger)
);

parser->parseFromFile("model.onnx", 
    static_cast<int>(nvinfer1::ILogger::Severity::kWARNING)
);
  • 作用 :将 ONNX 文件解析成 TensorRT 的 INetworkDefinition
  • 依赖库 :需要链接 nvonnxparser

步骤 4:配置 Builder Config

cpp 复制代码
auto config = std::unique_ptr<nvinfer1::IBuilderConfig>(
    builder->createBuilderConfig()
);
config->setMaxWorkspaceSize(1 << 30); // 1GB
config->setFlag(nvinfer1::BuilderFlag::kFP16); // 启用 FP16
  • 作用 :设置优化策略:
    • 工作空间大小(影响 kernel 选择)
    • 精度模式(FP32 / FP16 / INT8)
    • 动态 shape(如果需要)

动态batch推理(看需求设置)

bash 复制代码
auto profile = builder->createOptimizationProfile();
profile->setDimensions("input", OptProfileSelector::kMIN, Dims4{1, 3, 640, 640});
profile->setDimensions("input", OptProfileSelector::kOPT, Dims4{4, 3, 640, 640});
profile->setDimensions("input", OptProfileSelector::kMAX, Dims4{16, 3, 640, 640});
config->addOptimizationProfile(profile);
config->setFlag(nvinfer1::BuilderFlag::kFP16);

步骤 5:构建 Engine

cpp 复制代码
auto plan = std::unique_ptr<nvinfer1::IHostMemory>(
    builder->buildSerializedNetwork(*network, *config)
);
  • 作用:执行图优化(层融合、精度校准、内核选择等),生成可执行计划。
  • 输出IHostMemory 是序列化的 Engine(二进制 blob)。

步骤 6:保存 Engine 到文件(可选但推荐)

cpp 复制代码
std::ofstream engineFile("model.engine", std::ios::binary);
engineFile.write(static_cast<char*>(plan->data()), plan->size());
engineFile.close();
  • 好处:下次直接加载,省去构建时间(构建可能耗时几十秒)。

▶️ 第二阶段:加载 Engine 并推理

步骤 1:读取 Engine 文件

cpp 复制代码
std::ifstream file("model.engine", std::ios::binary);
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<char> engineData(size);
file.read(engineData.data(), size);
file.close();

步骤 2:创建 Runtime 并反序列化 Engine

cpp 复制代码
auto runtime = std::unique_ptr<nvinfer1::IRuntime>(
    nvinfer1::createInferRuntime(logger)
);

auto engine = std::unique_ptr<nvinfer1::ICudaEngine>(
    runtime->deserializeCudaEngine(engineData.data(), size)
);
  • Runtime:负责将序列化 Engine 加载到 GPU。
  • ICudaEngine:优化后的可执行模型(只读,线程安全)。

步骤 3:创建 Execution Context

cpp 复制代码
auto context = std::unique_ptr<nvinfer1::IExecutionContext>(
    engine->createExecutionContext()
);
  • 作用:持有推理时的状态(如中间张量内存)。
  • 注意每个线程应有自己的 IExecutionContext(非线程安全)。

步骤 4:准备输入/输出内存(GPU + CPU)

获取输入/输出绑定信息
cpp 复制代码
int inputIndex = engine->getBindingIndex("input");   // 绑定名来自 ONNX
int outputIndex = engine->getBindingIndex("output");

auto inputDims = context->getBindingDimensions(inputIndex);
auto outputDims = context->getBindingDimensions(outputIndex);
分配 GPU 内存
cpp 复制代码
void* buffers[2];
cudaMalloc(&buffers[inputIndex], volume(inputDims) * sizeof(float));
cudaMalloc(&buffers[outputIndex], volume(outputDims) * sizeof(float));
准备 CPU 输入数据
cpp 复制代码
std::vector<float> inputData(volume(inputDims));
// ... 填充 inputData ...
cudaMemcpy(buffers[inputIndex], inputData.data(), 
           volume(inputDims) * sizeof(float), cudaMemcpyHostToDevice);

步骤 5:执行推理

cpp 复制代码
bool status = context->executeV2(buffers);
if (!status) { /* handle error */ }
  • executeV2:同步执行推理(输入/输出指针数组)。
  • 也有异步版本 enqueueV2(配合 CUDA Stream)。

步骤 6:拷贝结果回 CPU

cpp 复制代码
std::vector<float> outputData(volume(outputDims));
cudaMemcpy(outputData.data(), buffers[outputIndex],
           volume(outputDims) * sizeof(float), cudaMemcpyDeviceToHost);

步骤 7:释放资源

cpp 复制代码
cudaFree(buffers[inputIndex]);
cudaFree(buffers[outputIndex]);
// unique_ptr 会自动释放 engine/context/runtime

📊 流程图总结

复制代码
[ONNX 文件]
     ↓
 Builder → Network → Parser → 解析 ONNX
     ↓
 BuilderConfig → 设置 FP16 / workspace
     ↓
 buildSerializedNetwork() → 生成序列化 Engine
     ↓
 保存为 .engine 文件(离线完成)

───────────────────────────────
[推理时]
     ↓
 Runtime ← deserializeCudaEngine(.engine)
     ↓
 ExecutionContext ← createExecutionContext()
     ↓
 分配 GPU 输入/输出缓冲区
     ↓
 cudaMemcpy (Host → Device)
     ↓
 executeV2() → 执行推理
     ↓
 cudaMemcpy (Device → Host)
     ↓
 得到结果

⚠️ 关键注意事项

  1. Engine 与硬件/驱动/TensorRT 版本绑定

    • 在 A100 上生成的 Engine 不能在 Jetson 上用
    • 升级驱动或 TRT 版本后需重新构建
  2. 动态 Shape 支持

    • 需在构建时设置 profile,推理时用 setBindingDimensions
  3. INT8 量化需要校准

    • 额外步骤:提供校准数据集,实现 IInt8Calibrator
  4. 多线程推理

    • 共享 ICudaEngine(线程安全)
    • 每个线程独占 IExecutionContext

✅ 总结

阶段 核心对象 作用
构建 IBuilder, INetworkDefinition, IParser 解析 ONNX,优化图,生成 Engine
推理 IRuntime, ICudaEngine, IExecutionContext 加载 Engine,分配内存,执行计算

🌟 记住:构建一次,推理千次;Engine 是性能的关键!

通过这种方式,TensorRT 能将 ONNX 模型加速数倍甚至数十倍,广泛应用于生产环境。希望这个详解对你有帮助!

相关推荐
_YiFei2 小时前
2026年度论文降重工具全维度评测|高效、合规、低重复率综合榜单
人工智能·深度学习
renhongxia12 小时前
从模仿到创造:具身智能的技能演化路径
人工智能·深度学习·神经网络·算法·机器学习·知识图谱
有Li3 小时前
基于几何映射的二维自然图像到四维fMRI脑图像的迁移学习/文献速递-大模型与图像分割在医疗影像中应用
人工智能·深度学习·文献·医学生
Flying pigs~~3 小时前
深度学习之循环神经网络RNN
人工智能·rnn·深度学习·自然语言处理·循环神经网络
ホロHoro3 小时前
深度学习路线
人工智能·深度学习
XuecWu34 小时前
Karpathy的AutoResearch与Gemini三层 Agent 架构后的相通设计逻辑
人工智能·深度学习·语言模型·自然语言处理
_小雨林4 小时前
Transformer模型、整体结构,编码器与解码器内部组成
人工智能·深度学习·transformer
放下华子我只抽RuiKe55 小时前
AI大模型开发-实战精讲:从零构建 RFM 会员价值模型(再进阶版:模拟数据 + 动态打分 + 策略落地)
大数据·人工智能·深度学习·elasticsearch·机器学习·搜索引擎·全文检索
V搜xhliang02465 小时前
世界模型、强化学习PPOSAC
人工智能·深度学习·机器学习·语言模型·自然语言处理