← 全部文章端侧部署

NVIDIA AGX Orin 系统与 TensorRT 环境部署

从 Jetson AGX Orin 系统和 CUDA 组件,到 TensorRT Python binding、GPU 容器、引擎构建与数值验证,建立可复现的部署基线。

研究记录: 2026-03-30 — 2026-06-09
本站发布:

Jetson AGX Orin 的部署需要同时处理板级系统、计算库和应用运行环境。Jetson Linux 提供 bootloader、内核和驱动等 BSP 组件,JetPack 在此基础上提供 CUDA、TensorRT 等计算组件。只刷入系统,并不代表 Python binding、模型编译工具和容器运行时都已安装完整。

本文以归档中的 Jetson Linux R36.5、CUDA 12.6、TensorRT 10.3 环境为主,覆盖从刷机到引擎部署的操作顺序。命令中的路径和输入名称均为示例;安装、刷机、修改网络和重启 Docker 是环境搭建步骤,已有设备排查时先执行查询命令,按缺失项处理。

一、先确认系统与软件栈

1.1 区分 BSP、计算组件和 Python 环境

先记录系统信息,再决定安装哪些包:

cat /etc/nv_tegra_release
cat /etc/os-release
uname -r
uname -m
getconf GNU_LIBC_VERSION
dpkg-query -W 'nvidia-l4t-core' 'nvidia-jetpack'
dpkg-query -W 'cuda-cudart-*' 'libnvinfer*' 'python3-libnvinfer*'
readlink -f /usr/local/cuda

部分包未安装时,dpkg-query 会返回非零状态,应结合输出逐项判断。没有 nvidia-jetpack 元包,也不代表 CUDA 和 TensorRT 不存在:它们可能被单独安装。

归档中的版本基线如下:

层次 版本或状态 主要核对方式
Jetson Linux R36.5.0 /etc/nv_tegra_release、L4T 包
操作系统 Ubuntu 22.04、aarch64 os-release、uname -m
内核 5.15.185-tegra uname -r
系统 Python 3.10 /usr/bin/python3 --version
CUDA 12.6 安装包、CUDA 路径、nvcc
TensorRT Python 导入版本 10.3.0 Python binding 与系统库共同检查

JetPack 6.2.2 的官方组合包含 Jetson Linux 36.5、CUDA 12.6 和 TensorRT 10.3。版本表用于确定这篇教程的适用范围,不要求其他版本的设备照表降级。计算组件也可以按官方支持的方式升级,不能只凭一个 JetPack 名称推断所有已安装版本。

1.2 检查解释器与编译工具

command -v python3
python3 --version
/usr/bin/python3 --version
command -v nvcc
nvcc --version
command -v trtexec
ls -l /usr/src/tensorrt/bin/trtexec

nvcc 不存在可能只是没有安装 CUDA 开发工具,不能据此判定 GPU 运行库不可用。反过来,nvcc --version 只说明这个编译器的版本,不能证明当前 Python 进程加载的库来自同一套 CUDA。

二、刷机、登录与存储准备

2.1 确定刷机目标

刷机前确认模块、载板和启动介质。AGX Orin 开发套件的配置不能直接套到所有第三方载板;eMMC 与外置 NVMe 的刷机流程也不同。先备份目标盘数据,再选择对应版本的 SDK Manager 或 BSP 工具。

使用 SDK Manager 时,依次选择目标硬件和 JetPack 版本,连接 Recovery USB,完成系统刷写和首次启动,再按需要安装目标端 SDK 组件。主机 Ubuntu 版本以对应 SDK Manager 和 BSP 的要求为准。

命令行方式需要同一版本的 BSP 与 Sample Root Filesystem。准备过程为:

  1. 解压 BSP,得到 Linux_for_Tegra。
  2. 将配套 Sample Root Filesystem 解压到 rootfs/,保留文件权限。
  3. 在 BSP 目录按该版本要求执行 sudo tools/l4t_flash_prerequisites.sh,再执行 sudo ./apply_binaries.sh。
  4. 使设备进入 Force Recovery,在主机检查 USB 识别结果。
  5. 使用匹配板型和介质的命令刷写。
