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<float></float>分配输入数据,再用.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></:value>,每个元素对应一个输出节点。直接调用 .GetTensorData<float>()</float> 得到指针,但必须先确认输出 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<int64_t>()</int64_t>,混用类型会读出垃圾值
Ort::Session session(env, L"model.onnx", session_options);
std::vector<const char*> input_names = {"input"};
std::vector<const char*> output_names = {"output"};
<p>std::vector<int64_t> input_shape = {1, 3, 224, 224};
std::vector<float> input_tensor_values(1 <em> 3 </em> 224 * 224, 0.0f);
// ... 填充 input_tensor_values</p><p>auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
auto input_tensor = Ort::Value::CreateTensor<float>(
memory_info, input_tensor_values.data(), input_tensor_values.size(),
input_shape.data(), input_shape.size());</p><p>auto output_tensors = session.Run(
Ort::RunOptions{nullptr},
input_names.data(), &input_tensor, 1,
output_names.data(), 1
);</p><p>float* output_data = output_tensors[0].GetTensorData<float>();
std::vector<int64_t> output_shape = output_tensors[0].GetTensorTypeAndShapeInfo().GetShape();</p>最易被忽略的是:模型输入/输出名称、shape、dtype 三者必须与 ONNX 文件定义严格一致,任何一项不匹配都会导致静默错误(如输出全零)或段错误。建议首次部署时用 Python 的 onnxruntime.InferenceSession 同样输入跑一遍,比对输出数值和 shape,再迁移到 C++。











