一句话先说结论:8GB 的 Jetson Orin Nano Super,用 MLC-LLM 跑 Qwen2.5-1.5B 实测 60 tok/s,跑 3B 也有 33 tok/s,首 token 延迟不到 0.2 秒,峰值内存 4.44GB / 5.02GB,全程不 OOM。这篇把从踩坑到跑通的全过程写出来,你照着做也能复现。


一、先说背景:为啥折腾这么个东西

咱手里有块 Jetson Orin Nano Super 8GB,就那种巴掌大的边缘 AI 小板子。8GB 统一内存,CPU 和 GPU 共享,sm_87 架构,1024 个 CUDA 核。

之前一直在上面折腾部署大模型,走的是 TensorRT-Edge-LLM 路线。0.5B 模型倒是跑通了,实测 21.9-30.5 tok/s,TTFT 1.9 秒,峰值内存 4.23GB。但想上 1.5B 的时候,五次 OOM,五次——构建期峰值内存直接撑爆 8GB,1.5B 那张 445MB 的 embedding 表就是压死骆驼的最后一根稻草。

后来调研了一圈,发现 MLC-LLM 这条编译器路线恰好能绕开这个坑:编译在 PC 上做(或者容器里 JIT),构建期内存压力根本不出现在 Jetson 上。加上 q4f16_1 量化把权重从 3GB 压到 840MB,8GB 跑 1.5B 甚至 3B 都有戏。

那就干。这篇博客记录的是真机实测全过程,不是纸上谈兵。


二、实验环境一览

先交代下家底:

项目配置备注
设备Jetson Orin Nano Super 8GBNVIDIA 边缘 AI 设备
SoCOrin(sm_87,Ampere)1024 CUDA 核,128-bit LPDDR5
内存8GB 统一内存CPU+GPU 共享,系统占用后可用 7.6GB
存储937GB NVMe SSD存模型绰绰有余
功耗模式MAXN_SUPER(25W)拉满性能模式
JetPack6.2(R36.5.0)CUDA 12.6.x
容器dustynv/mlc:0.20.0-r36.4.06.9GB,内置 MLC-LLM v0.20.0 全家桶
量化q4f16_1int4 权重 + fp16 激活

模型选了两个:

  • Qwen2.5-1.5B-Instruct:1.54B 参数,权重 840MB(30 个 shard)
  • Qwen2.5-3B-Instruct:3.09B 参数,权重 1.9GB(62 个 shard)

两个都是 32K 上下文窗口,q4f16_1 量化格式——HuggingFace 上 mlc-ai 官方组织有预转换好的,直接下就能用。


三、原理速通:为啥 MLC 行而 TRT 不行

不懂原理直接照抄容易翻车,花三分钟讲清楚。

TRT-Edge-LLM 的问题:引擎必须在 Jetson 上构建,构建期峰值内存 = 权重 × 2.5~3 + builder。1.5B 的 embedding 层(445MB)在 TRT 下还不能量化,直接 OOM。

MLC-LLM 的解法:它是编译器路线——不是在运行时解释执行 ONNX,而是用 TVM 把模型编译成 Jetson 专属的 CUDA 库(.so)。编译可以在 PC 上做(交叉编译),也可以在容器里 JIT 编译。关键是:构建内存压力不出现在你的 Jetson 上

再加上 q4f16_1 量化:权重压成 int4(每 4 bit 存一个权重 + 每组一个 fp16 scale),激活保持 fp16。1.5B 权重从 3GB 压到 840MB,省了 70%。

路线本质8GB 的痛点
TRT-Edge-LLM运行时解释执行 plugin ONNX必须在 Jetson 上构建,1.5B 直接 OOM
MLC-LLM编译器把模型变成专属 CUDA 程序编译在 PC/容器完成,8GB 只承担运行期

一句话:MLC 把"构建"和"运行"解耦了,8GB 只管跑,不管编译。


四、实操开始:从零到跑通

4.1 环境检查

先把基础环境确认一遍:

# 一键检查
./jetson-run.sh check

输出长这样就 OK:

R36.5.0 JP6.2 ✅
716GB 磁盘 ✅
Docker + nvidia-runtime ✅
MAXN_SUPER ✅

然后挂个 swap 防止 JIT 编译时 OOM(这步很重要,别跳):