# 在刷机主机执行,仅查询 USB 设备。
lsusb -d 0955:

归档中开发套件写入内部存储使用:

# 在已准备好的 BSP 目录执行;此命令会刷写目标设备。
sudo ./flash.sh jetson-agx-orin-devkit internal

外置 NVMe 应采用对应 BSP 的 l4t_initrd_flash.sh 流程,并核对目标盘与分区配置,不把上面的 internal 简单替换成一个盘符。Recovery 阶段的 USB 识别只说明刷机通道可用;刷写成功后,还要确认设备能从预期介质正常启动。

2.2 无头初始化与网络

没有显示器时,可以通过开发套件支持的 USB 串口完成首次用户和网络配置。正常启动后的 USB 网络与 Recovery 是两种状态:前者提供运行系统的通信入口,后者用于刷写,不能混为一谈。

先查询实际连接,不预设网卡一定叫 eth0:

ip -brief address
ip route
nmcli device status
nmcli connection show

需要固定地址时,修改已有连接配置,明确地址前缀、网关和 DNS。在远程连接下改当前网卡会中断会话,应保留串口或其他管理入口。教程不固定某个私网网段,部署时由实际网络分配。

2.3 确认根分区与数据盘

findmnt /
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS
df -hT
docker info --format '{{.DockerRootDir}}'

模型、编译产物和镜像层很容易占满根分区。数据盘挂载完成后,还应检查挂载路径的可写权限和持久化配置,避免重启后服务把数据写入根分区中的空目录。

Docker 与使用 containerd image store 的环境可能分别占用不同目录。迁移前先确认实际存储后端,停服务、复制数据、修改配置和重启验证应作为独立维护操作,不能只修改一个路径就假定所有镜像数据都已迁走。

三、补齐 CUDA 与 TensorRT 组件

先检查 NVIDIA APT 源是否与 BSP 匹配:

grep -RhE '^[[:space:]]*deb .*repo.download.nvidia.com/jetson' \
  /etc/apt/sources.list /etc/apt/sources.list.d/
apt-cache policy nvidia-jetpack python3-libnvinfer libcudla-12-6
dpkg --audit

不要为安装一个新包而混入另一代 L4T 的软件源。在源和包依赖正确的全新系统上,可以安装完整 JetPack:

sudo apt-get update
sudo apt-get install nvidia-jetpack

存储有限时,可以按官方组件清单选择运行包和开发包。TensorRT 原生 runtime、Python binding、头文件和 trtexec 是不同组件:只安装 lean 或 dispatch binding,不等于具备完整的模型构建环境。

需要补包时先模拟依赖变化,例如:

apt-get --simulate install python3-libnvinfer python3-libnvinfer-dev

确认不会意外替换现有计算栈后再执行实际安装。包管理器显示“可自动删除”的 CUDA 包也需要逐项核对,不能直接把 apt autoremove 当作部署收尾步骤。

四、定位 Python 与动态库问题

4.1 先确认导入的到底是什么

/usr/bin/python3 -B - <<'PY'
import sys
import tensorrt as trt

print("python:", sys.executable)
print("TensorRT:", getattr(trt, "__version__", "<missing>"))
print("module:", getattr(trt, "__file__", None))
PY

正常环境应同时给出版本和明确的模块位置。导入成功却没有 __version__,应先排查当前目录中的同名文件、空目录或残留 namespace package;不能仅凭 import 没报错就认定 binding 完整。

系统 APT 安装的 binding 通常位于系统 Python 的 dist-packages,独立虚拟环境不一定可见。若希望沿用系统 TensorRT,可以用同一 Python 小版本建立环境:

/usr/bin/python3 -m venv --system-site-packages .venv
. .venv/bin/activate
python -B -c 'import tensorrt as trt; print(trt.__version__, trt.__file__)'

该方式也会暴露其他系统 Python 包。若需要更强隔离,应采用匹配平台的完整环境;不要把 Python 3.10 的二进制扩展直接复制到另一小版本,也不要用一次 pip install --upgrade tensorrt 覆盖整套 JetPack 依赖。

