2. 加载ONNX模型并获取输入输出信息

任务目标

使用ONNX Runtime C++ API加载一个ONNX格式的模型文件,解析模型的计算图,并打印所有输入/输出张量的名称、形状和数据类型。本案例聚焦于模型加载与元信息解析,不涉及推理执行。

环境依赖

  • ONNX Runtime库(版本≥1.15,支持C++接口)
  • C++17编译器
  • 示例模型:可从ONNX Model Zoo下载,或使用下方代码生成的简易模型

关键完整代码

#include <onnxruntime_cxx_api.h>
#include <iostream>
#include <vector>
#include <string>

void PrintTensorInfo(const std::string& prefix,
                     const std::vector<Ort::AllocatedStringPtr>& names,
                     const std::vector<std::vector<int64_t>>& shapes,
                     const std::vector<ONNXTensorElementDataType>& types) {
    for (size_t i = 0; i < names.size(); ++i) {
        std::cout << prefix << "[" << i << "] name: " << names[i].get()
                  << ", shape: [";
        for (size_t j = 0; j < shapes[i].size(); ++j) {
            std::cout << shapes[i][j];
            if (j + 1 < shapes[i].size()) std::cout << ", ";
        }
        std::cout << "], type: " << Ort::DataTypeToName(types[i]) << std::endl;
    }
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <model.onnx>" << std::endl;
        return 1;
    }

    // 初始化环境(必须保持存活直到所有会话结束)
    Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "model-info");
    Ort::SessionOptions session_options;
    session_options.SetIntraOpNumThreads(1);

    // 加载模型
    Ort::Session session(env, argv[1], session_options);

    // 获取输入信息
    Ort::AllocatorWithDefaultOptions allocator;
    auto input_names = session.GetInputNamesAllocated(allocator);
    auto input_shapes = session.GetInputShapes();
    auto input_types = session.GetInputTypes();

    // 获取输出信息
    auto output_names = session.GetOutputNamesAllocated(allocator);
    auto output_shapes = session.GetOutputShapes();
    auto output_types = session.GetOutputTypes();

    std::cout << "Model loaded successfully!" << std::endl;
    std::cout << "Input count: " << input_names.size() << std::endl;
    PrintTensorInfo("Input ", input_names, input_shapes, input_types);

    std::cout << "Output count: " << output_names.size() << std::endl;
    PrintTensorInfo("Output", output_names, output_shapes, output_types);

    return 0;
}

编译与运行

# 假设ONNX Runtime已安装到/usr/local/onnxruntime
g++ -std=c++17 model_info.cpp -o model_info \
    -I/usr/local/onnxruntime/include \
    -L/usr/local/onnxruntime/lib \
    -lonnxruntime

# 运行(替换为实际模型路径)
./model_info /path/to/your/model.onnx

验证方法

  1. 程序退出码为0,且输出以Model loaded successfully!开头。
  2. 打印的输入/输出名称与模型文件中的实际名称一致(可用Python onnx库交叉验证:onnx.load(path)后检查graph.input/output)。
  3. 形状信息中动态维度(如-1)被正确显示,数据类型名称(如tensor(float))与ONNX定义匹配。

常见问题

  • 链接错误:确保编译时-L指向包含libonnxruntime.so的目录,且运行时通过LD_LIBRARY_PATH指定动态库路径。
  • 模型加载失败:检查模型路径是否正确,以及模型是否为有效的ONNX格式(可用onnx.checker验证)。
  • 动态形状:如果模型包含动态轴,形状中会显示-1,这是正常行为,表示该维度在推理时才确定。