第一次在 Jetson AGX Orin 上搭深度学习环境时,我犯过一个几乎所有刚从 x86 服务器转过来的开发者都会犯的错:直接在终端里敲pip install torch,然后坐等它装完。结果要么是装了一堆 x86 的 wheel,import torch直接报Segmentation fault,要么是 torch 装上去了,torch.cuda.is_available()却永远是False。后来我才彻底明白,Jetson 上的软件生态和普通 Linux 服务器完全是两个世界。这篇文章把我最近一次从 SDK Manager 刷机 JetPack 6.2.3、装 Miniforge/conda、配置 PyTorch、最后用 YOLO 做板端推理验证的完整过程沉淀下来,适合手里有 AGX Orin 开发板、准备做边缘侧目标检测项目的朋友直接照着操作。
1. 从刷机方式说起:SDK Manager 直刷还是命令行烧录
Jetson 刷机这件事,网上的教程一搜一大把,但多数写得含糊。先把结论放在这里:个人开发者首选 SDK Manager 图形化刷机,产线或者需要批量部署的才去折腾命令行刷机。原因很简单,SDK Manager 会自动处理 L4T 系统镜像、CUDA、cuDNN、TensorRT 这些组件的下载和烧录,全程有进度条,出错了也容易定位。
1.1 主机端环境准备
刷机不是把开发板用 Type-C 线连上电脑就行,主机端有硬性要求:
- 一台 x86_64 架构的 Ubuntu 主机,推荐 22.04 或 24.04 LTS,Windows 和 macOS 都不行。
- 主机预留至少 50GB 磁盘空间,SDK Manager 会先下载完整镜像再写入开发板,空间不够会在烧录中段直接失败。
- 需要注册一个 NVIDIA 开发者账户,不用付费,SDK Manager 登录用。
我见过有人在虚拟机的 Ubuntu 里刷机,理论上也能跑,但 USB 直通经常出问题。如果你用虚拟机,务必确认设备管理器里能把 NVIDIA 的 USB 设备完整透传给虚拟机,否则刷到一半lsusb看不到目标设备,整个过程全部白费。
1.2 进入恢复模式与 USB 识别
AGX Orin 开发板刷机前必须进入 USB 恢复模式。具体操作:
- 先把开发板断电。
- 按住板载的
Recovery按键不松手。 - 插上 Type-C 数据线到主机。
- 上电开机,保持
Recovery按键按住大约 5 秒后再松开。
在主机终端执行:
lsusb正常情况下会看到一行包含NVIDIA Corp的 USB 设备,厂商 ID 通常落在0955开头。如果这一行没出现,大概率是线材问题——一定要用支持数据传输的 Type-C 线,很多线只能充电不能传数据,我在这个坑上浪费过半小时。
1.3 烧录选项与常见卡点
SDK Manager 打开后登录账户,主界面会让你选择目标硬件和 JetPack 版本。这里注意,别勾选 "Host Machine" 那一栏,那不是给开发板装驱动,而是在你的主机上装 CUDA 工具包,普通人用不到。
选择 JetPack 6.2.3 后,SDK Manager 会列出可安装组件。建议保持默认全选,后续不需要的组件可以在系统里手动卸载。点击烧录后,整个流程分为两个阶段:先下载镜像包(L4T),再写入开发板并做基础配置。
我遇到的卡点主要发生在下载阶段。国内网络下载 L4T 镜像的速度不稳定,有时候进度条卡在某个百分比不动。这时候别冲动拔线,先看日志确认是不是真的断流。比较难受的是 SDK Manager 没有断点续传,一旦中途失败就要重新下。如果反复失败,建议直接弃用 SDK Manager,改用命令行方式刷机:从 NVIDIA 官网手动下载 L4T 驱动包和 rootfs,解压后用flash.sh脚本来烧。命令行方式没有图形界面,但对网络容忍度高,可以先下载好所有文件再离线烧录。
提示:刷机不会损坏硬件,最多把系统搞坏再重刷。第一次刷机遇到问题不用慌,多试几次是常态。
2. 刷完机的分区策略:默认方案会让人很快后悔
很多人刷完 JetPack 就直接开始装环境,等到df -h一看根分区只剩十几 GB,才开始后悔当初没有规划存储。AGX Orin 开发者套件有两种常见形态:eMMC 版和 NVMe 版。64GB eMMC 的版本如果全给系统,后续装 conda 环境、模型权重、数据集,很快会爆盘。
2.1 默认分区为什么不够用
SDK Manager 默认会把整块存储的大部分空间分配给 APP 分区,也就是系统根目录。理论上 64GB 不小,但 JetPack 本身吃掉了大量空间,加上 CUDA、TensorRT、OpenCV 这些组件后,可用空间往往只剩 20GB 出头。一个 YOLO 训练数据集动辄几十 GB,你要是习惯把所有东西都放在~/下,一个月内就会遇到磁盘无空间的问题。
2.2 我用下来的分区方案
我目前这套方案是在刷机完成后手动调整的,不重新烧录也能做:
- 系统盘保留给
/、/home、/usr等系统路径。 - 数据盘单独挂载一块 NVMe SSD 到
/data。 - conda 环境安装时通过
--prefix参数指定到/data/conda-envs,或者干脆把 Miniforge 整个安装到/data/miniforge3。
NVMe SSD 的读写速度比 eMMC 快不少,而且刷机后系统盘和数据盘分离,以后重刷系统不会误删模型权重和数据集,这个隔离价值才是重点。
挂载 NVMe 的操作很简单。先确认设备名称:
lsblk定位到 NVMe 设备后,格式化并挂载:
sudo mkfs.ext4 /dev/nvme0n1 sudo mkdir -p /data sudo mount /dev/nvme0n1 /data为了让重启后依然生效,把挂载信息写入/etc/fstab:
echo '/dev/nvme0n1 /data ext4 defaults 0 0' | sudo tee -a /etc/fstab2.3 单盘用户的空间急救方法
如果你只有 eMMC 这一块盘,不想外接 SSD,那至少要学会扩展根分区。JetPack 有时候刷完留给根分区的大小并不等于整块盘的大小,执行:
sudo resize2fs /dev/mmcblk0p1它会自动把根文件系统扩展到可用空间的最大值。执行后df -h再看,可用空间一般会有明显改善。如果resize2fs提示文件系统已挂载,先卸载再扩,但根分区不能直接卸载,这种情况下就用resize2fs在线扩展,它支持已挂载状态。
注意:扩容前先备份重要数据。虽然
resize2fs很安全,但电源不稳导致掉电的话,文件系统损坏的风险不是零。
3. JetPack 6.2.3 软件栈盘点与 Python 环境取舍
刷机成功后,第一步不是急着装环境,而是先搞清楚系统里已经有什么。JetPack 6.2.3 不是一套空 Linux,它内置了大量 NVIDIA 优化的底层库,很多人在装 PyTorch 时遇到莫名其妙的问题,根因恰恰是没弄清楚系统里已有的东西和后来安装的东西之间存在冲突。
3.1 系统预装了哪些组件
JetPack 6.2.3 的核心组件主要包括:
- CUDA 工具包,
nvcc -V可以查看版本。 - cuDNN,深度学习卷积加速库。
- TensorRT,NVIDIA 的推理优化引擎,后面 YOLO 导出 engine 就靠它。
- OpenCV 4.x 系列,NVIDIA 编译好的版本,支持 CUDA 加速。
- VPI 视觉编程接口,一般用不上。
- NVIDIA 容器运行时,用于跑 Docker 容器。
这些组件在刷机时如果选择了完整安装,会占掉不少磁盘空间。查看已安装的 CUDA 相关包:
dpkg -l | grep -E 'cuda|nvinfer|libnvinfer'这里有个容易踩坑的点:系统自带的 OpenCV 是 NVIDIA 编译的特殊版本,和 PyPI 上通过pip install opencv-python安装的版本完全是两码事。如果你的 conda 环境里再装一个 opencv-python,可能会覆盖系统 OpenCV 的库文件,导致依赖系统 OpenCV 的组件崩溃。解决办法是在 Jetson 上尽量不要用 pip 安装 opencv-python,直接用系统自带的 OpenCV,Python 里import cv2默认就能用。
3.2 为什么首选用 Miniforge 而非 Anaconda
Jetson 开发板的 CPU 架构是 aarch64,也就是 ARM64。Anaconda 官方对 Linux ARM64 的支持一直很尴尬,虽然能装上基础发行版,但很多第三方包只有 x86_64 的预编译版本,conda 下载时会找不到匹配的包。更麻烦的是 Anaconda 默认的defaultschannel 对 aarch64 的覆盖不全。
我的选择是Miniforge。它本质上是 conda 社区维护的轻量发行版,默认走 conda-forge 源,对 ARM 架构的支持好得多。下载地址在官方仓库有,拿到的是Miniforge3-Linux-aarch64.sh。安装:
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh bash Miniforge3-Linux-aarch64.sh安装过程中会问是否执行conda init,务必选择是。如果选否,后面每次用 conda 都要手动 source 脚本,很容易碰到conda: command not found的报错。
3.3 conda 装好后第一件事:换源
Miniforge 默认源在国外,虽然能访问,但下载速度不稳定。为了省时间,换国内镜像是最优解。以清华源为例:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge conda config --set show_channel_urls yespip 也需要换源,否则后面装 PyTorch 相关依赖会很痛苦:
pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple换完后检查一下当前 pip 源:
pip config list只要显示已经指向国内镜像,后面所有pip install的速度都会快一截。
4. conda 环境创建与 "conda init" 报错的完整排障
换完源就可以开始创建虚拟环境了。在 Jetson 上,虚拟环境不是可选,而是强烈建议。因为系统级 Python 环境一旦弄乱,重装的成本很高,虚拟环境把依赖隔离好,随时可以推倒重来。
4.1 创建独立环境而不是直接用 base
我先创建了一个专门用于 YOLO 推理和训练的环境:
conda create -n yolo python=3.10 -yPython 版本为什么选 3.10?因为 Ultralytics 官方对 3.10 的兼容性测试最充分,3.11 和 3.12 虽然也能跑,但个别依赖的预编译包可能缺失。在 aarch64 平台上,年份较新的 Python 版本往往意味着更多包需要源码编译,没必要给自己增加难度。
激活环境:
conda activate yolo验证当前环境:
which python python -V输出应该指向 Miniforge 目录下envs/yolo/bin/python。
4.2 "conda error: run 'conda init' before 'conda activate'" 的根源
这个报错在 Jetson 和 x86 电脑上都常见,本质只有一个:conda 的 shell 函数没有被加载进当前终端的 shell 环境。
conda activate不是一个简单的 PATH 修改,它调用的是 conda 写入 shell 配置文件里的一个 shell 函数。如果你安装 Miniforge 时选择了不初始化 shell,或者手动编辑过~/.bashrc,就会触发这个报错。
解决分两步:
source ~/miniforge3/etc/profile.d/conda.sh conda init bash第一条命令手动加载 conda 的函数定义,第二条命令把初始化脚本写进~/.bashrc。执行完重新打开终端,conda activate就应该正常了。
如果你的 Miniforge 安装路径不是默认的~/miniforge3,请把路径换成自己的实际路径,不确定时用find / -name conda.sh 2>/dev/null搜一下。
4.3 conda 使用的几个建议
- 不要在 base 环境里乱装包。base 是 conda 自身依赖的环境,搞坏了整个 conda 都得重装。所有项目包一律放独立环境。
- 不要用 sudo pip install。这会把包安装到系统 Python 目录,污染系统环境,而且和 conda 环境的依赖隔离无关。如果真的遇到权限问题,说明你的环境激活有问题。
- 配置好 conda 默认不激活 base:
conda config --set auto_activate_base false这样每次打开终端不会自动进入 base,避免一些脚本里的 Python 版本意外指向 conda 的 base。
5. 安装 PyTorch:Jetson 专用包与常见的仓库陷阱
终于到了最容易出问题的一步。PyTorch 的安装直接决定了后面 YOLO 能不能跑通,而 Jetson 上的 PyTorch 安装方式和普通 x86 Linux 完全不一样。
5.1 为什么不能直接用 PyPI 的 torch
PyPI 上的torch也有 aarch64 Linux 的 wheel,但那是给通用 ARM 服务器(比如 Ampere Altra、树莓派 5)用的,没有针对 Jetson 的 CUDA 依赖做集成。JetPack 的 CUDA 库不是标准路径,PyPI 版 torch 在 Jetson 上装上后,import torch有时候能过,但torch.cuda.is_available()返回False,甚至直接报libcusolver.so.11: cannot open shared object file这类缺库错误,因为 PyPI 包的依赖解析逻辑根本不知道为什么 Jetson 的 CUDA 在别名路径上。
正确做法是安装NVIDIA 官方为 JetPack 编译的 PyTorch。JetPack 6.2.3 对应的版本以 NVIDIA 官方公告为准,我这套环境用的是 2.7.0 系列。这些 wheel 是 NVIDIA 从源码针对 Jetson 重新编译的,CUDA 支持完备,OpenCV 也是配套的。
5.2 找到并安装对应版本的 wheel
NVIDIA 会发布 "PyTorch for Jetson" 的预编译 wheel,通常发布在官方社区和 JetPack 下载页面。先把环境准备好:
conda activate yolo conda install numpy -y然后根据你拿到的实际 wheel 链接安装。如果你已经下载到本地:
pip install ./torch-2.7.0-cp310-cp310-linux_aarch64.whl如果在官方的 index 里直接装:
pip install torch==2.7.0 --index-url https://developer.download.nvidia.com/compute/redist/jp/v60x/pytorch/中间的 index 地址请以你实际的 JetPack 版本对应路径为准。这里多提一句,如果这个下载速度不稳定,把 wheel 下载后离线安装是最稳的。先把.whl文件下载到本地,然后pip install /path/to/torch.whl。
提示:安装前务必确认 wheel 的 Python 版本和你的 conda 环境一致。cp310 就是 Python 3.10,cp311 对应 Python 3.11,装错版本会在
pip阶段直接报错。
5.3 torchvision 源码编译实操
torchvision 的情况比较特殊。JetPack 6.2.3 对应的 torchvision 不一定有现成的预编译 wheel,很多时候要源码编译。编译前先装系统依赖:
sudo apt update sudo apt install -y libjpeg-dev libpng-dev libpython3-dev从源码安装:
git clone --branch v0.22.0 https://github.com/pytorch/vision.git cd vision export BUILD_VERSION=0.22.0 python setup.py install这里有两个细节很关键:
BUILD_VERSION必须设置,否则 torchvision 的__version__会显示0.0.0+unknown,后续 Ultralytics 检查版本会报兼容性能问题。- 如果编译过程中报找不到
nvcc,是因为 PATH 没设置:
export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATHtorchvision 源码编译在 AGX Orin 上大约需要 20 到 30 分钟,耐心等,不要以为死机了。编译完验证:
python -c "import torchvision; print(torchvision.__version__)"5.4 CUDA 可用性验证
PyTorch 安装完成后,最重要的验证命令:
python -c "import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))"你应该看到类似输出:
2.7.0 True NVIDIA Orin如果cuda.is_available()是False,大概率是装了 PyPI 版或不对应的 wheel。检查一下 torch 的构建来源:
python -c "import torch; print(torch.__config__.show())"编译信息里会包含CUDA相关的路径信息,如果显示的是 x86_64 的构建路径,卸载重装torch。
6. YOLO 验证与 TensorRT 加速部署
环境搭好了,终于可以跑 YOLO。这一步与其说是模型训练,不如说是环境联调。不过在 Jetson 上跑 YOLO,不需要急着训练,先在板端把推理跑通,验证整条链路,再考虑训练。
6.1 安装 Ultralytics 并跑通推理
在 conda 的 yolo 环境里安装 Ultralytics:
conda activate yolo pip install ultralytics安装过程会拉入一些依赖,比如matplotlib、pandas、onnx等。如果没有特别需求,直接用。
跑一个最简单的推理测试:
yolo predict model=yolo11n.pt source=https://ultralytics.com/images/bus.jpg第一次运行会下载 YOLO11 的预训练权重,顺便验证 PyTorch 是否真的在用它。如果在 Jetson 上一切正常,日志里会显示推理设备为cuda,速度通常在几十毫秒。
这里有个注意点:Ultralytics 安装时可能会重新装一个opencv-python,和系统 OpenCV 撞库。如果遇到ImportError: libGL.so.1,是因为opencv-python依赖系统 GL 库但 Jetson 上没装。解决办法:
sudo apt install -y libgl1 libglib2.0-06.2 用 TensorRT 导出加速引擎
PyTorch 直接推理在 AGX Orin 上已经能跑,但既然 JetPack 里带了 TensorRT,不把模型导出成 engine 就太亏了。TensorRT 引擎能显著提升吞吐量,对于边缘部署场景是标配。
导出命令:
yolo export model=yolo11n.pt format=engine device=0 half=True过程会先生成 ONNX,再由 TensorRT 编译成 engine 文件。导出时如果报缺onnx或onnxslim,补装:
pip install onnx onnxruntime onnxslim导出成功后,目录下会多出一个yolo11n.engine,用它推理:
yolo predict model=yolo11n.engine source=test.mp4 device=0TensorRT 引擎的加载比 PyTorch 模型慢,因为要反序列化优化后的网络,但一旦加载完成,推理速度会是 PyTorch 直接推理的 2 到 3 倍。
注意:
half=True开启 FP16 精度,在边缘设备上通常不会带来明显的精度损失,但速度提升非常明显。如果你的模型对精度极敏感,可以不开 half 用 FP32。
6.3 板端部署的几个实用小经验
- 模型文件路径不要带中文和空格。这种嵌入式环境下的 C++ 组件对路径解析很死板,中文路径经常触发奇怪的报错。
- TensorRT 引擎文件和 JetPack 版本强绑定。你在 JetPack 6.2.3 上导出的 engine,拿到 JetPack 6.0 上大概率不能用,制定部署方案时要规划好软件版本统一。
- 对图像尺寸做固定输入。YOLO 默认输入是 640x640,TensorRT 对固定尺寸优化效果最好。如果用动态尺寸,需要额外设置
dynamic=True,但边缘部署一般固定尺寸就够了。
7. 实测数据、常见报错与个人经验
刷机装环境整套流程走完,我顺手做了一轮基准测试,把有代表性的结果和踩过的坑记在这里。测试条件:AGX Orin 64GB 版本,MAXN 功耗模式,关闭电源限制,环境温度 25°C 左右。
7.1 AGX Orin 跑 YOLO 的实际性能参考
| 模型 | 推理格式 | 输入尺寸 | 单帧耗时(毫秒) | 备注 |
|---|---|---|---|---|
| YOLO11n | PyTorch | 640x640 | 约 35ms | 稳定但可感知延迟 |
| YOLO11n | TensorRT FP16 | 640x640 | 约 12-15ms | 适合实时视频流 |
| YOLO11s | TensorRT FP16 | 640x640 | 约 25-30ms | 精度与速度均衡 |
| YOLO8m | TensorRT FP16 | 640x640 | 约 45-55ms | 高精度场景可用 |
这些数据是单次推理耗时,不包含图像预处理和后处理。如果用torch.no_grad()加上 TensorRT 批处理,还能进一步压榨吞吐。
功耗和散热方面,MAXN 模式下跑 YOLO11s 持续推理,CPU 和 GPU 综合功耗在 30W 到 40W 之间,板载散热风扇会明显提速,温度稳定在 80°C 上下。如果长期 7x24 小时跑,建议把功耗模式降到 30W 级,速度损失不大但温度会舒服很多。
7.2 高频报错对照与处理
| 报错信息 | 原因 | 处理方法 |
|---|---|---|
Illegal instruction (core dumped) | 装了非 Jetson 版本的 PyTorch | 卸载后安装 NVIDIA 官方 wheel |
ImportError: libnvinfer.so.10: cannot open shared object file | TensorRT 库路径没找到 | export LD_LIBRARY_PATH=/usr/lib/aarch64-linux-gnu:$LD_LIBRARY_PATH |
conda: command not found | conda 没有初始化 shell | source ~/miniforge3/etc/profile.d/conda.sh后执行conda init bash |
The detected CUDA version (12.6) mismatches the version ... | PyTorch 编译时的 CUDA 与当前环境不一致 | 确认安装版本对应 JetPack,必要时重装 torch |
Failed to load engine because it was compiled for a different version of TensorRT | engine 与当前 TensorRT 版本不匹配 | 重新导出 engine |
7.3 个人经验
这套环境我前前后后搭过不下七八次,现在流程已经固定为一套脚本。最深的体会是:Jetson 平台上,系统版本、PyTorch 版本、TensorRT 版本三者必须严格对齐,任何一个错位都会导致莫名其妙的运行时报错,而且这些报错往往不直接指向版本问题,排查起来非常耗时。
另外一个建议是刷机完成后第一时间做一次系统备份,用dd把 eMMC 或者 NVMe 全盘镜像到外部存储。以后环境折腾坏了,直接恢复备份,十分钟回到干净状态,比从头重刷省太多时间。别依赖"反正能重刷"的心态,重刷一次包括下载镜像和重新配环境,至少浪费大半天。
最后提醒一下 swap 的事。AGX Orin 内存虽然大,但训练 YOLO 时显存和内存的压力同时存在,用free -h观察内存紧张的时候,建议启用一块 swap 文件。比如在/data下建 16GB 的 swapfile,能避免大模型加载时 OOM 崩溃。方法很简单:
sudo fallocate -l 16G /data/swapfile sudo chmod 600 /data/swapfile sudo mkswap /data/swapfile sudo swapon /data/swapfile同样写入/etc/fstab让开机自动挂载。其实 Jetson 上的坑说来说去就两类:版本对应关系,和路径写法。把这两个根源解决掉,AGX Orin 是一台非常能打的边缘计算平台。