4.2 区分缺库与搜索路径错误

遇到:

ImportError: libcudla.so.1: cannot open shared object file

先查看系统包、文件和链接缓存:

dpkg-query -W 'libcudla*'
ls -l /usr/local/cuda-12.6/targets/aarch64-linux/lib/libcudla.so*
ldconfig -p | grep -E 'libcudla|libnvinfer'
dpkg -L python3-libnvinfer | grep -E '\.so($|\.)'

再对上一步找到的实际 Python 扩展执行 ldd。归档中的路径为:

ldd /usr/lib/python3.10/dist-packages/tensorrt/tensorrt.so
检查结果 处理方向
主系统缺少文件,只有旧系统备份或容器层里存在 安装当前 CUDA 对应的 cuDLA 包
正确版本的文件存在,但依赖解析为 not found 检查链接缓存、配置和符号链接
终端可导入,服务启动失败 检查服务使用的解释器和库搜索环境
导入的是空模块或其他目录中的同名模块 检查 Python 包位置和 binding 是否完整

在 CUDA 12.6 环境,运行库缺失时补充 libcudla-12-6;只有开发工作需要时再加开发包:

sudo apt-get install libcudla-12-6

文件已经存在、但系统搜索配置确实缺失时,才采用归档中用过的路径修复:

printf '%s\n' '/usr/local/cuda-12.6/targets/aarch64-linux/lib' \
  | sudo tee /etc/ld.so.conf.d/cuda-12-6-aarch64.conf
sudo ldconfig

修复后重新检查 ldconfig -p、ldd 和 Python 导入。旧 CUDA 目录或 Docker overlay 中找到一个同名库,并不能说明它适合当前宿主系统;也不能用软链接把不匹配的 SONAME 伪装成所需版本。

4.3 把媒体依赖与推理环境分开

原生媒体程序常同时依赖 FFmpeg、OpenCV、Python 和 C++ 运行库。排查时从实际二进制的 ldd 开始,按缺少的 SONAME 找对应构建版本,而不是笼统升级一个 FFmpeg 命令行程序。

交互终端、虚拟环境与 systemd 服务的环境变量不同。只在个人 shell 中设置 LD_LIBRARY_PATH,不会自动修复服务进程。服务需要的私有库应限定在该服务的启动环境中;不要把 conda 的整套库目录加入全系统搜索路径,否则可能替换媒体插件原本使用的 libstdc++、FFmpeg 或 OpenCV。

五、配置 GPU 容器环境

先查询 Docker 和 NVIDIA runtime:

docker version
docker info --format '{{json .Runtimes}}'
command -v nvidia-container-runtime
command -v nvidia-ctk
dpkg-query -W 'nvidia-container-toolkit*'

若缺少 toolkit,按 NVIDIA 安装指南配置对应 APT 源并安装。提供 nvidia-ctk 的版本可以这样配置 Docker:

sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

这一步会更新 Docker 配置并重启服务,应安排在维护窗口。显式指定 runtime 即可,不必为了一个推理容器把所有容器的默认 runtime 都改成 NVIDIA。

镜像需要同时满足 aarch64、Jetson/iGPU 支持和计算库兼容性。aarch64 的服务器镜像也不必然支持 Jetson;镜像内 CUDA 或 TensorRT 与宿主版本不同,需要依据该镜像的支持说明判断。

对于已经包含 Python TensorRT binding 的兼容镜像,可以先做导入检查:

# jetson-trt:validated 代表已经核对兼容性的本地镜像。
docker run --rm --runtime=nvidia \
  -e NVIDIA_VISIBLE_DEVICES=all \
  jetson-trt:validated \
  python3 -B -c 'import tensorrt as trt; print(trt.__version__, trt.__file__)'

导入通过后,再单独验证实际 GPU 计算。容器启动成功、库能导入、GPU 算子能执行是三个检查层次;不要通过挂载宿主的整套 /usr/lib 来掩盖镜像依赖不匹配。

