Jetson TensorRT vs RK3588 RKNN:两块板子都跑通了 LLM 和 VLM 之后,我悟了

Jetson TensorRT vs RK3588 RKNN:两块板子都跑通了 LLM 和 VLM 之后,我悟了

先交代背景:我手头有两块边缘设备,一块 NVIDIA Jetson Orin(8GB,GPU 路线),一块 Orange Pi 5 Plus(RK3588,16GB,NPU 路线)。过去一段时间我把 LLM 和 VLM 在两块板上各部署了一遍------Jetson 上用过 TensorRT、TensorRT-Edge-LLM、MLC-LLM、llama.cpp,RK3588 上用 rknn-llm 官方工具链跑通了文本和多模态。全部真实数据,全部亲自踩坑。

折腾完回头一看,发现一个特别有意思的事:这两套看起来八竿子打不着的工具链,骨子里是同一套范式。今天就把两边的部署过程摊开对比,聊聊哪里像、哪里不像、选型该怎么选。

🧰 两套工具链长啥样

先把两边的"全家福"摆出来:

Jetson Orin(NVIDIA) Orange Pi 5 Plus(Rockchip RK3588)
算力单元 GPU(sm_87,统一内存 8GB) NPU 三核(各 2 TOPS,共 6 TOPS)+ CPU
CV 推理引擎 TensorRT 10.3.0 rknn-toolkit2 2.3.2 + librknnrt
LLM 工具链 TensorRT-Edge-LLM 0.6.0 / MLC-LLM 0.20 rkllm-toolkit 1.3.0 + librkllmrt
VLM 方案 llama.cpp(GGUF) rknn-llm 多模态 demo(视觉 rknn + 语言 rkllm)
模型格式 .engine / MLC 的 -q4f16_1 / GGUF .rknn / .rkllm
板端系统 JetPack 6.x(L4T R36.x,CUDA 12.6) Armbian 26.8.2(vendor 内核 6.1.115)

一句话概括:NVIDIA 是"一套 CUDA 打天下",Rockchip 是"视觉一套工具、语言一套工具,各干各的"。这个差异贯穿后面所有环节。

🔄 CV 模型:两边居然是同一个模子

先从最简单的 ResNet18 说起。Jetson 上的流程:

复制代码
PyTorch → torch.onnx.export → trtexec --onnx --saveEngine --fp16 → .engine → 板端 TensorRT API 跑

RK3588 上跑 Qwen3-VL 的视觉塔,流程是:

复制代码
PyTorch → torch.onnx.export → rknn-toolkit2 build → .rknn → 板端 librknnrt 跑

看出来没?一模一样。都是"框架图 → ONNX 公证层 → 厂商编译器 → 设备绑定二进制 → 板端专用 runtime"。

为什么都绕不开 ONNX?因为 NPU/GPU 编译器吃不了"活的" PyTorch 代码。HuggingFace 模型本质是动态 Python 程序,编译器需要一张静态、封闭的计算图。所以第一步必须 trace 冻图,第二步编译成目标芯片的指令流。我之前专门琢磨过这个问题:rknn-toolkit2 其实有 load_pytorch 接口,但它要求传入的也是 traced model------冻图这一步怎么都省不掉,ONNX 只是把"冻图"和"编译"解耦了

拆两步还有个工程上的好处:出错能二分 。我在 RK3588 上转换视觉塔时,ONNX 导出 20 秒就验完了输出形状([49, 2048]),后面 ONNX→RKNN 首跑报 pkg_resources 缺失,我立刻就知道是编译段的环境问题(setuptools 84 移除了老 API,降级解决),跟导出没关系。要是一条道跑到黑,这种问题就得两头猜。

相同点还不止这些:

  • 产物都绑芯片型号.engine 绑 sm_87,.rknn 绑 rk3588,换芯片都得重编
  • 产物都要 md5 校验后推板:两边我都推过 G 级文件,G 级文件不查 md5 就是给自己埋雷
  • 都有算子兜底机制 :TensorRT 不支持的算子写 plugin;RKNN 不支持的落到 CPU(op_target 指定)
  • 量化思想一致:离线用代表性数据统计分布,换低精度加速。TensorRT INT8 要校准集,RKNN 的 W8A8 同样要校准数据

🧠 LLM 部署:Jetson 三条路,RK3588 一条路

Jetson 上我玩过三种姿势

路线 思路 我的实测
TensorRT-Edge-LLM 0.5B runtime 优化,engine + plugin Qwen2.5-0.5B,OpenAI 兼容 API 好接,但 v0.6.0不支持流式输出
MLC-LLM 1.5B/3B 编译器路线,PC 交叉编译 1.5B 60 tok/s、TTFT 0.077s,是目前 Jetson 上最快的一档
llama.cpp GGUF 直接吃 省事,兼容性最好,VLM 靠它

Jetson 最大的坑是 8GB 内存 :MLC-LLM 3B 必须 MAX_SEQ_LEN=2048(从 4096 砍半)才塞得下;JIT 编译前必须开 8GB swap 防 OOM;后来跑 VLM 时还发现两套 CUDA 服务不能并存,测 Qwen3-VL 前得先把常驻的 Qwen2.5-VL 服务 kill 掉腾内存。大模型编译这种重活,我干脆放 PC 上交叉编译好再推板。