./jetson-run.sh swap-on
# 结果:8G swap 已挂载 ✅

4.2 拉容器

dustynv 是 NVIDIA Jetson 生态的知名维护者,他维护的 MLC 容器跟 JetPack 版本严格对应,拿来就能用:

sudo docker pull dustynv/mlc:0.20.0-r36.4.0
# 6.9GB,拉一次就行

这个镜像里东西很全:CUDA 12.6、cuDNN、CUTLASS、FlashAttention-2、PyTorch 2.8、flashinfer、完整的 MLC-LLM v0.20.0 环境。不用自己从源码编译,省好几个小时。

4.3 下载权重(第一个坑来了)

这里我踩了第一个坑。容器里直接 git clone huggingface.co,exit 128,连不上——国内网络限制嘛。

解决方案很简单,宿主机走镜像站下:

export HF_ENDPOINT=https://hf-mirror.com
hf download mlc-ai/Qwen2.5-1.5B-Instruct-q4f16_1-MLC \
  --local-dir ~/work/mlc/models/Qwen2.5-1.5B-Instruct-q4f16_1-MLC
# 840MB,嗖嗖的就下完了 ✅

划重点:HuggingFace 上 mlc-ai 官方组织已经有 Qwen2.5 系列的 q4f16_1 预转换格式了,不用自己跑 convert_weight,直接下就能用。3B 的也一样,改个 repo 名就行。

4.4 启动服务(第二个坑)

这里踩了第二个坑——参数不兼容。网上很多教程用的是老版本参数 --max-batch-size 1 --max-total-sequence-length 4096,但 v0.20.0 改了参数体系,变成 --overrides 了。

# ❌ 老版本写法(v0.20.0 不认)
--max-batch-size 1 --max-total-sequence-length 4096

# ✅ v0.20.0 正确写法
--overrides "max_num_sequence=1;max_total_seq_length=4096"

完整的启动命令长这样:

sudo docker run -d --runtime nvidia --name mlc-serve --network=host \
  -v ~/work/mlc:/workspace -w /workspace \
  dustynv/mlc:0.20.0-r36.4.0 \
  mlc_llm serve /workspace/models/Qwen2.5-1.5B-Instruct-q4f16_1-MLC \
    --device cuda:0 --host 0.0.0.0 --port 8000 \
    --mode local --overrides "max_num_sequence=1;max_total_seq_length=4096"

启动后看日志,几个关键信息:

  • JIT 编译:约 1.5 分钟(首次跑会编译模型库,之后就缓存了)
  • 内存估算:3670MB(Parameters 828MB + KVCache 174MB + Temporary 2668MB)
  • 端口:8000 ✅
  • 引擎模式:local(单并发优先,边缘设备就该这么配)

4.5 性能测试

./benchmark.sh

结果出来的那一刻,说实话有点激动:

指标数值评价
TTFT(首 token)0.077s快到离谱
生成速度60.05 tok/s远超预期
生成 token 数135
总时延2.308s
峰值内存4.44GB / 7.6GB余量 3.1GB
整机功耗20.2W 峰值在 25W 上限内
GPU 利用率96% @ 1013MHz满负荷
GPU 温度56.8°C非常健康

60 tok/s! 之前文档给的预期是 20-40 tok/s,实测直接翻倍。对比之前 TRT 跑 0.5B 才 21.9-30.5 tok/s,这次是 1.5B 模型跑出 2-2.7 倍速度,还有之前用相同硬件使用llama.cpp部署qwen2.5-1.5B_Q4_K_M 的速度只有38.37 tok/s,几乎翻倍,当然这是因为它们量化程度不同。


五、上 3B:第三个坑

1.5B 跑通了,心就大了——能不能上 3B?

5.1 脚本参数化

先把脚本改成支持环境变量切换,MODEL_SIZE 默认 1.5B,设成 3B 就切大模型:

# 下 3B 权重
MODEL_SIZE=3B ./jetson-run.sh download
# 1.9GB,62 个 shard ✅

5.2 内存优化(第三个坑)

3B 模型默认的 context_window_size 是 32768(32K),直接跑会 OOM——这是第三个坑。

默认配置会按 32K 上下文预分配内存池,8GB 上根本扛不住。解决方案是一套参数组合拳压下去:

--overrides "max_num_sequence=1;max_total_seq_length=2048;context_window_size=2048;prefill_chunk_size=1280"

四个参数各自的作用:

参数默认值压成省了啥
max_total_seq_length40962048KV pool 省 0.5-1GB
context_window_size327682048避免 32K 预分配(最大的坑)
prefill_chunk_size20481280削减 prefill 激活峰值
max_num_sequence1防并发翻倍

5.3 启动 + 测试

MODEL_SIZE=3B MAX_SEQ_LEN=2048 ./jetson-run.sh serve

启动观察:JIT 编译约 3-5 分钟(比 1.5B 长一倍),内存稳定,swap 用了 348MB(JIT 阶段,推理时基本不用),无 OOM。

MODEL_SIZE=3B ./benchmark.sh

3B 测试结果:

指标数值评价
TTFT0.175s依然很快
生成速度33.11 tok/s实用速度
峰值内存5.02GB / 7.6GB余量 2.5GB
功耗21.4W在 25W 内
GPU 利用率99% @ 1013MHz满负荷
GPU 温度60°C健康

3B 跑 33 tok/s,内存才 5.02GB,还剩 2.5GB 余量。8GB 跑 3B 大模型,真成了


六、数据对比:一目了然

6.1 1.5B vs 3B 正面刚

指标1.5B3B变化评价
生成速度60.05 tok/s33.11 tok/s-45%3B 慢 1.8x,但实用
TTFT0.077s0.175s+127%都在 0.2s 内
峰值内存4.44GB5.02GB+13%只多 0.58GB
内存余量3.1GB2.5GB-0.6GB3B 仍有余量
功耗20.2W21.4W+6%都在 25W 内
GPU 利用率96%99%+3%都满负荷
GPU 温度56.8°C60°C+3°C都健康
权重大小840MB1.9GB+126%3B 多 1.1GB

6.2 跟之前的 TRT 0.5B 横比

这才是最直观的——同样 8GB 设备上:

指标MLC 1.5BTRT 0.5B差距
生成速度60 tok/s21.9-30.5 tok/sMLC 快 2-2.7x
TTFT0.077s1.9sMLC 快 25 倍
峰值内存4.44GB4.23GB基本持平
模型规模1.5B0.5BMLC 支持大 3 倍的模型
流式输出原生支持要改源码重编译MLC 开箱即用

同样 4.4GB 内存,MLC 跑的模型大了 3 倍,速度快了 2 倍多,TTFT 快了 25 倍——q4f16 量化的威力全在这张表里了


七、1.5B 还是 3B?看你的场景

跑通两个模型后,怎么选?我给个参考:

选 1.5B 的场景

  • 实时对话系统(60 tok/s 响应飞快,用户基本不用等)
  • 多用户并发场景(3.1GB 内存余量大,扛得住)
  • 简单问答任务(1.5B 的智能能力够用了)
  • 功耗敏感场景(20.2W 更省电)

选 3B 的场景

  • 复杂推理任务(3B 智能能力显著更强)
  • 专业领域应用(质量优先于速度)
  • 单用户或低并发(2.5GB 余量足够)
  • 能接受 33 tok/s 的响应速度(其实也不慢)

切换也很方便,一条命令搞定:

# 跑 1.5B
./jetson-run.sh serve

# 跑 3B(压参数)
MODEL_SIZE=3B MAX_SEQ_LEN=2048 ./jetson-run.sh serve

两个模型一分钟内就能切换,完全可以按需来。


八、三个坑总结(避坑指南)

这次实操踩了三个坑,汇总一下帮大家避雷:

#现象解法
1HuggingFace 连不上容器内 git clone exit 128宿主机走HF_ENDPOINT=https://hf-mirror.com 镜像站下载
2参数不兼容v0.20.0 不认--max-batch-size--overrides "max_num_sequence=1;max_total_seq_length=4096"
33B 默认 32K 上下文 OOM启动直接撑爆内存压参数:context_window_size=2048;max_total_seq_length=2048;prefill_chunk_size=1280

还有几个容易忽略的点

  • 一定要挂 swap:JIT 编译阶段会吃额外内存,8GB 上不挂 swap 偶尔会 OOM,挂个 8G swap 就稳了
  • 功耗模式拉满:务必确认是 MAXN_SUPER(25W),不然性能打折
  • 版本要统一:容器版本(0.20.0-r36.4.0)、MLC 版本(v0.20.0)、JetPack 版本(6.2/R36.4)三者要匹配,别混用