如果应用还需要 PyTorch,应选择 NVIDIA 的 Jetson wheel 或明确支持当前 JetPack 的容器,核对 Python、CUDA 和框架扩展版本。torch.cuda.is_available() 返回真仍不足以覆盖所有扩展;no kernel image is available 需要进一步检查报错算子所属二进制的 GPU 架构支持。

六、在目标环境编译 TensorRT 引擎

6.1 固定输入契约

编译前保存 ONNX 及其外部权重文件,核对输入名称、dtype、维度和输出含义。检测模型还要固定 RGB/BGR、缩放或 Letterbox、归一化、类别顺序和 NMS 所在位置,先得到 PyTorch 与 ONNX 的数值基线。

找到实际 trtexec 后查看当前版本帮助:

/usr/src/tensorrt/bin/trtexec --help

工具也可能由本地软链接加入 PATH。核对链接目标和依赖,避免 shell 调用旧版工具、Python 却导入另一版 runtime。

6.2 建立静态 FP16 基线

下面以 TensorRT 10.3、静态输入 ONNX 为例:

/usr/src/tensorrt/bin/trtexec \
  --onnx=model.onnx \
  --saveEngine=model-fp16.plan \
  --fp16 \
  --skipInference

--skipInference 让此步骤只构建和保存引擎。构建本身也会进行计算与 tactic 测量,应在资源可用时进行。

静态 ONNX 不需要额外设置动态 profile。固定 batch=1 的图,要增加 batch 应重新导出相应静态图,或导出真正的动态维度,不能只在命令后面追加一个 batch 数。

--fp16 允许编译器使用 FP16,并不要求每一层和输入输出都是 FP16。先验证浮点路径,再增加 INT8 及校准逻辑,便于区分模型导出、编译与量化误差。

若 FP16 引擎构建和执行成功,但固定样本输出明显偏离,可参考 TensorRT FP16 数值异常排查:QKV 布局的等价改写,从中间张量与图表达继续定位。

6.3 动态 batch 与 profile

假设输入叫 images,只有首维动态,通道和分辨率固定为 3×640×640:

/usr/src/tensorrt/bin/trtexec \
  --onnx=model-dynamic.onnx \
  --saveEngine=model-dynamic-fp16.plan \
  --fp16 \
  --minShapes=images:1x3x640x640 \
  --optShapes=images:4x3x640x640 \
  --maxShapes=images:8x3x640x640 \
  --skipInference

这里的 1、4、8 只是示例。min/max 限定接受范围,opt 是构建优化的重要目标,应贴近常见请求;不能只按“能装下多大的 batch”设置范围。多输入模型需要覆盖各动态输入,并维持输入间的维度关系。

TensorRT 8.5 与 10.3 的脚本也应分开核对:

配置 TensorRT 10.3 示例 迁移时要检查
只构建引擎 --skipInference 旧脚本可能使用 --buildOnly
workspace 限制 --memPoolSize=workspace:1024 旧 --workspace 参数不能直接照搬
batch ONNX 维度与 profile 不沿用 implicit batch 的 --maxBatch 思路
日志 按当前帮助选择 --verbose 等 不添加不存在的 --quiet=false

workspace 限制也不是整个构建进程或运行时的总内存上限。Orin 使用共享物理内存,模型权重、激活、CPU 应用和媒体缓冲区会共同占用资源。

6.4 引擎的兼容边界

.plan 与 .engine 通常只是序列化引擎的不同扩展名。引擎包含面向目标硬件和 runtime 的优化结果,不能因为服务器生成成功,就认为能复制到 Orin 运行。

常规部署优先在目标 Orin 或匹配的 Jetson 构建环境生成引擎。版本兼容与硬件兼容是不同选项,并且有平台限制;JetPack 不支持的硬件兼容模式,不能用来实现桌面 GPU 到 Orin 的通用引擎迁移。

6.5 区分 INT8 校准与显式 QDQ

以下区分针对本文的 TensorRT 10.3 环境。该版本已将隐式 INT8 量化与校准器 API 标记为弃用,维护旧流程时仍需分清两条路径。先检查 ONNX 是否包含 QuantizeLinear / DequantizeLinear,再决定量化范围从哪里来:

路径 量化范围来源 构建前需要核对
浮点图的隐式 INT8 校准 代表性样本与校准器 正式前处理、校准器实现与 cache
显式 QDQ 图 图内的尺度与量化节点 scale、zero point、axis、dtype 与目标版本支持

校准输入必须与正式推理的颜色、归一化、布局和 shape 一致。模型、前处理或输入尺寸改变后,重新核对校准 cache;trtexec 不会将图片目录自动变成正确的校准输入,需要配套校准程序或兼容的校准表。没有真实校准数据的 INT8 性能测试不能用于证明精度通过。

显式 QDQ 图已经表达量化语义,不再用校准器重新决定这套范围。不要将删除 Q/DQ 当作普通图清洗,也不要在没有核对图的情况下叠加量化参数。构建失败时保留原图与日志,将浮点基线、QDQ 图及对应构建配置分别对照;某份移除 QDQ 的图能构建,不足以证明之前发生了“重复量化”。

数值验证还要分别检查输出分支。检测图可能将像素尺度的 boxes 与低幅值 scores 拼接在一起;若实际量化粒度使分数分辨率不足,整体余弦仍可能掩盖阈值附近的损失。先确认实际尺度、层精度与任务结果,再考虑混合精度或调整输出分支,不能仅靠降低检测阈值补偿已经丢失的数值。

七、运行验证与部署打包

7.1 分开检查数值和性能

静态引擎加载与计时示例:

/usr/src/tensorrt/bin/trtexec \
  --loadEngine=model-fp16.plan \
  --warmUp=1000 \
  --duration=10

动态引擎运行时还要设置具体输入形状:

/usr/src/tensorrt/bin/trtexec \
  --loadEngine=model-dynamic-fp16.plan \
  --shapes=images:4x3x640x640 \
  --warmUp=1000 \
  --duration=10

这些命令会实际占用 GPU。默认生成的测试数据适合检查执行和计时,不代表真实图片上的精度已经通过。数值验证应给 PyTorch、ONNX 和 TensorRT 输入相同的前处理张量,逐步比较原始输出与最终结果;动态模型还要覆盖 profile 的边界和常用形状。

记录功耗模式与频率状态时可以查询:

sudo nvpmodel -q
sudo jetson_clocks --show

jetson_clocks --show 是查询,不等于执行不带参数的锁频操作。比较性能时同时记录温度、内存和其他负载,区分 GPU 计算时间、数据传输与端到端时延,不直接把 trtexec 的吞吐当成视频服务处理速度。

将引擎接入多路视频后,解码、推理、缓冲与排队需要分别预算,方法见 NVIDIA 多路视频 AI 的资源预算与容量规划。

7.2 打包可复现的部署材料

材料 需要记录的内容
系统清单 L4T、内核、架构、CUDA、TensorRT、Python
原始模型 ONNX、外部权重、模型哈希
构建信息 完整命令、profile、精度、构建日志与所需插件
推理约定 输入输出名称、dtype、前后处理、类别表
运行环境 镜像 digest 或包版本、动态库配置、启动命令
验证材料 固定输入、参考结果、误差标准和性能测试条件
sha256sum model.onnx model-fp16.plan

涉及外部权重和自定义插件时也要计算对应哈希。部署包中的路径使用可配置目录,账号、网络地址和服务凭据由运行环境注入。

遇到问题时按“系统包 → 动态库 → Python binding → 引擎 → 应用”的顺序缩小范围。系统 Python 与原生 TensorRT 正常后,再接入虚拟环境和容器,最后进入真实媒体链路,能减少多个环境问题叠在一起时的定位成本。

八、参考资料

来源与说明

本文保留原始技术记录中的实验条件与限制,不代表当前所有产品均支持文中模型、设备或性能。

阅读原文(中文) · 查看固定版本 · MIT License

© 2026 moonnryan。本站提供英文翻译,英文版由 AI 辅助翻译并对照中文原文核对。

Read this article in English ↗