RK3588 上 rkllm 一条道

RK3588 的官方路线 rknn-llm 是"PC 端转换期量化":用 rkllm-toolkit 把 HF 权重直接转成 .rkllm。我转 Qwen3-VL-2B 的 W8A8 用了 33 分钟(其中 28 层逐层优化占 22 分钟,48 秒/层,全程最慢段),产物 2.3G。

转换前要先生成校准数据,这一步文本和多模态不一样:

  • 文本路线:纯文本 prompt 进,prompt 出
  • 多模态路线 :跑 20 条 MMBench 图文样本的前向,hook 截获语言模型入口的 inputs_embeds------校准数据是图文联合嵌入,不是纯文本。这个细节挺讲究的,量化分布得跟实际推理时的分布对上

实测性能(端侧 HTTP 口径):1.5B decode 23.8 tok/s,3B 13.5 tok/s,TTFT(256 字提示)541/919 ms。跟 Jetson MLC 的 60 tok/s 比,纯文本速度确实差一截,但两块板子价钱差得更多。

LLM 踩坑风格对比

两边坑的类型完全不同,挺能说明工具链成熟度:

  • Jetson 的坑是"资源型":内存不够、swap、并发服务互踩------芯片太强但板子内存太小,全是物理约束
  • RK3588 的坑是"工程型" :NPU 驱动 0.9.6 跑 rknn 静默输出乱码(差 0.0.2 版本!)、官方脚本内部命名不一致(生成写 llm_inputs.json、导出读 inputs.json)、--savepath 参数目录部分被忽略......都是版本对齐和细节规范问题 。Rockchip 工具链迭代快,但粗糙的地方不少,用之前先读仓库源码,别全信博客------我踩的 5 个坑全是参考博客(老版本)和实操(新版本)行为差异导致的

👁️ VLM 部署:两边哲学完全不同

这是我觉得最有意思的部分。同样是 Qwen3-VL-2B,两边走了两条截然不同的路。

Jetson:llama.cpp 一把梭

GGUF 格式直接吃,一条命令起服务:

bash 复制代码
llama-server -m Qwen3VL-2B-Instruct-Q8_0.gguf --mmproj mmproj-F16.gguf \
    -ngl 99 --ctx-size 3072 --port 8081

视觉和语言都在一个模型文件体系里(mmproj 单独放视觉投影层),动态分辨率------图多大切多少 patch,一张图约 604 个视觉 token,看图细节丰富。4.4 秒加载完事,OpenAI 兼容 API 直接用。整个过程没有任何"转换"环节,下载即部署,对用户极其友好。

RK3588:外科手术式拆分

rknn-llm 的思路是把 VLM 拆成"眼睛"和"大脑",两条工具链分别伺候

复制代码
Qwen3-VL-2B(一个 HF 仓库)
├── 视觉塔:PyTorch → ONNX → .rknn(rknn-toolkit2,fp32 不量化,795M)
└── LLM:  PyTorch → .rkllm(rkllm-toolkit,W8A8 量化,2.3G)

板端:图片 → imgenc(.rknn) → 图像特征[49,2048]
    → 替换 prompt 里的 <|image_pad|> 占位 → demo(.rkllm) → 文本

因为分辨率被钉死在 224×224(448 会超 NPU 寄存器限制,转换成功运行也崩),每张图固定 49 个视觉 token ------是 Jetson 的零头。官方 demo 只有前台交互程序,没有 HTTP 服务,我还得自己基于 ctypes 封装写了个 OpenAI 兼容的 Flask 服务。另外还有个隐蔽的坑:交互输入必须包含 <image> 字样,否则走纯文本通道,图像嵌入压根不注入,模型会一本正经地回答"我无法查看图片"。

一个工具链成熟度的直观对比:Jetson 上 VLM 从下载到服务跑起来 6 分钟;RK3588 上同样的事,PC 端两套 venv、两次转换共 40 分钟、demo 编译、自研 HTTP 层,以天计。llama.cpp 是"傻瓜相机",rknn-llm 是"手动挡"------前者省心,后者对 NPU 的利用更彻底(毕竟 llama.cpp 在 RK3588 上官方版只走 CPU,NPU 要靠社区 fork,而社区 fork 又有驱动版本坑)。

⚔️ 正面交锋:同模型同精度对打

光说不练假把式。我做了个能回答"RK3588 到底慢多少"的实验:同模型(Qwen3-VL-2B)、同 8bit 精度档(W8A8 vs Q8_0)、同图同问同测试脚本,唯一变量是硬件。

指标(中位) RK3588 · 3×NPU Jetson Orin · GPU 倍数
TTFT(图已缓存,热态) 164.2 ms 165.8 ms ≈1.0×,打平
decode 输出速度 12.74 tok/s 31.29 tok/s 2.46×
单轮总耗时(出 256 token) 19.8 s 8.3 s 2.4×
每图视觉 token 49(固定) ~604(动态) 前端根本不同

