ONNX Runtime 微软的推理引擎 TensorRTNVIDIA GPU 上的深度学习推理*
GPU优化的极致性能推理编译器;二者可协同使用------ONNX Runtime通过"TensorRT Execution Provider"调用TensorRT底层,在保持跨平台能力的同时实现NVIDIA GPU上的最高推理速度。
ONNX Runtime:以ONNX格式为中间表示,支持CPU、NVIDIA CUDA、AMD ROCm、Intel OpenVINO、NPU等多种硬件后端,主打跨平台兼容性与部署灵活性,适合多设备统一推理。
TensorRT:NVIDIA专属的推理优化器和运行时,通过层融合、FP16/INT8精度校准、内核自动调优等激进编译优化,为NVIDIA GPU生成高度定制化引擎,实现最低延迟与最高吞吐。
协同作用:当ONNX Runtime配置TensorRTExecutionProvider时,它会将模型中TensorRT支持的子图自动交由TensorRT编译加速,不支持的部分回退到CUDA或CPU执行,兼顾性能接近原生TensorRT与代码/模型格式统一(.onnx
ONNX(Open Neural Network Exchange)不是某个公司的产品,而是一个开放标准。
发起方与治理
| 时间 | 事件 |
|---|---|
| 2017 年 | 微软 + Facebook(Meta) 联合发起 |
| 现在 | Linux Foundation AI & Data 托管,社区开源项目 |
所以 ONNX 本身不属于任何公司,是 Linux 基金会下的开放标准,微软和 Meta 仍是主要贡献者,但 AWS、NVIDIA、Intel、华为等都在参与。
ONNX Runtime 呢?
| 项目 | 归属 | 说明 |
|---|---|---|
| ONNX 格式标准 | Linux Foundation | 开放的模型交换格式 |
| ONNX Runtime | 微软 | 推理引擎,支持多种后端(CUDA/ROCm/DirectML/OpenVINO) |
ONNX Runtime 是微软开发的,但开源(MIT 协议),支持跨平台跨硬件。
简单区分
ONNX (.onnx) → 文件格式标准(类似 .jpg, .pdf)
ONNX Runtime → 微软的推理引擎(类似 TensorRT)
国产替代场景
如果你用华为昇腾、海光 DCU 等,路线是:
| 硬件 | 导出格式 | 推理引擎 |
|---|---|---|
| NVIDIA | ONNX / TensorRT | TensorRT / ONNX Runtime |
| 华为昇腾 | ONNX / MindIR | CANN + MindIE(昇腾专用,性能最好) |
| 海光 DCU | ONNX | ONNX Runtime(ROCm 后端) |
| 通用 | ONNX | ONNX Runtime(最省心) |
TensorRT 是 NVIDIA 的。
2016 年发布,专门用于优化 NVIDIA GPU 上的深度学习推理。核心功能:
- 模型量化(FP32 → FP16/INT8)
- 层融合(把 Conv+BN+ReLU 合并成一个 kernel)
- 自动选择最优 CUDA kernel
- 支持 ONNX、PyTorch、TensorFlow 模型导入
如果你不是 NVIDIA 卡
| 厂商 | 对应推理优化工具 |
|---|---|
| AMD | MIOpen / ROCm(生态弱很多,没有 TensorRT 级别的专用推理引擎) |
| Intel | OpenVINO(支持 CPU/GPU/NPU,跨平台) |
| 国产(华为昇腾) | CANN + MindIE |
| 海光 DCU | 兼容 ROCm,用 MIOpen |
| 摩尔线程 | 兼容 CUDA,部分支持 TensorRT |
| 通用跨平台 | ONNX Runtime 、TVM 、MLIR |
一个替代方案:ONNX Runtime
如果你未来可能换卡(比如国产替代),建议用 ONNX Runtime:
python
# 导出 ONNX
torch.onnx.export(model, z_sample, "dcgan.onnx",
input_names=["z"], output_names=["image"])
# 推理(支持 CUDA/ROCm/OpenVINO 后端)
import onnxruntime as ort
session = ort.InferenceSession("dcgan.onnx",
providers=['CUDAExecutionProvider'])
速度接近 TensorRT(差 10~20%),但跨硬件。
天数智芯(Iluvatar CoreX),路线和 NVIDIA 比较接近:
天数智芯生态
| 项目 | 说明 |
|---|---|
| 架构 | 自研 GPU,兼容 CUDA 生态 |
| 软件栈 | IxRT (对标 TensorRT)+ IxDNN(对标 cuDNN) |
| PyTorch | 通过 CUDA 兼容层运行,模型迁移成本低 |
| ONNX | 支持 ONNX Runtime 或转 IxRT |
你的 DCGAN 部署建议
方案一:CUDA 兼容层(最快上手)
python
# 天数智芯上直接跑,PyTorch 代码基本不用改
# 安装天数智芯的 PyTorch 适配包
import torch
# 自动映射到天数智芯 GPU
model = model.cuda()
问题: 兼容层有性能损耗,大概 NVIDIA 同规格卡的 60~80%。
方案二:IxRT 推理(性能最优)
python
# 导出 ONNX,再用 IxRT 编译优化
torch.onnx.export(model, z_sample, "dcgan.onnx")
# 用天数智芯工具链
# ixrtexec --onnx=dcgan.onnx --saveEngine=dcgan.ixrt
效果: 接近硬件极限,和 TensorRT 思路一样(层融合、量化、自动调优)。
方案三:ONNX Runtime(跨平台保险)
python
import onnxruntime as ort
# 天数智芯提供 EP(Execution Provider)
session = ort.InferenceSession("dcgan.onnx",
providers=['IxRTExecutionProvider'])
好处: 万一要换卡(比如同时试华为昇腾),ONNX 模型不用重新导出。
对比
| 方案 | 性能 | 迁移成本 | 灵活性 |
|---|---|---|---|
| CUDA 兼容层 | 70% | 极低 | 中 |
| IxRT | 95%+ | 中 | 低(绑死天数) |
| ONNX Runtime + IxRT EP | 85% | 低 | 高 |
建议路线
- 开发阶段:PyTorch CUDA 兼容层,快速验证
- 部署阶段:导出 ONNX → IxRT 优化,或者 ONNX Runtime + IxRT EP
CUDA Graph 简明详解,推理加速,但是没有TensorRT,ONNX Runtime效果好
CUDA Graph 是 CUDA 10+ 推出的任务图执行机制 ,核心解决频繁小Kernel、数据拷贝、同步带来的CPU-GPU交互开销,大幅提升短任务流水线性能。
一、核心原理
传统CUDA流程:CPU逐个向Stream提交任务(Kernel、Memcpy、同步),每次提交都有CPU开销,大量细碎任务时延迟显著。
CUDA Graph 分为两步:
- 捕获(Capture) :记录一条/多条Stream上的所有操作、依赖关系,生成有向无环图(DAG);
- 执行(Launch) :一次性把整个图提交给GPU,CPU仅一次调用,GPU自主按依赖调度执行,消除反复提交开销。
适用场景:重复执行的固定任务流(推理、循环计算、固定数据流转)。
二、关键优势
- 降低CPU开销 :图构建后反复执行,省去数万次
cudaLaunchKernel/内存拷贝的CPU调用; - GPU调度更高效:硬件级调度任务与依赖,Stream间并行/串行更紧凑;
- 延迟降低、吞吐提升:对小Kernel、低计算密度任务增益最明显。
三、基础使用流程(标准API)
1. 四大核心对象
cudaGraph_t:图本体cudaGraphExec_t:可执行图(编译优化后的图,反复执行用它)cudaGraphNode_t:图节点(Kernel、Memcpy、同步、空节点等)cudaStreamCaptureMode:捕获模式
2. 标准五步代码流程
cpp
// 1. 开始捕获 Stream
cudaStreamBeginCapture(stream, cudaStreamCaptureModeGlobal);
// -------- 此处是要录制的CUDA任务 --------
kernel<<<grid, block, 0, stream>>>(d_in, d_out);
cudaMemcpyAsync(h_out, d_out, size, cudaMemcpyDeviceToHost, stream);
// --------------------------------------
// 2. 结束捕获,生成 cudaGraph_t
cudaGraph_t graph;
cudaStreamEndCapture(stream, &graph);
// 3. 实例化(编译)为可执行图 cudaGraphExec_t
cudaGraphExec_t graphExec;
cudaGraphInstantiate(&graphExec, graph, nullptr, nullptr, 0);
// 4. 反复执行图(性能核心)
for (int i = 0; i < loop_times; i++) {
cudaGraphLaunch(graphExec, stream);
}
// 5. 资源释放
cudaGraphExecDestroy(graphExec);
cudaGraphDestroy(graph);
四、两种捕获模式
- Global(全局,默认)
捕获当前Stream + 所有关联Stream的操作,适合多Stream协同流水线。 - Relaxed(宽松)
仅捕获目标Stream,跨Stream操作不纳入,隔离性更强。
五、支持的节点类型
- Kernel节点:GPU核函数(最常用)
- Memcpy节点 :
cudaMemcpyAsync设备/主机间拷贝 - Event节点 :
cudaEventRecord/cudaEventWait(依赖控制) - Host节点:CPU回调函数(异步执行)
- Empty节点:纯依赖占位,用于手动编排执行顺序
六、重要限制 & 避坑
- 不支持动态流
录制阶段不能有不确定分支、动态Kernel参数、动态内存分配 (cudaMalloc/free禁止在捕获区间内)。 - 参数更新
若每次执行输入地址/核函数参数变化 ,需用 Graph Update 动态修改节点参数,不用重新捕获。 - 同步限制
捕获区间内慎用阻塞式同步(cudaStreamSynchronize),优先用Event异步依赖。 - 首次实例化有开销
图编译(Instantiate)耗时较高,必须多次循环执行才划算,单次任务不建议用。
七、常见优化用法
1. 动态更新节点参数(高频需求)
推理场景下输入数据地址每次变化,无需重录图:
- 获取Kernel节点 →
cudaGraphExecUpdate修改参数/网格/线程配置。
2. 多图/多Stream并行
多个独立CUDA Graph 提交到不同Stream,实现GPU多流水线并行。
3. 结合 TensorRT
TensorRT 推理后端默认启用CUDA Graph,是大模型推理低延迟的关键技术之一。
八、适用 & 不适用场景
✅ 适合
- AI模型推理、循环迭代计算
- 大量小Kernel、频繁内存异步拷贝
- 固定执行流程、循环次数多的任务
❌ 不适合
- 单次执行、流程动态变化(分支/循环不确定)
- 录制区间内频繁分配/释放显存
- 复杂阻塞同步逻辑
补充:PyTorch 中使用 CUDA Graph
PyTorch 原生封装,极简调用:
python
import torch
stream = torch.cuda.Stream()
g = torch.cuda.CUDAGraph()
# 预热
with torch.cuda.stream(stream):
# 运行一次预热
pass
# 捕获计算图
with torch.cuda.graph(g, stream=stream):
# 你的前向推理/计算逻辑
pass
# 反复执行
for _ in range(1000):
g.replay()
可以用,但有前提:训练过程必须"形状固定、流程稳定",不是所有训练都适合。
一、结论先说
- ✅ 完全可以用于训练:前向、反向、优化器一步到位,都能包进 CUDA Graph。
- ✅ 适用场景:LLM 微调(LoRA)、固定 batch/固定 shape 的分类/检测/推荐模型、小batch高频迭代。
- ❌ 不适合:动态 shape(每次batch尺寸/分辨率变)、分支结构多变、频繁显存分配/释放、调试阶段。
二、训练里能加速什么
训练一次迭代 = 前向 → 损失 → 反向 → 梯度更新。
传统:每一步都要 CPU 发 kernel,几千次小kernel,CPU开销巨大 。
CUDA Graph:一次捕获整迭代,之后反复 replay ,CPU 只发一次请求,kernel launch 开销几乎归零。
实测:小batch(≤32)训练,速度提升 10--30%,GPU 利用率更高。
三、PyTorch 训练最简示例(可跑)
python
import torch
import torch.nn as nn
# 1. 模型与数据
model = nn.Linear(1024, 1024).cuda()
loss_fn = nn.MSELoss().cuda()
opt = torch.optim.Adam(model.parameters(), lr=1e-3)
# 固定shape输入(必须固定!)
bs, dim = 32, 1024
static_x = torch.randn(bs, dim, device="cuda")
static_y = torch.randn_like(static_x)
# 2. 预热(必须!让所有lazy init完成)
for _ in range(3):
opt.zero_grad()
out = model(static_x)
loss = loss_fn(out, static_y)
loss.backward()
opt.step()
# 3. 捕获训练图
g = torch.cuda.CUDAGraph()
with torch.cuda.graph(g):
opt.zero_grad()
out = model(static_x)
loss = loss_fn(out, static_y)
loss.backward()
opt.step()
# 4. 训练循环(直接 replay,极快)
for i in range(1000):
# 刷新输入(地址不变,内容可改)
static_x.copy_(torch.randn_like(static_x))
static_y.copy_(torch.randn_like(static_y))
g.replay() # 一次launch,跑完整个迭代
if i % 100 == 0:
print(loss.item())
四、关键限制(训练必看)
- Tensor shape 必须固定
每次迭代输入/权重/梯度 shape 不能变,否则图无法复用。 - 不能有动态控制流
捕获区间内不能有if/else、while、动态cudaMalloc。 - 输入地址要固定
不能每次迭代新建 tensor,要用copy_复用同一块显存。 - 调试不方便
图执行时 debug 断点、print不易用,建议 eager 调试、graph 训练。
五、大模型训练怎么用(LLM)
- 整迭代捕获:小模型、单卡、固定 batch。
- 分层捕获:Megatron-LM/Transformer Engine 对每一层单独建图,支持流水线并行。
- LoRA 微调最香:主干冻结、仅LoRA训练,shape 固定、收益极高。
六、什么时候别用
- 动态尺寸(如NLP变长序列、检测多尺度)。
- 训练初期调参、频繁改模型结构。
- 显存紧张(graph 会占用额外显存存中间状态)。
七、一句话总结
能用于训练,且在固定shape、小batch、高频迭代场景下提速明显;但要接受"静态图"约束,动态场景不适合。
先给你一句话结论:
- ONNX Runtime:可以用来训练(支持训练) ,但不是"主训练框架",而是推理+训练加速引擎。
- TensorRT:不能做常规训练(只有推理) ,只能做和推理相关的量化感知训练(QAT)/蒸馏/稀疏 等辅助训练,不能从零训练或完整微调。
下面分开讲清楚。
一、ONNX Runtime(ORT):能训练,而且是正经训练加速
1. 官方定位
- 本来是推理引擎
- 从 v1.10(2021) 开始正式支持 ORT Training
- 口号:inference + training engine,兼顾部署和训练加速
2. 能做什么训练
- ✅ PyTorch 模型微调/预训练(用 ORTModule)
- 只需改一行:
model = ORTModule(model) - 前向、反向、优化器全部走 ORT,速度比原生 PyTorch 快 1.3--1.5 倍
- 只需改一行:
- ✅ Hugging Face 模型训练(Optimum + ORT)
ORTTrainer替换Trainer,训练时间减少 35%+
- ✅ 端侧训练(On-Device Training)
- 手机/嵌入式设备上做小模型微调
- ✅ 支持多 GPU、DeepSpeed、混合精度
3. 不能做什么
- ❌ 不能完全替代 PyTorch/TensorFlow 写新模型
- ❌ 动态控制流(if/else、动态 shape)支持有限,和 CUDA Graph 类似
4. 一句话总结
ORT 可以训练,适合加速现有模型的微调/预训练,尤其 LLM、Transformer 类。
二、TensorRT:只能推理,不能做常规训练
1. 官方定位
- 纯推理引擎 :只负责把训练好的模型跑快
- 没有反向传播、没有优化器、不能从零训练
2. 唯一沾边的"训练":QAT(量化感知训练)
- TensorRT 自己不训练
- 提供 Model Optimizer :在 PyTorch 里做 QAT、稀疏、蒸馏,让模型更好部署到 TensorRT
- 流程:PyTorch 做 QAT → 导出 ONNX → TensorRT 编译推理
3. 能不能做微调?
- ❌ 不能:没有反向传播,没有梯度更新
- ❌ 不能替代 PyTorch 做任何完整训练/微调
4. 一句话总结
TensorRT 只能推理,不能训练;QAT 是 PyTorch 里的训练,不是 TensorRT 训练。
三、和 CUDA Graph 的关系(你之前问的)
- CUDA Graph :PyTorch 里训练/推理都能用,省 CPU 开销
- ORT :可以结合 CUDA Graph,训练推理都更快
- TensorRT :内部自带类 CUDA Graph 优化,但你看不到,也不能用来训练
四、怎么选(快速建议)
- 你要训练/微调 :用 PyTorch + ORT(加速)
- 你要部署推理 :用 TensorRT(最快) 或 ORT(跨平台)
- 你要训练+部署一套流程 :ORT 全链路最省事