环境准备:安装Python、CMake、编译器(GCC/Clang/MSVC)、依赖库(Protobuf、Eigen等)
核心原理:为什么环境准备是ONNX编译的第一道门槛
ONNX模型本身只是一个描述计算图的中间表示(IR),它并不包含可执行的算子实现。要让ONNX模型在特定硬件上高效运行,必须借助ONNX Runtime或自定义推理引擎,将ONNX图转换为可执行代码。这一过程涉及模型解析(读取onnx文件)、图优化(融合算子、消除冗余)、代码生成(生成C++或汇编)以及链接依赖库。因此,编译环境必须同时具备:
- Python:用于运行ONNX转换脚本、调用onnxoptimizer或onnxsim工具,以及生成C++代码前的模型预处理。
- CMake:跨平台构建系统,负责管理编译选项、查找依赖库、生成平台对应的构建文件(Makefile或Visual Studio工程)。
- C++编译器:将生成的C++代码编译为机器码。不同平台选择不同:Linux用GCC或Clang,Windows用MSVC,macOS可用Clang。
- 依赖库:Protobuf用于解析ONNX的protobuf格式;Eigen提供高性能线性代数运算;此外还可能需要abseil、re2、flatbuffers等。
这些组件之间存在严格的版本匹配关系。例如,ONNX Runtime 1.16要求Protobuf ≥ 3.20,而Eigen版本影响矩阵运算的SIMD优化路径。若版本不匹配,编译时会出现“找不到头文件”或“链接器无法解析符号”等错误。
版本匹配的核心原则:以ONNX Runtime的cmake/onnxruntime_protobuf.cmake中指定的版本为准,不要随意升级依赖库。若使用自定义算子,还需确保编译器支持C++17标准。
方法流程:分平台搭建编译环境
下面以Ubuntu 22.04、Windows 11和macOS 13三个典型平台为例,说明完整的环境搭建流程。每个平台都需要完成四步:安装基础工具、安装编译器、安装依赖库、验证环境。
1. Ubuntu 22.04(GCC + CMake + Protobuf + Eigen)
# 更新apt源
sudo apt update
# 安装基础工具
sudo apt install -y build-essential cmake git wget
# 安装Protobuf(Ubuntu仓库版本可能较旧,建议源码编译)
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.21.12/protobuf-cpp-3.21.12.tar.gz
tar -xzf protobuf-cpp-3.21.12.tar.gz
cd protobuf-3.21.12
./configure --prefix=/usr/local
make -j$(nproc)
sudo make install
sudo ldconfig
# 安装Eigen(仅头文件库)
sudo apt install -y libeigen3-dev
# 验证
gcc --version
cmake --version
protoc --version
ls /usr/include/eigen3/Eigen/Core
2. Windows 11(MSVC + CMake + vcpkg)
# 使用vcpkg管理依赖(推荐)
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg integrate install
# 安装依赖库
.\vcpkg install protobuf:x64-windows eigen3:x64-windows
# 安装Visual Studio 2022(需勾选“使用C++的桌面开发”工作负载)
# 安装CMake(可从官网下载,或通过Visual Studio Installer安装)
# 验证(在Developer PowerShell中)
cmake --version
cl.exe
protoc --version
3. macOS 13(Clang + Homebrew)
# 安装Homebrew(若未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安装工具
brew install cmake protobuf eigen
# 验证
clang --version
cmake --version
protoc --version
ls /opt/homebrew/include/eigen3/Eigen/Core
案例/场景:从零编译ONNX Runtime(CPU版)
假设我们需要在Ubuntu上编译ONNX Runtime的CPU版本,并启用自定义算子。完整命令如下:
# 1. 克隆ONNX Runtime源码
git clone --recursive https://github.com/microsoft/onnxruntime.git
cd onnxruntime
# 2. 创建build目录
mkdir build && cd build
# 3. 配置CMake(指定Python路径和Eigen路径)
cmake .. \
-Donnxruntime_ENABLE_PYTHON=OFF \
-Donnxruntime_BUILD_SHARED_LIB=ON \
-DCMAKE_PREFIX_PATH="/usr/local;/usr/include/eigen3" \
-DProtobuf_INCLUDE_DIR=/usr/local/include \
-DProtobuf_LIBRARY=/usr/local/lib/libprotobuf.so
# 4. 编译(使用8个线程)
make -j8
# 5. 验证生成的动态库
ls libonnxruntime.so
ldd libonnxruntime.so | grep -E "protobuf|eigen"
编译过程中,CMake会通过find_package(Protobuf)和find_package(Eigen3)自动查找依赖。若找不到,可手动指定Protobuf_DIR和Eigen3_DIR变量。
误区/复盘:常见环境配置错误及解决方案
| 错误现象 | 根本原因 | 解决方案 |
|---|---|---|
fatal error: google/protobuf/port_def.inc: No such file |
Protobuf头文件路径未正确包含 | 检查Protobuf_INCLUDE_DIR是否指向包含google/protobuf的目录 |
undefined reference to `google::protobuf::MessageLite::GetTypeName()' |
链接时找不到libprotobuf库 | 在CMakeLists.txt中添加target_link_libraries(your_target protobuf::libprotobuf) |
Eigen/Dense: No such file or directory |
Eigen未安装或路径错误 | Ubuntu安装libeigen3-dev后,头文件位于/usr/include/eigen3,需在CMake中添加include_directories(/usr/include/eigen3) |
MSVC编译时C2039: 'max' is not a member of 'std' |
Windows下Eigen与MSVC的兼容性问题 | 在代码前添加#define NOMINMAX,或使用#include <algorithm>并调用std::max |
CMake报Could NOT find Protobuf |
Protobuf未安装或CMake缓存未更新 | 运行sudo ldconfig后,删除build目录重新配置 |
重要提醒:不要混用系统自带的Protobuf和源码编译的Protobuf。若系统已安装libprotobuf-dev,建议先卸载,再统一使用源码编译版本,避免版本冲突导致ONNX Runtime运行时崩溃。
复盘:环境验证清单
完成安装后,建议按以下清单逐项验证,确保所有组件可用:
- Python版本:
python3 --version应输出3.8及以上。 - CMake版本:
cmake --version应输出3.18及以上。 - 编译器版本:GCC ≥ 9.4,Clang ≥ 12,MSVC ≥ 19.29。
- Protobuf版本:
protoc --version应输出libprotoc 3.21及以上。 - Eigen可用性:编译一个包含
#include <Eigen/Dense>的测试程序,确认无头文件错误。 - 链接测试:编译一个调用
google::protobuf::Message的简单程序,确认链接成功。
完成以上验证后,即可进入下一阶段的ONNX模型编译配置。环境准备阶段虽然繁琐,但一旦搭建完成,后续的编译工作将变得顺畅高效。建议将上述安装命令保存为脚本,便于在其他机器上快速复现环境。