两个发现特别值得说:

① TTFT 为什么能打平? 因为两边都吃了缓存红利(图特征进 prompt cache),首包延迟由小段增量 prefill 和网络开销主导,这部分两边半斤八两。用户感知的"反应快不快",两块板是一个水平

② decode 差 2.5 倍,物理上完全自洽。 decode 是纯内存带宽瓶颈:RK3588 算下来 12.74 tok/s × 2.3G ≈ 29 GB/s,而 LPDDR4x 理论带宽 31.6 GB/s------利用率 92%,已经打满了;Jetson 侧 57 GB/s。带宽决定天花板,这不是优化能救的,是硬件代差。

还有一个容易被忽略的点:输入信息量天然不对等。Jetson 每图 604 token,看图细节明显更细腻;RK3588 的 49 token 是拿"看得粗"换"每图成本低"。如果你做质量盲评,得知道两边根本没看同一份"图"。

📊 总结:像的部分和不像的部分

像的部分(范式同构)

  1. 都是"离线编译 + 板端 runtime"两段式
  2. 都以 ONNX 为中间公证层(LLM 权重打包除外)
  3. 产物都绑死芯片型号、都要 md5 推板校验
  4. 都有量化体系(INT8/W8A8)和算子兜底(plugin/CPU fallback)
  5. LLM 侧殊途同归:权重离线量化打包 + 专用 runtime 逐 token 生成 + OpenAI 兼容 HTTP 包装

不像的部分

维度 TensorRT(Jetson) RKNN/RKLLM(RK3588)
动态 shape 原生支持(optimization profile) 基本静态,转换时钉死
VLM 分辨率 动态,细节丰富 固定 224,省成本
工具链数量 CV/LLM/VLM 生态各自成熟,llama.cpp 兜底 视觉、语言两套工具链,各自独立版本
踩坑类型 资源型(内存/swap) 工程型(驱动版本/命名不一致)
部署体验 下载即用(llama.cpp)或交叉编译(MLC) PC 转换链路长,板端常要自己补服务层
decode 天花板 带宽 57 GB/s 带宽 29 GB/s(已跑满 92%)

选型建议(个人向):

  • 看图质量(OCR、细节描述、grounding):Jetson 动态分辨率优势太大,没得选
  • 成本 sensitive 的纯文本对话:RK3588 够用,TTFT 同级,decode 慢 2.5 倍但价格是零头
  • 快速验证/原型:Jetson + llama.cpp,零转换成本
  • 深度榨干国产 NPU:RK3588 + rknn-llm,做好读源码的心理准备
  • CV 小模型:两边一个套路,TensorRT FP16 和 RKNN fp16/fp32 随便选,TensorRT 生态文档更成熟

环境版本锚定:Jetson Orin 8GB / JetPack 6.x / CUDA 12.6 / TensorRT 10.3.0 / TensorRT-Edge-LLM 0.6.0 / MLC-LLM 0.20.0 / llama.cpp b10618;Orange Pi 5 Plus 16GB / Armbian 26.8.2 Trixie / vendor 内核 6.1.115 / RKNPU 驱动 v0.9.8 / rknn-toolkit2 2.3.2 / rkllm-toolkit 1.3.0。对比协议:同模型 Qwen3-VL-2B、同 8bit 精度档(W8A8 vs Q8_0)、同图同问同 HTTP 测试脚本、3 问 × 3 轮取中位、max_tokens=256、temperature=0。全部数据来自本人实测,欢迎评论区交流踩坑经验。

相关推荐
上海蓝色星球1 小时前
蓝色星球NG-AIOS新型AI工业操作系统重磅发布——以本体智能为内核,重构“AI+制造“新范式
大数据·数据库·人工智能·机器人
来让爷抱一个1 小时前
2026 视觉语言模型实战:八帧跳跃不许看走样,百智云精灵图把图文契约写进素材包
人工智能·机器学习
Joy T1 小时前
Spring AI 2.0 进阶入门:RAG、Structured Output 与 Agent 信息闭环
java·人工智能·spring·rag·springai·agent入门
skywalk81631 小时前
第 23 轮方向确定:保护表通用化替代轮。先深入探查剩余保护表依赖场景和任务 6 的四阶段路径,再写任务书。9.14
开发语言·人工智能·光明
深海鱼在掘金2 小时前
深入浅出RAG——第11章:Prompt 工程与上下文优化
人工智能
华清远见成都中心2 小时前
OpenCV中颜色空间有哪些区别
人工智能·opencv
做萤石二次开发的哈哈2 小时前
视频汇集平台模板上线萤石蓝海AIoT一站式工作台:多品牌摄像机+NVR统一接入,GB/T28181国标级联实现工程施工多方视频调度(附部署教程)
大数据·人工智能·物联网·音视频·萤石开放平台·蓝海aiot一站式工作台·aiot开发
张小姐的猫2 小时前
【AI大模型接入SDK】 —— SQLite上手
linux·开发语言·c++·人工智能·python·log4j
AI深栈2 小时前
第 9 章 · Model Context Protocol(MCP)
java·人工智能