ONNX Runtime CUDA Provider概述

1. ONNX Runtime CUDA Provider概述

1.1. 它是什么
ONNX Runtime(ORT)是一个高性能推理引擎,CUDA Provider 是它的 GPU 执行后端之一,用来把 ONNX 模型的计算图映射到 NVIDIA GPU 上执行。简单说:模型还是 ONNX,但算力来自 CUDA。它并不是“重写模型”,而是把算子(Conv、Gemm、Attention 等)交给 CUDA / cuDNN / cuBLAS 去跑。

1.2. 它解决什么问题
CPU 推理在吞吐和延迟上很快会撞天花板。CUDA Provider 的价值在于:

  • 把计算密集型算子下放到 GPU
  • 复用 NVIDIA 已经高度优化的数学库
  • 在不改模型、不改业务代码的前提下获得数量级的性能提升

2. CUDA Provider 的架构与执行路径

2.1. 执行链路
从模型加载到 GPU 执行,大致是下面这条“流水线”:

flowchart LR
    A[ONNX Model] --> B[ONNX Runtime Session]
    B --> C[Graph Optimization]
    C --> D{Execution Provider选择}
    D -->|CPU| E[CPU EP]
    D -->|CUDA| F[CUDA EP]
    F --> G[CUDA Kernel]
    G --> H[cuBLAS / cuDNN / CUDA Runtime]
    H --> I[NVIDIA GPU]

关键点在 D:

  • ORT 会根据算子支持情况,把一部分图切给 CUDA EP
  • 不支持的算子会自动 fallback 到 CPU EP(这是很多性能坑的来源)

2.2. Graph Partition(图切分)
现实世界里几乎没有“100% GPU”的模型:

  • CUDA EP 支持算子 A、B、C
  • 模型里混进一个冷门算子 X
    结果就是:
  • A/B/C 在 GPU
  • X 在 CPU
  • 中间伴随 CPU ↔ GPU 的数据拷贝

3. CUDA Provider的核心依赖

3.1. 必要组件
CUDA Provider ≠ 只装一个 onnxruntime-gpu

你至少需要:

  • NVIDIA Driver(向下兼容 CUDA Runtime)
  • CUDA Toolkit(libcudart.so)
  • cuDNN(卷积、RNN、Attention 核心)
  • cuBLAS / cuBLASLt(矩阵乘法)

典型报错(你很可能见过):

  • libcufft.so not found
  • libcudnn.so.X: cannot open shared object file

这不是 ORT 的错,是动态链接库缺失

3.2. 版本匹配的“物理学”
一个实用规律:

  • NVIDIA Driver ≥ CUDA Runtime
  • CUDA Runtime ≈ ORT 构建时使用的版本

否则你会进入量子态:程序能启动,但在第一次 GPU 调用时坍塌。


4. CUDA Provider 的启用方式

4.1. Python

1
2
3
4
5
6
7
8
import onnxruntime as ort

sess = ort.InferenceSession(
"model.onnx",
providers=["CUDAExecutionProvider", "CPUExecutionProvider"]
)

print(sess.get_providers())

顺序很重要:

  • CUDA 放前面 = 优先用 GPU
  • CPU 放后面 = 兜底

4.2. 环境变量(调试必备)

1
2
export ORT_LOG_SEVERITY_LEVEL=0
export CUDA_VISIBLE_DEVICES=0

当你怀疑“是不是根本没跑在 GPU 上”,日志比直觉可靠


5. 性能与稳定性关键点

5.1. 常见性能陷阱

  • 算子不支持 → CPU/GPU 频繁拷贝
  • batch 太小 → GPU 吃不饱
  • IO 绑定不当 → Host 内存反复 memcpy

5.2. I/O Binding
ORT 支持直接把输入输出绑定到 GPU 内存,避免 Host ↔ Device 往返:

  • 延迟显著下降
  • 吞吐更稳定
    这在高 QPS 服务里是质变,不是优化。

6. CUDA Provider vs 其他 GPU EP

6.1. 对比关系

  • CUDA EP:通用、稳定、覆盖面广
  • TensorRT EP:极致性能,但构建复杂、算子限制多
  • ROCm EP:AMD GPU 世界线

经验法则:

  • 先 CUDA EP
  • 性能不够再 TensorRT
  • 别一上来就“核弹级优化”