第三章:环境搭建与工具链

好,咱们直接进入正题。环境搭建这事儿,说难不难,说简单吧,我见过太多人在这一步卡上好几天。说白了,就是要把交叉编译工具链、Docker镜像、还有各家硬件的SDK都伺候好。今天我就把这几年的经验捋一捋,帮你少走弯路。

3.1 交叉编译工具链——你的代码翻译官

先聊聊交叉编译。你想想看,你的开发机是x86架构,但目标硬件是ARM或者别的架构。代码在x86上编译出来,直接扔到ARM上跑?跑不了的。这时候就需要交叉编译工具链。

我个人习惯用Linaro提供的工具链,稳定且社区活跃。安装其实不复杂:

# 以aarch64为例
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
tar -xf gcc-linaro-*.tar.xz
sudo mv gcc-linaro-* /opt/
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin

嗯,这里要注意。环境变量最好写到 ~/.bashrc 里,不然每次开终端都要重新export。我在项目中遇到过有人忘了这步,编译出来的程序在板子上跑起来全是段错误,排查了半天才发现是工具链没配好。

避坑指南: 我曾经因为工具链版本不匹配,导致OpenCV的NEON优化指令集没生效。推理速度直接掉了30%。所以,一定要确认工具链版本跟目标硬件的内核版本、glibc版本对应得上。

3.2 Docker镜像构建——让环境可复现

Docker这东西,说白了就是给你的开发环境拍个快照。团队里有人环境坏了?把镜像拉下来重新跑一个容器就行。我建议每个项目都维护一个Dockerfile。

下面是我常用的一个基础Dockerfile模板:

FROM ubuntu:20.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
    build-essential \
    cmake \
    git \
    wget \
    python3-dev \
    python3-pip \
    libopencv-dev \
    && rm -rf /var/lib/apt/lists/*

# 安装交叉编译工具链
COPY gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz /opt/
RUN cd /opt && tar -xf gcc-linaro-*.tar.xz && \
    ln -s /opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu /opt/cross-toolchain

ENV PATH="/opt/cross-toolchain/bin:${PATH}"

WORKDIR /workspace

构建镜像时,我习惯加上 --no-cache 参数,避免缓存导致依赖没更新。你想想看,要是因为缓存问题导致编译失败,那多冤。

小技巧: 把工具链的压缩包直接COPY进镜像,比在Dockerfile里wget要快得多,而且不受网络波动影响。我在离线环境下就是这么干的。

3.3 目标硬件SDK安装——三巨头各有脾气

接下来是重头戏。Jetson、RK3588、Intel这三家,SDK安装方式完全不同。我一个个说。

3.3.1 NVIDIA Jetson 系列

Jetson用的是JetPack SDK。我个人建议用SDK Manager来装,图形化界面,省心。但如果你跟我一样喜欢命令行:

# 下载JetPack
wget https://developer.nvidia.com/embedded/jetpack

# 安装依赖
sudo apt-get install -y qemu-user-static

# 运行SDK Manager
./sdkmanager

安装完成后,你会得到CUDA、cuDNN、TensorRT这些好东西。我记得第一次在Jetson Nano上跑YOLOv5,TensorRT优化后推理速度从200ms降到了30ms,那感觉,真爽。

关键点: Jetson的交叉编译建议在x86主机上完成,然后用 scp 传到板子上。直接在板子上编译?嗯,除非你很有耐心。

3.3.2 Rockchip RK3588

RK3588的SDK叫RKNN Toolkit。这玩意儿有点特殊,它依赖Python环境。安装步骤:

# 创建虚拟环境
python3 -m venv rknn_env
source rknn_env/bin/activate

# 安装RKNN Toolkit
pip install rknn-toolkit2-1.5.0-cp38-cp38-linux_x86_64.whl

# 验证安装
python -c "from rknn.api import RKNN; print('OK')"

我在项目中遇到过一个问题:RKNN的版本跟NPU驱动版本必须严格对应。有一次我升级了固件,忘了更新RKNN Toolkit,结果模型转换一直报错。折腾了两天才发现是版本不匹配。

注意: RK3588的NPU驱动在Linux内核5.10以上版本才支持。如果你用的是老内核,记得先升级。

3.3.3 Intel 系列(OpenVINO)

Intel这边,主要是OpenVINO Toolkit。安装方式比较友好,有在线安装和离线安装两种。我推荐离线安装,因为在线安装经常因为网络问题中断。

# 下载OpenVINO
wget https://storage.openvinotoolkit.org/repositories/openvino/packages/2023.3/linux/l_openvino_toolkit_ubuntu20_2023.3.0.20231005_x86_64.tgz

# 解压并安装
tar -xf l_openvino_toolkit_*.tgz
cd l_openvino_toolkit_*
sudo ./install.sh

# 设置环境变量
source /opt/intel/openvino_2023/setupvars.sh

Intel的OpenVINO有个好处:它支持把模型从各种框架(TensorFlow、PyTorch、ONNX)转换成IR格式。你想想看,这省了多少事。我有个项目,客户给的模型是PyTorch的,我直接用Model Optimizer转成IR,在Intel NUC上跑得飞起。

硬件平台 SDK名称 安装方式 关键依赖
Jetson JetPack SDK Manager / 命令行 CUDA、cuDNN、TensorRT
RK3588 RKNN Toolkit pip安装 Python 3.8、NPU驱动
Intel OpenVINO 离线安装包 CMake、Python 3.8+

3.4 环境验证——别等到最后才发现问题

环境搭好了,怎么知道对不对?我习惯写一个简单的测试脚本。比如,验证交叉编译工具链:

# test_toolchain.c
#include <stdio.h>
int main() {
    printf("Hello from %s!\n", "Edge Device");
    return 0;
}

# 编译
aarch64-linux-gnu-gcc test_toolchain.c -o test_toolchain

# 查看文件类型
file test_toolchain
# 输出应该是:ELF 64-bit LSB executable, ARM aarch64

对于Docker镜像,我建议跑一个简单的推理测试。比如用OpenCV读取一张图片,看看能不能正常处理。我在项目中遇到过Docker镜像里OpenCV编译时没开NEON优化,结果推理速度慢得离谱。后来在Dockerfile里加了 -DCMAKE_CXX_FLAGS="-march=armv8-a+simd" 才解决。

我的习惯: 每次搭建完环境,都写一个 env_check.sh 脚本,把工具链版本、SDK路径、依赖库版本都打印出来。这样出了问题,一眼就能看出是哪个环节不对。

好了,环境搭建这部分就聊到这儿。说白了,工具链和SDK就是你的武器,武器不趁手,仗就没法打。下一章咱们开始真正接触推理框架的定制,到时候这些环境就派上用场了。