1. 车载AI座舱环境搭建与交叉编译工具链配置

任务目标

在车载Linux系统(aarch64)上搭建AI推理环境,配置交叉编译工具链,并验证编译产物可在目标板上运行。本案例以ONNX Runtime为推理引擎,完成从x86主机交叉编译到aarch64目标板的完整闭环。

环境与依赖

  • 主机:x86_64 Ubuntu 20.04+,已安装cmake(≥3.18)、gcc、git
  • 目标板:aarch64 Linux(如NVIDIA Orin / 瑞芯微RK3588),root权限
  • 交叉编译器:gcc-aarch64-linux-gnu(主机执行 sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu)
  • 推理引擎:ONNX Runtime v1.17.0(预编译aarch64包)

实现步骤

1. 获取ONNX Runtime交叉编译包

# 在主机下载aarch64版本(无需自行编译,节省数小时)
wget https://github.com/microsoft/onnxruntime/releases/download/v1.17.0/onnxruntime-linux-aarch64-1.17.0.tgz
tar -xzf onnxruntime-linux-aarch64-1.17.0.tgz
# 解压后目录结构:onnxruntime-linux-aarch64-1.17.0/{include,lib}

2. 编写交叉编译测试程序

创建文件 infer_test.cpp,实现一个最小推理验证:加载ONNX模型,执行一次前向计算,输出结果维度。

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

int main() {
    // 创建环境(使用CPU EP)
    Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test");
    Ort::SessionOptions session_options;
    session_options.SetIntraOpNumThreads(1);

    // 加载模型(模型文件与可执行文件同目录)
    const char* model_path = "model.onnx";
    Ort::Session session(env, model_path, session_options);

    // 获取输入输出信息
    Ort::AllocatorWithDefaultOptions allocator;
    auto input_name = session.GetInputNameAllocated(0, allocator);
    auto output_name = session.GetOutputNameAllocated(0, allocator);

    // 构造输入数据(假设模型输入为 1x3x224x224 float)
    std::vector<int64_t> input_shape = {1, 3, 224, 224};
    std::vector<float> input_data(1 * 3 * 224 * 224, 0.5f);

    // 创建输入输出Tensor
    Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
    Ort::Value input_tensor = Ort::Value::CreateTensor<float>(
        memory_info, input_data.data(), input_data.size(), input_shape.data(), input_shape.size());

    // 运行推理
    const char* input_names[] = {input_name.get()};
    const char* output_names[] = {output_name.get()};
    auto output_tensors = session.Run(Ort::RunOptions{nullptr}, input_names, &input_tensor, 1, output_names, 1);

    // 获取输出维度
    auto output_info = output_tensors[0].GetTensorTypeAndShapeInfo();
    auto output_shape = output_info.GetShape();
    std::cout << "Inference OK. Output dims: ";
    for (auto d : output_shape) std::cout << d << " ";
    std::cout << std::endl;
    return 0;
}

3. 交叉编译

# 编译命令(使用aarch64交叉编译器)
aarch64-linux-gnu-g++ -std=c++17 infer_test.cpp \
    -I onnxruntime-linux-aarch64-1.17.0/include \
    -L onnxruntime-linux-aarch64-1.17.0/lib \
    -lonnxruntime -o infer_test_arm

# 确认产物架构
file infer_test_arm
# 预期输出:ELF 64-bit LSB executable, ARM aarch64

4. 部署到目标板并运行

# 将可执行文件、模型、动态库拷贝到目标板(假设目标板IP为192.168.1.100)
scp infer_test_arm model.onnx user@192.168.1.100:/home/user/
scp onnxruntime-linux-aarch64-1.17.0/lib/libonnxruntime.so* user@192.168.1.100:/home/user/

# 在目标板上执行
ssh user@192.168.1.100
export LD_LIBRARY_PATH=/home/user:$LD_LIBRARY_PATH
chmod +x infer_test_arm
./infer_test_arm

验证方法

  • 编译验证:file infer_test_arm 输出包含 ARM aarch64,说明交叉编译成功
  • 运行验证:目标板上执行后输出 Inference OK. Output dims: ...,且无动态库加载错误,说明推理环境搭建完成
  • 判定标准:程序返回码为0,输出维度与模型实际输出维度一致(例如分类模型输出 1 1000)

常见问题

  • 找不到libonnxruntime.so:确认目标板上 LD_LIBRARY_PATH 包含库所在目录,且库文件权限可读
  • 模型文件缺失:本案例需要准备一个ONNX格式模型(如ResNet50),放置在与可执行文件相同目录
  • GLIBC版本不兼容:若目标板系统较旧,需使用目标板自带编译器重新编译ONNX Runtime源码(耗时较长,非本案例范围)