C++可直接调用ONNX Runtime实现高性能轻量部署,需严格匹配模型输入输出名称、shape与dtype,正确管理内存并配置执行提供者与优化选项。

可以直接用 C++ 调用 ONNX Runtime 进行模型推理,无需 Python 中转,性能高、部署轻量。关键在于正确加载模型、匹配输入输出张量形状与数据类型,并避免内存生命周期错误。
ONNX Runtime C++ API 初始化和会话创建
必须显式设置 Ort::Env 和 Ort::SessionOptions,否则默认行为可能触发调试日志或禁用优化。Windows 下若链接失败,大概率是没正确导入 onnxruntime.lib(不是 DLL)或 ABI 不匹配(如 /MD 与 /MT 混用)。
-
Ort::Env建议用ORT_LOGGING_LEVEL_WARNING避免刷屏 - 启用图优化:调用
session_options.SetGraphOptimizationLevel(ORT_ENABLE_ALL) - CUDA 执行提供者需手动注册:
OrtSessionOptionsAppendExecutionProvider_CUDA(options, 0),且必须在Ort::Session构造前完成 - Linux 下注意
LD_LIBRARY_PATH包含libonnxruntime.so路径
输入张量构造与内存管理
ONNX Runtime 不接管用户分配的内存,Ort::Value::CreateTensor 的第 4 个参数(data pointer)必须保证在整个 Run() 调用期间有效。常见崩溃源于栈内存传入或提前 free()。
- 推荐用
std::vector分配输入数据,再用.data()传指针 - 输入 shape 必须与模型期望完全一致,包括 batch 维度 —— 即使只推一个样本也要是
{1, 3, 224, 224},不能是{3, 224, 224} - 数据排布默认是 NCHW;若模型导出为 NHWC,需在预处理时重排,或用
Ort::Value::CreateTensor指定Ort::MemoryInfo::CreateCpu(..., OrtArenaAllocator)并自行处理 layout - 图像归一化必须与训练时一致:例如
(pixel - [123.675, 116.28, 103.53]) / [58.395, 57.12, 57.375],顺序错会导致输出全零
运行推理并读取输出结果
session.Run() 返回的是 std::vector<:value>,每个元素对应一个输出节点。直接调用 .GetTensorData 得到指针,但必须先确认输出 shape 和数据类型,否则越界读写。
立即学习“C++免费学习笔记(深入)”;
- 用
output_values[0].GetTensorTypeAndShapeInfo().GetShape()检查维度,比如分类模型常为{1, 1000} - 用
output_values[0].GetTensorTypeAndShapeInfo().GetElementType()确认是否为ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT - 不要假设输出名是
"output"—— 查看模型用netron或onnx.shape_inference.infer_shapes()确认实际 output name - 若输出是
int64(如 token ids),需用.GetTensorData,混用类型会读出垃圾值()
Ort::Session session(env, L"model.onnx", session_options); std::vectorinput_names = {"input"}; std::vector output_names = {"output"}; std::vector
input_shape = {1, 3, 224, 224}; std::vector input_tensor_values(1 3 224 * 224, 0.0f); // ... 填充 input_tensor_values auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault); auto input_tensor = Ort::Value::CreateTensor
( memory_info, input_tensor_values.data(), input_tensor_values.size(), input_shape.data(), input_shape.size()); auto output_tensors = session.Run( Ort::RunOptions{nullptr}, input_names.data(), &input_tensor, 1, output_names.data(), 1 );
float* output_data = output_tensors[0].GetTensorData
(); std::vector output_shape = output_tensors[0].GetTensorTypeAndShapeInfo().GetShape();
最易被忽略的是:模型输入/输出名称、shape、dtype 三者必须与 ONNX 文件定义严格一致,任何一项不匹配都会导致静默错误(如输出全零)或段错误。建议首次部署时用 Python 的 onnxruntime.InferenceSession 同样输入跑一遍,比对输出数值和 shape,再迁移到 C++。











