过年期间闲下来,把近两年在Jetson平台上折腾AI项目的过程重新捋了一遍。从最早在Jetson Nano上跑通YOLOv5目标检测,到后来在Orin NX上部署大模型和SLAM相关任务,中间踩过的坑、总结出的套路,其实都很固定。不少朋友问我,Jetson平台AI开发到底要学哪些东西,怎么从跑通demo进阶到能交付项目。这篇文章就围绕选型、环境初始化、模型部署、性能优化、稳定性排查这五块,把我认为最核心的知识点串讲一遍。无论你是在校学生做毕设,还是工程师做边缘计算产品选型,这篇文章给出的都是能直接落地参考的经验。
1. Jetson硬件选型:不同型号之间的差距不只是算力
很多人第一次接触Jetson,习惯直接用官方那张TOPS算力图来选型。但实际做项目后你会发现,单看算力远远不够,内存带宽、显存容量、网络吞吐、散热设计,每一项都可能成为瓶颈。
1.1 型号定位与核心参数对比
目前市面上主流的Jetson设备大致分为几个梯队。老牌的Jetson Nano(2GB/4GB)和TX2已经处于生命周期后期,但二手市场保有量大,很多教学项目还在用。真正值得重点关注的是Orin系列,包括Jetson Orin Nano(8GB)、Jetson Orin NX(8GB/16GB)和Jetson AGX Orin(32GB/64GB)。
我自己实际测试过的几个型号,核心参数区别如下表:
| 型号 | GPU架构 | CUDA核心数 | 内存 | 内存带宽 | 算力(INT8稀疏) | 典型功耗 |
|---|---|---|---|---|---|---|
| Jetson Nano 4GB | Maxwell | 128 | 4GB LPDDR4 | 25.6GB/s | 0.47 TOPS | 5W~10W |
| Jetson Orin Nano 8GB | Ampere | 1024 | 8GB LPDDR5 | 68GB/s | 40 TOPS | 7W~15W |
| Jetson Orin NX 16GB | Ampere | 2048 | 16GB LPDDR5 | 102.4GB/s | 100 TOPS | 10W~25W |
| Jetson AGX Orin 64GB | Ampere | 2048 | 64GB LPDDR5 | 204.8GB/s | 275 TOPS | 15W~60W |
注意看内存带宽这一列。Jetson Nano的25.6GB/s带宽放到今天已经很难支撑稍微复杂一点的模型,这也是为什么现在不建议再买Nano做新项目。Orin Nano的68GB/s带宽跑轻量级检测模型绰绰有余,但如果你要部署7B级别的LLM,8GB内存和68GB/s带宽就会非常吃力。Orin NX 16GB是我个人认为目前性价比最高的型号,102.4GB/s的带宽配合16GB内存,既能跑视觉模型,也能用4bit量化方式跑中小规模大模型。AGX Orin 64GB则是真正能接近桌面级体验的设备,适合做多模型并发或者需要大显存的场景。
1.2 选型中容易被忽略的隐藏成本
选型时还有三个容易被忽略的点。第一个是散热设计。Jetson Orin NX和AGX Orin在跑满负载时发热量很大,官方散热套件只在开放环境下表现尚可,一旦放进密封机箱,很容易触发降频。我见过不止一个项目因为没考虑散热,导致推理帧率从30FPS直接掉到个位数。如果产品是长时间高负载运行,建议直接预留主动散热方案,别指望被动散热能压住。
第二个是存储。Jetson设备默认使用SD卡或NVMe SSD启动。SD卡在频繁读写日志和模型权重时寿命下降很快,而且IO性能会直接影响推理时读取模型的速度以及训练时的数据加载效率。我现在的习惯是:SD卡只用来做系统引导,所有项目代码、数据集、模型文件全部放在外接SSD上。Orin系列开发套件都有M.2 Key M接口,建议优先用PCIe Gen4的NVMe SSD,性能差距感知非常明显。
第三个是网络接口。AGX Orin Developer Kit自带千兆网口,有些工业级载板还会集成2.5G网口或多个网口。如果项目涉及多路相机取流或者需要和上位机高频通信,网口数量和速率比CPU性能更值得关注。Jetson Nano的老款载板只有一个千兆网口,接相机和外网通信就需要USB转千兆网卡,稳定性会差一些,这也是老平台在实际项目中体验不佳的原因之一。
2. 刷机与系统初始化:JetPack版本的选择决定了后面所有环节
Jetson的系统不像普通PC装Windows那么随意,操作系统、CUDA、cuDNN、TensorRT是打包在一个叫JetPack的SDK里一起发布的。很多人前期忽略JetPack版本,后面装Python依赖时出现一堆版本冲突,根因往往是L4T内核和CUDA之间版本不匹配。
2.1 JetPack、L4T、CUDA三者的绑定关系
简单说,L4T(Linux for Tegra)是Jetson的底层系统内核和用户空间基础,JetPack是基于L4T之上的一整套SDK套件,包含CUDA、cuDNN、TensorRT、DeepStream等组件。三者的版本是绑定的,并不是说你想在Jetson Nano上装CUDA 12.4就能随便装。
以Orin系列为例,JetPack 5.x基于CUDA 11.4/11.8,JetPack 6.x基于CUDA 12.2/12.6。如果你在JetPack 5.x环境下用PyTorch 2.0以后版本跑模型,需要自己编译或寻找为L4T定制的wheel包,直接pip install安装的x86_64版本是跑不了的。
建议新项目全部使用JetPack 6.x,也就是内置CUDA 12.x系列环境的版本。原因有两点:一是最近两年NVIDIA官方以及社区预编译的PyTorch、ONNX Runtime、JAX的Jetson版本都以JetPack 6为主;二是JetPack 6的驱动对Orin平台的新特性支持更完整,例如DLA单元的初始化和TensorRT的版本兼容都做得更好。JetPack 5.x则可以作为老项目的兼容环境保留,但新项目起步别选它。
2.2 刷机流程的两种方式与关键参数
给Jetson刷系统,官方推荐用SDK Manager。SDK Manager会在x86主机上安装后,通过USB线连接Jetson设备,自动完成系统镜像烧录和SDK组件安装。这种方式最适合AGX Orin Developer Kit这种带USB Device口的产品。对于Orin Nano/NX这种使用SD卡或者NVMe启动的模块,也可以用SDK Manager选择直接把系统烧到SD卡或NVMe里,然后插到设备上启动,不用每次都用USB线连接。
手动烧写SD卡的流程也不复杂:下载官方镜像压缩包后用balenaEtcher烧录到格式化好的SD卡,首次开机进入系统后,再用SDK Manager或命令行安装剩余SDK组件。这种方式的好处是快,缺点是你需要自己管理依赖版本。
初始化完成后,别忘了做三件事。第一件事是检查运行模式:
sudo nvpmodel -m 0 # 0为最大性能模式,在Orin系列上通常对应15W/25W/40W等不同档位 sudo jetson_clocks # 锁定CPU/GPU最高频率,防止降频影响测试结果第二件事是确认基础环境:
nvcc -V # 查看CUDA版本 dpkg -l | grep TensorRT # 查看TensorRT版本 sudo apt-cache show nvidia-jetpack | grep Version # 查看JetPack版本第三件事是设置开机默认的电源模式并把nvpmodel服务设为自启动。如果不做这一步,设备重启后可能退回低功耗模式,导致推理性能大幅波动。这一点在交付项目时特别重要,很多客户反馈"重启后变慢",八成就是默认电源模式没设置好。
2.3 启动黑屏问题:十有八九是电源和显示器兼容性
热搜词里有"jetson orin nano 启动后黑屏",这个问题我在群里被人问了无数次。绝大多数情况不是板子坏了,而是下面几个原因。
电源不足排在第一位。Jetson Orin Nano的Developer Kit需要USB-C PD供电,官方要求15W~25W功率的电源适配器,有些劣质电源标注支持20W但实际电流输出不稳定,开机瞬间电流拉不上去就会黑屏或者循环重启。判断方法很简单:看电源适配器标签上的电流值,USB-C PD模式下建议选20V/3.25A这个档位。如果是Orin NX模块配合第三方载板,一定要查载板说明书确认需要的是12V还是5V供电,电压搞错了有烧板子的风险。
显示器兼容性排在第二位。Jetson的HDMI输出对部分4K显示器或特定分辨率支持不佳,表现就是开机后指示灯正常,但屏幕一直黑着。遇到这种情况,先换一块1080P显示器试试,或者用DP口输出。我遇到过Orin NX接某品牌4K显示器黑屏,但换了一台老款1080P显示器后一切正常的情况,属于驱动层面的兼容性瑕疵。
还有一个容易忽视的点:SD卡接触不良。插SD卡的瞬间如果没插到位,开机自检过不去,主板上的绿色指示灯会不亮或者闪烁。重新拔插SD卡,听到"咔哒"声到位后再开机,能解决一部分"黑屏"。
如果以上都排查过了仍然黑屏,可以接串口线看启动日志。Jetson的Developer Kit排针上有UART调试口,用USB转TTL小板连接后,在主机上用minicom或screen打开串口,能看到内核启动到哪一步崩了——这比蒙着猜靠谱得多。能走到串口日志这一步,排障思路基本就入了门。
3. 视觉推理链路的完整搭建:以YOLOv5在Jetson上的部署为例
Jetson平台上最经典的任务就是目标检测。YOLOv5因为生态成熟、教程多、PyTorch权重转ONNX和TensorRT的资料齐全,适合作为第一个跑通的完整项目。这个链路走通之后,换成YOLOv8、YOLOv9或者自定义模型,套路基本一致。
3.1 从PyTorch到TensorRT:模型转换的完整流程
在Jetson上部署YOLOv5,推荐路径是PyTorch模型先转ONNX,再转TensorRT engine。有人会问,为什么不直接用PyTorch做推理?Jetson上PyTorch推理走的是CUDA,性能其实能用,但TensorRT在推理速度上通常有1.5倍到3倍的提升,而且INT8量化后还能更快。对于边缘设备来说,这差别可能就是"能用"和"好用"的距离。
先说一下ONNX转TensorRT的方式。YOLOv5官方仓库里已有现成的export.py,支持直接导出TorchScript、ONNX甚至TensorRT engine:
python export.py --weights yolov5s.pt --include onnx engine --device 0 --half这里有个容易踩的坑:直接在Jetson上用export.py导出engine,走的是TensorRT Python API,过程中极容易出现Dynamic shape设定的问题。因为YOLOv5默认的推理shape是动态的,而TensorRT在构建engine时要固定最小、常规、最大三档shape。如果不指定,默认可能是[1, 3, 640, 640]这种固定尺寸,后续摄像头输入尺寸不同就会报错。
更稳妥的做法是先导出ONNX,再使用trtexec命令手动构建engine:
trtexec --onnx=yolov5s.onnx --saveEngine=yolov5s_fp16.engine --fp16 --minShapes=images:1x3x640x640 --optShapes=images:1x3x640x640 --maxShapes=images:1x3x640x640trtexec是TensorRT自带的命令行工具,用它可以方便地测试不同batch size、精度模式下的性能。也有人使用TensorRT的Python API构建engine,灵活度更高,但前期调试不如trtexec直观。
3.2 推理脚本的改造:不能直接套用桌面端代码
拿到engine文件后,推理代码不能直接套用桌面端的YOLOv5检测脚本,因为engine的后处理部分需要自己处理。YOLOv5的TensorRT输出通常是一个[batch, 25200, 85]的张量,25200是三个尺度预测框的总数,85是box(4) + objectness(1) + class probabilities(80)。你需要自己解析这个张量,做NMS(非极大值抑制),再把box坐标缩放到原图尺寸。
这个解析过程很容易出错。我建议是直接参考YOLOv5仓库里utils/general.py的non_max_suppression函数,自己实现一个纯TensorRT版本的NMS算子。Jetson的TensorRT支持EfficientNMS插件,但版本之间API有变化,前期为了跑通,直接用PyTorch的NMS逻辑配合NumPy处理也未尝不可,只是速度会稍慢,顺畅跑通后再换成插件。
在Jetson上有两个提升推理速度的额外手段:
第一个是启用CUDA Stream。TensorRT推理默认是同步模式,意味着推理期间CPU在等待GPU计算完成。使用多线程或者CUDA Stream可以让图像预处理和推理重叠,实际吞吐量能提升20%到40%。我的做法是开两个线程,一个线程负责从摄像头拉流和图像预处理,另一个线程负责推理,中间用队列做缓冲。数据送到GPU显存之后,把预处理和推理放进同一个CUDA Stream里,减少host和device之间同步次数。
第二个是使用内存池。反复调用TensorRT引擎时会频繁分配显存,Jetson上显存和内存共享,频繁的分配/释放会引入内存碎片。正确做法是engine构建时设置setMemoryPoolLimit,给激活张量指定一个初始显存池,运行时复用这块空间。
3.3 实测性能对比:FP16与INT8的使用场景
用YOLOv5s在Jetson Orin NX 16GB上做了一组对比实验,输入尺寸640x640,情况如下:
| 推理方式 | 平均延迟 | 帧率(单路) | 相对PyTorch提升 |
|---|---|---|---|
| PyTorch FP32 | 约19ms | 52FPS | 1x |
| ONNX Runtime FP32 | 约15ms | 66FPS | 1.27x |
| TensorRT FP16 | 约6ms | 166FPS | 3.19x |
| TensorRT INT8 | 约4ms | 250FPS | 4.8x |
对大多数目标检测场景,FP16已经够用,精度损失在1%以内完全可接受。INT8需要额外准备校准数据集,如果校准集和实际场景差异大会出现精度抖动,例如漏检率偏高。我的建议是做产品优先用FP16,推理速度不够再考虑INT8,而且要准备500张以上能覆盖真实场景的校准图片,不能随便抓几张图凑数。
3.4 部署时的版本匹配问题
YOLOv5部署中频繁出现的报错,有一大半来自PyTorch、TorchVision、TensorRT的版本不匹配。Jetson上安装PyTorch建议使用NVIDIA官方发布的JetPack对应版本。JetPack 6.x对应的PyTorch wheel在NVIDIA论坛和官网Index中有提供,不要从PyTorch官网直接下载x86_64包安装。
判断当前PyTorch是否为Jetson对应版本,可以在Python里执行:
import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.version.cuda)如果torch.cuda.is_available()返回False,大概率装了CPU版本。如果是True但报算子不支持的错,检查torch.version.cuda是否和nvcc -V的CUDA版本一致。Jetson上这两个版本不一致也是在所难免的事情,最省事的办法是重新从NVIDIA官方渠道安装匹配的wheel包。为了不再被这块坑到,我现在会把常用的PyTorch wheel下载后存放在本地,换设备时直接安装,省得每次都在网上翻找。
4. 大模型和SLAM类任务上Jetson:从Ollama跑Qwen到资源分配
今年明显感觉到,越来越多的Jetson项目开始把大语言模型部署到边缘设备上,典型需求是语音助手、本地知识库问答、农业领域的边缘问答系统。同时,无人机和机器人领域的视觉SLAM类任务(比如热词里提到的"AirSLAM Jetson部署")也在Jetson平台上有不少实践。这两类任务和传统视觉检测相比,资源分配逻辑差别很大。
4.1 如何在Jetson Orin Nano/NX上跑Qwen
在Jetson上部署Qwen这类大模型,最简单的方式是使用Ollama。Ollama原生支持Jetson的CUDA加速,安装后能自动识别GPU并利用JetPack环境。
JetPack 6.x上的安装非常简单:
curl -fsSL https://ollama.com/install.sh | sh ollama run qwen2.5:7b但是注意,Orin Nano 8GB直接跑7B模型默认会用Q4_K_M量化,依然可能出现上下文较长时内存不足。跑大模型之前,我建议先做一次内存和交换空间检查:
free -h # 查看内存和swap空间 cat /proc/meminfo | grep -E "MemTotal|SwapTotal"8GB内存的Orin Nano在跑7B模型时,建议把上下文长度限制在2048以内。实测如果开4096上下文,生成过程中显存的峰值会显著上升,一旦超过物理内存,系统就会疯狂swap,速度从每秒20 token掉到每秒3 token左右,几乎不可用。16GB的Orin NX则可以从容很多,能跑7B模型加2048上下文同时还有余量做另一路视觉推理。
如果Ollama跑Qwen7B速度不够满意,可以换用更小的qwen2.5:3b或者qwen2.5:1.5b。3B模型在Orin NX上能跑到每秒40~60 token,在Orin Nano上也有20~30 token,用于对话和摘要完全够用。另外需要做残差量化切换时,Ollama的GGUF模型文件也可以直接用ollama run配合OLLAMA_MODEL环境变量指定路径,把模型放在SSD上能明显减少加载时间。
4.2 SLAM类任务在Jetson上的部署要点
我实际接触过的视觉SLAM部署项目,最痛的点是实时性。AirSLAM这类基于视觉惯性导航的算法,需要做特征提取、位姿估计、回环检测,这些在x86 CPU上通过多核并行能跑下来,但到了Jetson上,如果不对GPU加速,帧率很容易撑不住10FPS。
部署SLAM类任务,我的经验是先分清楚哪些模块是CPU密集、哪些是GPU可加速的。特征提取和描述子计算通常可以换成GPU版本,比如使用Orb-SLAM的CUDA变体或者用TensorRT加速SuperPoint/SuperGlue这类深度学习特征模型。位姿优化和回环检测基本还是CPU任务,Jetson的CPU在高负载下为了保GPU频率会限频,所以需要在JetPack里配置CPU核心数和调度策略。Orin NX有8个Core的Cortex-A78AE,我在部署时会把特征提取线程绑定到CPU4-7,把后端优化线程绑定到CPU0-3,避免线程频繁迁移造成缓存失效。
内存占用也需要提前规划。SLAM通常需要保存历史关键帧的位姿、地图点和描述子,长时间运行内存会线性增长。在Jetson上跑SLAM常采用两种手段控制内存:一是设置滑动窗口,只保留最近N帧关键帧,超过就丢弃;二是使用DBoW2词袋模型做回环检测,同时不断压缩地图点数量。AirSLAM这类算法本身有内存管理机制,但在部署时还是要做足压力测试,防止长时间运行后内存耗尽导致进程被杀。
4.3 多任务并发时的资源分配思路
很多无人车和机器人项目并不只是单一模型的任务。一台Jetson Orin NX可能需要同时跑目标检测、语义分割、大模型语音交互、SLAM定位。这时候资源分配就是一个系统级设计问题。
我常用的分配策略如下:将GPU的CUDA核心和内存划分为多个上下文,每个任务使用独立的CUDA Stream。不要把所有任务塞进同一个TensorRT上下文,否则调度抖动会很大。CPU端使用taskset绑定核心,对于周期性任务(如SLAM)设置实时优先级,但要注意不要把CPU完全跑满,留15%的余量给系统进程。内存方面需要预先统计每个任务的峰值内存,如果总和超过物理内存,就要做取舍,例如将大模型量化进一步降低到3B级别,或者降低检测模型输入分辨率。
JetPack 6还提供了NVIDIA的nvpps工具(NVIDIA Performance Profiling System),可以监控每个进程的CPU、GPU、显存使用情况。部署前先用nvpps跑一轮压力测试,找出哪个任务吃掉最多资源,再针对性地优化,比盲目改代码有效得多。
5. TensorRT量化与推理优化:把硬件性能榨干的关键
前面提到FP16和INT8,但真正想把Jetson硬件性能榨干,光靠TensorRT自动优化是不够的。你还需要理解TensorRT的工作原理、量化方式,以及如何从算法层面消减开销。
5.1 TensorRT为什么能加速:图层融合与内核自动调优
TensorRT加速的核心有两个方向:图层融合和内核自动调优。图层融合是指把多个连续的计算步骤合并成单一算子,典型的是把Conv+BatchNorm+ReLU融合成一个CBR算子,减少kernel启动和显存读写的开销。对于ResNet这类结构规整的模型,融合后的网络可以减少30%到50%的运行节点。内核自动调优是TensorRT为每个算子选择最优的实现,同一个卷积操作,Tactics中可能有几十种不同的cuDNN/自定义kernel实现,TensorRT会在构建engine时逐一评估,挑选出当前shape下延迟最低的方案。这也是为什么TensorRT构建engine的时间往往很长,因为它相当于在做一次穷举搜索。
这个机制也解释了为什么TensorRT对固定输入shape的效果最好。如果输入shape频繁变化,TensorRT不得不为多个shape保留多个kernel实现,显存占用上升,部分场景下反而比动态shape优化前更慢。
5.2 INT8量化的完整流程:校准数据决定精度
TensorRT的INT8量化并不是直接把FP32权重收缩成8位整数那么简单,它默认采用后训练量化(PTQ),需要一个校准步骤来统计激活值的分布范围,然后据此计算量化缩放因子。
命令行方式:
trtexec --onnx=model.onnx --saveEngine=model_int8.engine --int8 --calib=calibration.cache其中calibration.cache是校准缓存文件,需要提前通过TensorRT Python API生成:
import tensorrt as trt def get_calibrator(calib_data): return trt.IInt8LegacyCalibrator(calib_data) # 构建INT8 engine时传入calibrator,TensorRT会遍历校准集 # 计算每个激活张量的min/max或直方图分布,生成calibration cache校准数据的选择是INT8量化成败的核心。一定不能只用ImageNet的自然图片,对于工业检测场景要用你实际拍摄的生产环境图片,且最好能覆盖光照变化、目标遮挡、背景多样性。我用YOLOv5s做过实验,用500张检测工位实拍图校准的INT8模型,mAP@0.5只下降了1.2%;但如果用自然图片校准,同样模型在工位场景下的漏检率会翻倍。
校准图片数量一般在100到1000张之间。太少统计不准,太多校准时间过长且收益递减。校准完成后生成的cache文件要保留,下次构建engine可以直接复用,不必重新校准。
5.3 常见的TensorRT精度与速度问题排查
构建engine时会遇到性能不符合预期的情况。常见原因有两个:
第一个是动态shape把优化范围拉大了。如果minShapes和maxShapes跨度太大,TensorRT会为每个范围生成多套优化,导致engine体积变大,推理速度可能反而下降。解决办法是尽量固定输入尺寸,或者缩小动态范围。对于视频检测任务,完全可以固定分辨率,只在模型输入的预处理里做letterbox。
第二个是batch size设置。TensorRT在batch size=1时对算子做了深度优化,但如果你的业务场景需要GPU满负荷,试试batch大小设置为2或4。这里有一个平衡:增大batch会提升吞吐量,但单帧延迟会上升。实时视频流场景更关注延迟,所以batch size=1往往是正确的选择;离线批量处理场景更关注吞吐,可以适当增大batch。
我习惯在构建engine后先用trtexec测一遍延迟曲线:
trtexec --loadEngine=model_fp16.engine --shapes=images:1x3x640x640 --duration=10如果平均延迟异常高,再回头检查输入shape设定和是否启用了DLA。DLA(Deep Learning Accelerator)是Orin系列保留的专用加速单元,可以运行部分算子,但只支持很少的算子类型,如果是自定义算子或特殊层,放到DLA上反而会拖慢。默认情况下把DLA留给固定结构CNN网络的部分层使用,动态结构网络建议完全关闭DLA。
5.4 DeepStream与高效后处理
视觉项目中如果存在多路视频流,可以考虑使用DeepStream框架。DeepStream是基于GStreamer和TensorRT构建的多路视频分析框架,它能帮你管理多路流的硬件解码(NVDEC)、批处理、推理和编码输出。Jetson平台上硬解H.264/H.265的能力非常强,Orin NX能同时解码20路以上1080P视频流,这是CPU解码完全做不到的。
不少人在单路摄像头项目里强行引入DeepStream,反而是过度设计。DeepStream适合摄像头路数较多(4路以上)且需要统一管线的场景。如果只做单路或双路检测,自己用GStreamer拉流加GstRtspOverlay等插件拼一条Pipeline可能更灵活。
6. 稳定性与排障:从启动黑屏到运行卡顿的排查思路
最后这部分是实际交付项目时最容易被忽视、也最影响用户体验的环节。Jetson毕竟不是数据中心里的服务器,供电、散热、存储都会在长时间运行时暴露问题。
6.1 从电源到风扇:运行不稳定的常见根因
我在多个项目里遇到过同样的现象:设备刚开机一切正常,跑几分钟后帧率下降、风扇猛转甚至死机。排查思路按优先级排列,先看温度再看电源。
查看温度和功耗状态:
sudo tegrastatstegrastats输出里的CPU [email protected]和GPU [email protected]是当前实时的CPU和GPU占用率,RAM项显示内存使用情况,AO@32C和GPU@45C分别是各传感器温度。如果GPU温度超过85°C,降频是必然的,需要从散热层面解决。Jetson Orin NX在载板上有风扇接口,BIOS中默认风扇策略可能偏保守,可以用jetson-clocks配合自定义风扇控制脚本,让温度超过60°C时自动拉满风扇转速。
电源不稳的表现更隐蔽。Jetson设备在峰值功耗时,如果电源输出电流不够,电压会跌落,系统表现为随机重启、USB设备认不到、模型推理突然中断。官网对每个型号都标了推荐的电源规格,Orin Nano建议20W,Orin NX建议25W以上,AGX Orin根据负载可能要到60W。我建议直接买功率余量充足的电源,例如给Orin NX配一台60W氮化镓适配器,电压跌落的风险会小很多。
6.2 Swap与文件系统:长时间运行的内存问题
Jetson的8GB/16GB内存在AI任务中非常容易紧张。如果内存不够,Linux内核会触发OOM Killer,直接杀掉占用最高的进程。这是部署大模型时进程莫名消失的头号原因。
缓解方案有两种。第一种是加大swap空间,官方推荐在NVMe SSD上创建swap文件:
sudo fallocate -l 8G /mnt/ssd/swapfile sudo chmod 600 /mnt/ssd/swapfile sudo mkswap /mnt/ssd/swapfile sudo swapon /mnt/ssd/swapfile注意swap不能放在SD卡上,否则频繁交换会加速SD卡损坏。第二种是使用ZRAM。Jetson的Ubuntu系统在较新版本中默认启用了zram,它利用压缩算法在内存中虚拟出更多空间。但ZRAM对CPU有额外消耗,如果CPU已经满负载,ZRAM会导致推理延迟上升。建议根据实际负载权衡,我通常在纯推理场景用swap不用ZRAM,在跑大模型场景两者都开启并把swap优先级调低。
文件系统方面还有一个经验:Jetson的eMMC或SD卡不宜长期写入高频率日志。生产环境建议将日志输出到tmpfs(内存文件系统)或者外接SSD上的指定分区,并且启用logrotate做日志轮转,否则一年半载后系统盘写满,设备表现会越来越慢。
6.3 开机自启与异常恢复机制
交付设备时,开机自启是必须做的。我的方案是编写一个systemd服务,负责拉起AI推理主程序,并配置自动重启:
[Unit] Description=AI Inference Service After=network.target [Service] ExecStart=/home/user/start_inference.sh Restart=always RestartSec=5 [Install] WantedBy=multi-user.target启动脚本里还需要检查GPU和关键服务状态,比如等待Ollama服务就绪后再启动推理程序,避免因依赖未启动导致崩溃。如果主程序发生段错误或OOM被杀,systemd的Restart=always会自动拉起,这对无人值守设备非常关键。
再高级一点的做法是添加看门狗。Jetson支持硬件看门狗触发复位,可以在系统无响应时自动重启。开启方式是把/etc/systemd/system.conf的RuntimeWatchdogSec设为30秒左右。这只用于兜底,正常情况下程序卡死还是优先用systemd的进程级重启。
6.4 一套实用的首轮排障清单
结合我自己的使用经验,Jetson设备出问题时,按下面这个顺序排查效率最高:
- 指示灯状态。正常启动时电源灯常亮,活动指示灯闪烁。如果灯不亮,先排除电源线和适配器。
- 串口日志。接上USB转TTL,观察内核启动的最后输出,是停在U-Boot、内核还是文件系统挂载。
- tegrastats观察温度、功耗、内存。
- 查看内核日志:
dmesg | tail -50,OOM、驱动加载失败、i2c错误都会在这里。 - 查看systemd服务状态:
systemctl --failed。 - 最后再看应用日志。
这套顺序能把大部分"玄学问题"定位到具体层面,避免重复刷系统。
如果你是用Jetson做AI应用开发的新手,我的建议是先把手上的板子按这篇文章梳理的链路完整走一遍——选型参考、刷JetPack 6、跑一个YOLOv5的TensorRT推理、再用Ollama跑通一个小模型。这个过程走完,你对Jetson平台的核心知识就建立了体系感。后续遇到新模型新框架,本质上都是在往这个框架里填细节。面试也好,做项目也罢,能讲清楚"为什么在Jetson上要用TensorRT而不是纯PyTorch"、"为什么INT8需要校准集"、"启动黑屏如何排查",就已经比大多数只在桌面端写过AI代码的开发者有优势了。
有一点我在多个项目里反复验证过:Jetson平台开发最大的壁垒不是模型算法本身,而是对整个软硬件链路的把控能力。你能不能让模型在功耗约束下稳定跑起来,能不能在内存紧张时保证长期运行不崩,这才是边缘AI开发真正考验人的地方。把这篇串讲里的每个环节都亲手跑一遍,你会少走很多弯路。