九、验证流式输出(ROS2 集成预备)

MLC 的 serve 是 OpenAI 兼容 API,流式输出开箱即用。curl 验证一下:

curl -N http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"Qwen2.5-1.5B-Instruct-q4f16_1-MLC","messages":[{"role":"user","content":"你好"}],"stream":true,"max_tokens":64}'

能看到 data: {"choices":[{"delta":{"content":"..."}}]} 逐 token 往外吐——这就是真流式。对比之前 TRT-Edge-LLM v0.6.0 要改源码重编译才能流式,MLC 这一点太省心了。

后续接 ROS2 的话,直接让节点请求 /v1/chat/completions?stream=true 就行,不用自己造轮子。


十、这套方案凭啥能成

最后总结一下这次实验的核心发现,四个关键点:

1. 编译器路线绕开了 8GB 构建红线

之前 TRT 跑 1.5B 五次 OOM 的根因是"构建必须在 Jetson 上做"。MLC 把编译放到了容器里(JIT)或 PC 上(交叉编译),8GB 只管运行,构建内存压力根本不出现。这次 1.5B 和 3B 全程零 OOM。

2. q4f16 量化是内存账本的关键

1.5B 权重从 3GB 压到 840MB,3B 从 6GB 压到 1.9GB,省了 60-70%。而且量化在编译期就完成了,运行时零开销——GPU 利用率 96-99% 说明 kernel 效率极高,量化没拖性能后腿。

3. 参数压降是 3B 能跑的最后一道保险

3B 默认 32K 上下文是最大的坑,不压就是 OOM。context_window_size=2048 + prefill_chunk_size=1280 这套组合拳把内存从理论 5.5-6GB 压到实际 5.02GB,留了 2.5GB 余量。

4. dustynv 容器是最快的落地路径

不用从源码编译 TVM + MLC-LLM(那得好几个小时),拉个 6.9GB 镜像就齐活了。JIT 编译 1.5B 才 1.5 分钟,3B 也就 3-5 分钟,首次跑完之后缓存复用,秒级启动。


十一、下一步:还能更快

跑通基线之后,还有两条提速路线:

路线一:PC 交叉编译(消除 JIT 开销)

  • 在 PC 上用 mlc_llm compile --host aarch64-unknown-linux-gnu 编出 sm_87 的 .so
  • scp 拷回 Jetson,启动时直接加载,省掉 JIT 编译等待
  • 我已经写好了完整的 Dockerfile + 交叉编译脚本三件套,可以复用

路线二:EAGLE 推测解码(预期再提速 1.5-1.8x)

  • 给目标模型挂一个 68M 参数的轻量预测头,让它"预判"下一个 token,再由目标模型一次验证
  • 数学上保证无损(输出分布和普通解码完全一致)
  • 1.5B 从 60 tok/s 预期能冲到 90-100 tok/s
  • MLC 的 serve 原生支持 --speculative-mode eagle,腾讯 AngelSlim 在 HF 上发布了 Qwen2.5 系列的 EAGLE3 head,不用自己训练

这两条路可以叠加:先用交叉编译消 JIT,再上 EAGLE 提速,最终在 8GB 上跑到接近 100 tok/s 不是梦。


写在最后

8GB 的小板子跑 1.5B 大模型飙到 60 tok/s、跑 3B 也有 33 tok/s——放一年前这事想都不敢想。关键是选对路线:TRT 的"设备上构建"思路在 8GB 上走不通,MLC 的"编译器 + 量化 + 构建运行解耦"三件套正好打中所有痛点。

如果你也在 Jetson 上折腾大模型部署,强烈建议直接上 MLC-LLM + dustynv 容器这条路,少走弯路。文中的脚本和命令都是真机跑通的,照着敲就能复现。

完整实验数据已整理提交github https://github.com/X32/tensorRT_ONNX。


如果这篇博客对你有帮助,点个赞 + 收藏 + 关注三连呗 👍

后续会更新 ROS2 集成和 EAGLE 推测解码实测,感兴趣的朋友关注别走丢。

转载请注明出处,感谢支持!

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