SNPE 2.21:VGG16 Demo 交叉编译到 ARM64 Linux 并推理

📅 2026/7/11 5:03:29
SNPE 2.21:VGG16 Demo 交叉编译到 ARM64 Linux 并推理
摘要本文完整演示了在 Ubuntu 20.04 x86_64 主机上将 SNPE 2.21.0 SDK 的 VGG16 Demo 交叉编译到 ARM64 Linux 板端并完成 CPU 推理的全流程。涵盖主机环境准备、交叉工具链安装、ONNX 模型转换与 DLC 生成、Native C Demo 交叉编译、板端部署与推理执行、结果拉取与 Top-5 分类展示等核心步骤并扩展介绍了 Yocto/OpenEmbedded 目标板适配、GPU/DSP 扩展注意事项以及常见错误排查方法为 ARM64 Linux 平台上的 SNPE 模型部署提供完整参考。flowchart TD A[主机环境准备] -- B[模型转换] A -- C[交叉编译] subgraph 主机环境 A1[Ubuntu 20.04 x86_64] A2[Python 3.8 venv] A3[SNPE 2.21.0 SDK] A4[aarch64-linux-gnu-g 9.4] end subgraph 模型转换 B1[下载 VGG16 ONNX] B2[预处理图片 → 224×224 float32 raw] B3[snpe-onnx-to-dlc → vgg16.dlc] end subgraph 交叉编译 C1[配置 SNPE_ROOT envsetup.sh] C2[make -f Makefile.aarch64-ubuntu-gcc9.4] C3[产物: snpe-sample] end subgraph 板端部署 D1[scp snpe-sample libSNPE.so] D2[scp vgg16.dlc kitten.raw] D3[设置 LD_LIBRARY_PATH] end subgraph 推理验证 E1[运行 snpe-sample CPU 推理] E2[生成 Result_0/*.raw] E3[拉回结果 → Top-5 分类] end B --gt; C C --gt; D1 D1 --gt; D2 D2 --gt; D3 D3 --gt; E1 E1 --gt; E2 E2 --gt; E3# SNPE 2.21VGG16 Demo 交叉编译到 ARM64 Linux 并推理本文针对当前 SDK 2.21.0完成以下链路textUbuntu 20.04 x86_64 主机├─ VGG16 ONNX - DLC├─ 图片 - 224x224 float32 raw└─ aarch64-linux-gnu-g 交叉编译 snpe-sample↓ scpARM64 Ubuntu Linux 板端运行 CPU 推理 - 拉回输出 - Top-5本文默认目标板是 **Ubuntu/glibc ARM64**所以选用 SDK 目标aarch64-ubuntu-gcc9.4。如果板端是 Yocto/OpenEmbedded请直接看第 10 节不能混用Ubuntu 运行库。## 1. 准备环境推荐配置- 编译主机Ubuntu 20.04 x86_64- Python3.8- 目标板ARM64 Ubuntu Linux- 交叉编译器aarch64-linux-gnu-g 9.4- SDK本目录中的 SNPE 2.21.0- 主机和板端可通过 ssh/scp 通信。先检查目标板bashssh root192.168.1.100 uname -m; ldd --version | head -1uname -m 必须输出 aarch64。下文用变量避免反复修改地址bashexport BOARD_USERrootexport BOARD_IP192.168.1.100export TARGET_DIR/opt/snpe_vgg## 2. 主机配置 SNPE 与 Pythonbashexport SNPE_ROOT$HOME/snpe_2.21 # 改成 SDK 实际绝对路径cd $SNPE_ROOTpython3.8 -m venv .venv-vggsource .venv-vgg/bin/activatesource bin/envsetup.shpython --versionecho $SNPE_ROOTsnpe-onnx-to-dlc --helpSDK 的 sdk.yaml 指定 ONNX 1.11.0VGG 辅助脚本还需要 NumPy、Pillow 和 SciPybashpython -m pip install --upgrade pippython -m pip install onnx1.11.0 numpy1.23.5 Pillow scipy1.9.1如果转换器仍提示缺包可在虚拟环境中运行 SDK 的依赖检查bash$SNPE_ROOT/bin/check-python-dependency## 3. 安装 ARM64 交叉工具链Ubuntu 20.04 的交叉编译器与 SDK 的 aarch64-ubuntu-gcc9.4 目标相匹配bashsudo apt updatesudo apt install -y build-essential gcc-aarch64-linux-gnu g-aarch64-linux-gnu \binutils-aarch64-linux-gnu wget openssh-clientaarch64-linux-gnu-g --version确认主版本是 9.x。若主机不是 Ubuntu 20.04建议安装独立 GCC 9.4/sysroot不要直接用过新的主机交叉编译器以免目标板缺少较新的 GLIBCXX_* 或 GLIBC_*。## 4. 下载 VGG16、标签和测试图片bashexport VGG$SNPE_ROOT/examples/Models/VGGmkdir -p $VGG/onnx $VGG/data/cropped $VGG/dlcwget -c -O $VGG/onnx/vgg16.onnx \https://s3.amazonaws.com/onnx-model-zoo/vgg/vgg16/vgg16.onnxwget -O $VGG/data/synset.txt \https://s3.amazonaws.com/onnx-model-zoo/synset.txtwget -O $VGG/data/kitten.jpg \https://s3.amazonaws.com/model-server/inputs/kitten.jpgVGG16 ONNX 大约 500 MB确认没有下载成错误页面bashls -lh $VGG/onnx/vgg16.onnx## 5. 预处理图片并生成 DLC随包脚本会把图片缩放到 256×256、中心裁剪到 224×224进行 ImageNet 归一化最后保存为 NHWC float32 rawbashpython $VGG/scripts/create_VGG_raws.py \-i $VGG/data \-d $VGG/data/croppedpython $VGG/scripts/create_file_list.py \-i $VGG/data/cropped \-o $VGG/data/cropped/raw_list.txt \-e *.raw -r转换 ONNX 为 DLCbashsnpe-onnx-to-dlc \--input_network $VGG/onnx/vgg16.onnx \--output_path $VGG/dlc/vgg16.dlcsnpe-dlc-info -i $VGG/dlc/vgg16.dlc检查输入bashstat -c %n %s bytes $VGG/data/cropped/kitten.rawcat $VGG/data/cropped/raw_list.txtkitten.raw 应为 224 × 224 × 3 × 4 602112 字节列表应包含相对路径kitten.raw。## 6. 交叉编译 SNPE Native C DemoSDK demo 位于textexamples/SNPE/NativeCpp/SampleCode随包 Makefile.aarch64-ubuntu-gcc9.4 默认期待一个特定目录结构的工具链。直接在 make命令行覆盖 CXX 最简单也比仅 export CXX... 更可靠因为 Makefile 自身给 CXX赋了值。bashexport SAMPLE$SNPE_ROOT/examples/SNPE/NativeCpp/SampleCodecd $SAMPLErm -rf obj/local/aarch64-ubuntu-gcc9.4make -j$(nproc) \SNPE_ROOT$SNPE_ROOT \CXXaarch64-linux-gnu-g \-f Makefile.aarch64-ubuntu-gcc9.4不要用 sudo make否则 SNPE_ROOT 很可能被 sudo 清理。编译前应确认头文件根目录bashtest -f $SNPE_ROOT/include/SNPE/SNPE/SNPE.hpptest -f $SNPE_ROOT/include/SNPE/SNPE/SNPEFactory.hpptest -f $SNPE_ROOT/include/SNPE/DlContainer/IDlContainer.hpp三条命令都应返回 0。实际编译命令中必须出现text-I SDK绝对路径/include/SNPE产物为text$SAMPLE/obj/local/aarch64-ubuntu-gcc9.4/snpe-sample验证架构和动态依赖bashfile $SAMPLE/obj/local/aarch64-ubuntu-gcc9.4/snpe-sampleaarch64-linux-gnu-readelf -h $SAMPLE/obj/local/aarch64-ubuntu-gcc9.4/snpe-sample \| grep -E Class:|Machine:aarch64-linux-gnu-readelf -d $SAMPLE/obj/local/aarch64-ubuntu-gcc9.4/snpe-sample \| grep NEEDED应看到 ELF 64-bit、ARM aarch64/AArch64以及对 libSNPE.so 的依赖。### 如果已有厂商 sysroot当板端根文件系统不是标准 Ubuntu 20.04建议用板端 BSP 配套 sysrootbashmake -j$(nproc) \CXX/opt/gcc-9.4/bin/aarch64-linux-gnu-g --sysroot/opt/board-sysroot \-f Makefile.aarch64-ubuntu-gcc9.4工具链/sysroot 与板端 rootfs 一致能显著减少 GLIBC_* not found 问题。## 7. 部署到 ARM64 Linux 板端先建目录bashssh $BOARD_USER$BOARD_IP \mkdir -p $TARGET_DIR/bin $TARGET_DIR/lib $TARGET_DIR/model $TARGET_DIR/data推送交叉编译出的 demo、SNPE ARM64 Ubuntu 运行库、模型和输入bashscp $SAMPLE/obj/local/aarch64-ubuntu-gcc9.4/snpe-sample \$BOARD_USER$BOARD_IP:$TARGET_DIR/bin/scp $SNPE_ROOT/lib/aarch64-ubuntu-gcc9.4/*.so \$BOARD_USER$BOARD_IP:$TARGET_DIR/lib/scp $VGG/dlc/vgg16.dlc \$BOARD_USER$BOARD_IP:$TARGET_DIR/model/scp $VGG/data/cropped/kitten.raw $VGG/data/cropped/raw_list.txt \$BOARD_USER$BOARD_IP:$TARGET_DIR/data/这里必须部署 lib/aarch64-ubuntu-gcc9.4不要误用 aarch64-android 或aarch64-oe-linux-*。## 8. 在板端运行 VGG16 CPU 推理先验证 demo 能加载bashssh $BOARD_USER$BOARD_IP export LD_LIBRARY_PATH$TARGET_DIR/lib:\${LD_LIBRARY_PATH:-}chmod x $TARGET_DIR/bin/snpe-sample$TARGET_DIR/bin/snpe-sample -h运行 CPU 推理bashssh $BOARD_USER$BOARD_IP set -eexport LD_LIBRARY_PATH$TARGET_DIR/lib:\${LD_LIBRARY_PATH:-}cd $TARGET_DIR/datarm -rf $TARGET_DIR/output_sample$TARGET_DIR/bin/snpe-sample \-b ITENSOR \-r cpu \-d $TARGET_DIR/model/vgg16.dlc \-i raw_list.txt \-o $TARGET_DIR/output_samplefind $TARGET_DIR/output_sample -type f -maxdepth 2 -ls成功后通常会生成text/opt/snpe_vgg/output_sample/Result_0/vgg0_dense2_fwd.raw也可先用 SDK 自带的 ARM64 Linux 工具排除 demo 编译问题bashscp $SNPE_ROOT/bin/aarch64-ubuntu-gcc9.4/snpe-net-run \$BOARD_USER$BOARD_IP:$TARGET_DIR/bin/ssh $BOARD_USER$BOARD_IP export LD_LIBRARY_PATH$TARGET_DIR/lib:\${LD_LIBRARY_PATH:-}cd $TARGET_DIR/data$TARGET_DIR/bin/snpe-net-run \--container $TARGET_DIR/model/vgg16.dlc \--input_list raw_list.txt \--output_dir $TARGET_DIR/output_net_run \--use_cpu如果预编译 snpe-net-run 能运行而自编译 snpe-sample 不能问题在交叉工具链、sysroot或 demo 链接阶段如果二者都失败则优先检查模型、运行库和板端系统兼容性。## 9. 拉回结果并显示 Top-5bashrm -rf $VGG/output_samplescp -r $BOARD_USER$BOARD_IP:$TARGET_DIR/output_sample $VGG/output_samplepython $VGG/scripts/show_vgg_classifications.py \-i $VGG/data/cropped/raw_list.txt \-o $VGG/output_sample \-l $VGG/data/synset.txt官方 kitten 图片的结果通常以 tabby、tiger cat、Egyptian cat 等类别为主。运行后端不同会造成小幅概率差异。## 10. 如果目标板是 Yocto/OpenEmbedded先在板端确认bashcat /etc/os-release若是 Yocto/OE不要使用本文前面的 aarch64-ubuntu-gcc9.4。SNPE 2.21 提供以下目标- aarch64-oe-linux-gcc8.2- aarch64-oe-linux-gcc9.3- aarch64-oe-linux-gcc11.2适合相应版本的 Yocto SDK例如 Kirkstone 系以 BSP 提供的 GCC 11.2 SDK 为例bashsource /opt/board-sdk/environment-setup-armv8a-oe-linuxcd $SAMPLEmake -j$(nproc) \CXX$CXX \-f Makefile.aarch64-oe-linux-gcc11.2部署时也必须换成完全对应的库bashscp $SNPE_ROOT/lib/aarch64-oe-linux-gcc11.2/*.so \$BOARD_USER$BOARD_IP:$TARGET_DIR/lib/注意某些 Yocto 环境的 $CXX 自带多段参数。若 make 对包含空格的 CXX 处理不正确把 BSP 环境输出的完整编译命令直接写入 make 命令行或按实际 sysroot 修改一份本地Makefile。## 11. GPU/DSP 注意事项CPU 路径是基础验收路线。要跑 GPU目标 BSP 必须包含 Qualcomm OpenCL 用户态驱动bash$TARGET_DIR/bin/snpe-sample -b ITENSOR -r gpu \-d $TARGET_DIR/model/vgg16.dlc -i raw_list.txt -o output_gpuDSP/HTP 还要求- 按 SoC 选择正确的 hexagon-v68/v69/v73/v75 skeleton- 正确设置 ADSP_LIBRARY_PATH- 设备固件和用户态驱动与 SNPE 版本兼容- 通常先将模型量化成 INT8 DLC。因此建议先把本文 CPU 路径跑通再根据具体 SoC/BSP 配置 DSP。仅知道“ARM64 Linux”不足以确定 HTP 架构。## 12. 常见错误### libSNPE.so: cannot open shared object filebashexport LD_LIBRARY_PATH/opt/snpe_vgg/lib:$LD_LIBRARY_PATH并确认库是 aarch64-ubuntu-gcc9.4 版本。### GLIBCXX_x.y.z not found 或 GLIBC_x.y not found交叉编译 sysroot 比板端系统新或混用了 Ubuntu/OE 库。使用板端 BSP 对应的交叉工具链和sysroot不要靠复制主机的 libc.so 解决。### cannot execute binary file: Exec format error程序不是 AArch64 ELF。用 file 和 readelf -h 检查确保调用的是aarch64-linux-gnu-g不是主机 g。### 链接时 cannot find -lSNPE确认存在bashls $SNPE_ROOT/lib/aarch64-ubuntu-gcc9.4/libSNPE.so并且已经 source $SNPE_ROOT/bin/envsetup.sh。### SNPE/SNPE.hpp: No such file or directory说明 SNPE_ROOT 为空或不是 SDK 根目录。不要用 sudo make并在 make 命令行显式传入bashexport SNPE_ROOT$(realpath /path/to/snpe_2.21)test -f $SNPE_ROOT/include/SNPE/SNPE/SNPE.hpp || exit 1cd $SNPE_ROOT/examples/SNPE/NativeCpp/SampleCoderm -rf obj/local/aarch64-ubuntu-gcc9.4make -j$(nproc) \SNPE_ROOT$SNPE_ROOT \CXXaarch64-linux-gnu-g \-f Makefile.aarch64-ubuntu-gcc9.4### 进程被 OOM killer 杀死VGG16 很大。用 dmesg | tail 检查 OOM关闭其他进程或增加 swap也可以先用 MobileNet验证部署链路。### 后处理找不到 vgg0_dense2_fwd.raw通过 snpe-dlc-info 确认实际输出 tensor 名。不同来源的 VGG 模型可能输出名不同此时需同步修改 scripts/show_vgg_classifications.py 中的结果文件名。## 13. 验收清单- 主机 snpe-dlc-info 能读取 vgg16.dlc- kitten.raw 为 602112 字节- 目标板 uname -m 为 aarch64- file snpe-sample 显示 ELF 64-bit ... ARM aarch64- 板端 snpe-sample -h 能正常打印- CPU 推理生成 Result_0/*.raw- Top-5 是合理的猫类别。