准备好,AI MAX 395开始能用vllm干活了(从ling-3.0-flash开始)

准备好,AI MAX 395开始能用vllm干活了(从ling-3.0-flash开始)

AI MAX 395 的 vLLM终于从能跑到能打,迈了一步了。

写给所有 AMD Ryzen AI MAX+ 395(Strix Halo / gfx1151)用户: 被迫用 llama.cpp 一年多的本地大模型推理,终于在 vLLM 上开始迎来了真正可用的一天。 本文所有数据均来自同一台 395 机器的实测基准(2026-07 ~ 2026-08),以及 CIRU 发行版的官方技术文档。

一、395 的处境:理论硬件存在,但支持架构贫瘠

Ryzen AI MAX+ 395(Strix Halo,GPU 架构 gfx1151 / Radeon 8060S)的硬件设计,至少看起来适合本地LLM部署:

  • 128GB 统一内存,CPU/GPU 共享,隔壁DGX Spark也是如此;
  • 256-bit LPDDR5x-8000,理论内存带宽 256 GB/s,隔壁DGX Spark的273GB/s也没大哪儿去;
  • 但 GPU 是 Wave32 的 RDNA3.5 架构,不在 ROCm 官方支持列表的核心位置,比隔壁的CUDA差了好远,生态长期处于由Donato Capitella为首的各路社区达人自救的状态。

这就造成了一个持续一年多的尴尬局面:想在 395 上跑大模型,基本只有 llama.cpp(GGUF + Vulkan/HIP)一条路。vLLM 也并非装不上——AMD 官方 TheRock 频道一直在发 gfx1151 的 wheel——但装上之后的体验,用”能运行”三个字形容都嫌客气。

二、曾经的成绩单:官方 vLLM “能跑,但没法看”

先看 2026-07-23 的基准。AMD 官方 TheRock wheel 分发的 vLLM(0.23.1.dev1+rocm7.14.0.g9ddef7117.d20260715),模型 Qwen3.6-35B-A3B(BF16),单并发,输出固定 128 tokens:

提示词长度预填充速度 (tok/s)输出速度 (tok/s)
4K1487.1511.55
8K1448.769.32
16K1169.866.73
32K826.514.33
64K518.862.52
128K297.241.38

你看这PP,你看这TG……这还只是一个小小的35B-A3B的moe啊……

  1. 单流解码本来就慢。才4K,TG就跌到 11.55 tok/s,就连 llama.cpp 的一半都不到,PP都没好哪儿去,要知道llama.cpp这时候的pp大约也是1300~1400这个数。
  2. 长上下文衰减是崩塌式的。从 4K 到 128K,预填充跌掉 80%,解码从 11.55 跌到 1.38 tok/s——128K 上下文下每秒钟蹦不出两个词,要不是我为了收集跑分成绩,我早就提前掐了,眼不见心不烦。

同一时期 llama.cpp 跑同类模型能稳定输出 30~50 tok/s,甚至是快入土的2080ti,用vllm跑这个模型,pp高达6000,tg高达100,395对比2080ti简直就是个笑话。于是大家都有个共识:395 用户想用 vLLM ,试图去探索更好的处理、长 KV 池和Agent 工具链,那就只能干瞪眼。

三、转折点:CIRU 版 Ling-3.0-Flash

在2026 年 8 月,ling-3.0-flash开源后不久,官方贴心的自量化了个int4,而在这个基础上,社区开发者 CIRU(jcbtc)在 HuggingFace 发布了 Ling-3.0-Flash-CIRU-int4-Strix-native:一个专为 Strix Halo 打造的 vLLM 原生运行时发行包。它的构成是:

  • 模型:InclusionAI 官方 Ling-3.0-flash-int4 packed-INT4(W4A16)checkpoint,77GB,权重一个字节都没改,钉死 revision;
  • 引擎:vLLM 上游 commit d35eb6c4 + CIRU 16 个提交的分支(head 91fab4e6d),净改动仅 8 个文件、+459/-28 行,源码编译;
  • 软件栈:TheRock nightly ROCm 7.15 + Torch 2.13 + Triton 3.8 + FlashAttention 2.8.3(Triton AMD 路径),Python 3.12;
  • 配方:TRITON_MLA 注意力后端、Triton MoE 后端、chunked prefill、prefix caching、MTP K1 投机解码、定制编译档。

官方文档里有一段值得全文引用的”性能战役复盘”——从第一个能在 gfx1151 上跑起来的上游兼容构建,到最终发布版,单流解码吞吐的完整爬升阶梯:

优化阶段解码速度阶段收益
首个能跑的上游兼容构建0.269 tok/s起点
禁用 Wave32 上病态的 ROCm skinny-GEMM 调度7.57 tok/s28.16x
编译档 mode 3 + decode size 1 + 关 cudagraph11.21 tok/s+48.1%
一致的 ROCm 7.15 / Torch 2.13 / Triton 3.8 栈14.84 tok/s+32.4%
W4A16 MoE 专家指派与 finalize 归约快路径19.71 tok/s+42.4%
修复多 token 验证器路由 + 原生 MTP K125.13 tok/s+27.3%
精确形状的 gfx1151 SiLU-mul kernel26.23 tok/s+4.37%

从 0.269 到 26.23,累计 97.55 倍。 充分见证了CIRU是怎么一层一层把”gfx1151 上每一步都走错”的默认路径掰回正道的。

四、实测:同一台 395,新老 vLLM 与 llama.cpp 同台

以下均为本机实测(单并发 / 双并发 / 五并发,输出固定 128 tokens)。

4.1 CIRU vLLM + Ling-3.0-Flash int4,单并发(2026-08-10)

提示词长度预填充 (tok/s)输出 (tok/s)
4K1038.8827.28
8K947.8327.27
16K872.9724.21
32K769.9823.91
64K636.1721.20
128K474.8816.75
256K315.3611.89

对比旧官方 vLLM 的 128K 档位(PP 297 / TG 1.38):虽然模型不同(int4 MoE vs BF16),不完全对等,但 128K 下 PP 快 1.6 倍、TG 快 12 倍,而且一直到 256K 都保持着两位数的解码速度——长上下文从”不可用”变成了”可用”。

4.2 与 llama.cpp 单流对比:真正的各有千秋

llama.cpp(GGUF 版 ling-3.0-flash,2026-08-10 同机实测):

提示词长度llama.cpp PPllama.cpp TGCIRU vLLM PPCIRU vLLM TG
4K613.8840.241038.8827.27
8K569.5248.37947.8327.27
16K487.0343.46872.9724.21
32K384.1233.48769.9823.91
64K(缓存命中,无效)30.03636.1721.20
128K超时失败474.8816.75
注:llama.cpp 64K 档预填充耗时仅 3.3 秒(折合 19173 tok/s),是服务端 prompt cache 命中的结果,不代表真实算力,故不计入。128K 档 llama.cpp 实例直接连接超时失败,而 vLLM 侧的 KV 池实测可容纳约 145 万 tokens(约 5.5 个完整 256K 上下文)。

结论非常清晰:

  • 单流解码(TG):llama.cpp 仍然领先约 40~50%(40+ vs 27 tok/s)。纯聊天、短提示词场景,llama.cpp 依然是好用易上手。
  • 预填充(PP):vLLM 全面反超,4K 档 1039 vs 614,32K 档 770 vs 384,领先约一倍。长文档摘要、RAG、Agent 长提示词场景,vLLM 的等待时间直接减半。
  • 长上下文:llama.cpp 在 128K 已经失败,vLLM 到 256K 仍有315.36pp和11.89tg。
  • 并发与工具链:连续批处理、OpenAI 兼容、自动工具解析(--tool-call-parser ling3)、多槽 KV 池——这些是 llama.cpp 的弱项,正是 vLLM 的主场。

4.3 多并发不完善,但能凑合用

双并发实测:

提示词长度聚合 PP (tok/s)聚合 TG (tok/s)
4K1001.0642.40
8K926.6341.92
16K850.7324.35
32K711.746.61

五并发实测:

提示词长度聚合 PP (tok/s)聚合 TG (tok/s)
4K1038.2755.27
8K937.456.92

好消息:4K~8K 短上下文下双路并发聚合 TG 达到 42 tok/s(每路约 21),并发调度真实有效,PP 几乎无损耗。 坏消息:16K 往上(五并发直接8K往上),多并发 + 长上下文的组合衰减剧烈,32K 双路聚合只剩 6.61 tok/s——在带宽受限的统一内存平台上,长 prefill 会长时间占用连续批处理窗口、挤压 decode,这是当前配方下尚未解决的真实短板,官方从1到6 的多并发测试也只覆盖到 2K 提示词。指望它当多人共用的高并发服务还不现实,“单流/双流 + 长上下文”或”多流 + 短上下文”才是当下的可用范围,适合单人使用偶尔双线程并发或者前后插队

4.4 尝试验证:这套引擎不止能跑 Ling

把同一套 CIRU vLLM 运行时拿去服务 Qwen3.6-35B-A3B,对比三个月前的官方 vLLM(同模型、同机、同协议):

提示词长度旧官方 PPCIRU PP旧官方 TGCIRU TGTG 提升
4K1487.152008.6411.5533.012.86x
8K1448.761465.649.3231.003.33x
16K1169.861472.336.7325.493.79x
32K826.511241.674.3319.534.51x
64K518.86909.082.5213.095.20x

同一个模型、同一块 GPU,仅换运行时:TG 提升 2.9~5.2 倍,PP 提升最高 75%,MTP 投机解码实测接受率 83~97%。

但也确实”虎头蛇尾”:4K 时 33 tok/s 的开局比 Ling 还漂亮,64K 却跌到 13.09,被 Ling(21.20)反超。原因不太清楚,姑且猜测是——BF16 权重 + 全量注意力 KV 的带宽压力远大于 W4A16 的 Ling(本猜测不具备任何可鉴性)。

五、性能拉升原理:这 97.5 倍到底是怎么来的

综合 CIRU 官方文档与部署实践,收益来自四层:

1. 把”走错的路”掰回来(最大头)

最大的单项元凶是 vLLM 的 ROCm skinny-GEMM 路径在 Wave32 GPU 上被静默选中——仅禁用这一项(VLLM_ROCM_USE_SKINNY_GEMM=0),同样输出的解码就快了 28.16 倍。这类”默认路径在 gfx1151 上是病态的”问题还有好几个:ROCm FlashAttention 返回的 LSE 布局是 [tokens, heads] 而 vLLM 的 chunked MLA 累加器要求 [heads, tokens](不修则并发一高就挂);MTP 多 token 验证块的路由在 MLA 下走错后端;gfx1151 的 Triton merge kernel 会触发 HSA fault(CIRU 加了带守卫的安全归并路径)。每一个不修,都是”能跑但慢/崩”。

2. 编译与运行时栈

编译档 mode 3 + cudagraph NONE + compile_sizes [1,2](+48%);整套 TheRock nightly ROCm 7.15 / Torch 2.13 / Triton 3.8 保持一致(+32%);并显式关掉 AITER(VLLM_ROCM_USE_AITER=0)——在 gfx1151 上 AITER 至今仍是负资产。环境变量侧还有 HIP_FORCE_DEV_KERNARG=1HSA_NO_SCRATCH_RECLAIM=1 等配套。

3. 模型形状的定制化 kernel

W4A16 MoE 的专家指派与 finalize 归约快路径(+42%)、精确形状的 gfx1151 SiLU-mul kernel(+4.4%)——这些快路径带严格守卫,只对 Ling 的几何形状(512 专家、top-8、hidden 2560 等)生效,不匹配就安全回落上游路径。这也是”为什么别的模型不能完整吃到 Ling 的全部增益”的原因,但 Qwen3.6 的实测证明通用项(skinny-GEMM、编译档、栈、MTP)已经足以带来 3~5 倍

4. 投机解码与调度

Ling checkpoint 自带 MTP 头,K1(每步投机 1 token)实测接受率 67~82%,带来约 27% 的有效提速;Qwen3.6 的内置 MTP 头接受率更高(83~97%)。注意 K2(投机 2 token)实测零增益——单层 MTP 头决定了 K1 就是物理上限,别浪费带宽。另外 --max-num-batched-tokens 8192 必须显式给,否则 vLLM 会静默选 2048 的投机调度预算,并发 TG 明显变差。

六、部署注意事项(踩坑实录)

如果你准备照着部署,这些是用真机时间换来的教训:

环境

  • 必须用 Python 3.12(uv 管理最省事)。3.14 能编译通过,但运行时 tensorizer 会撞上 PEP 649 惰性注解直接起不来——别试。
  • 安装/启动时工作目录不能是运行时目录:目录里的 vllm/ 源码树会把子进程的 import vllm 遮蔽成命名空间包。启动器里都内置了 cd $HOME

配置

  • --compilation-config '{"mode":3,"cudagraph_mode":"NONE","compile_sizes":[1,2]}'Ling 专属,照抄到别的模型(如 Qwen3.6)会触发 inductor 断言崩溃。换模型请删掉这项用默认编译档。
  • --max-num-batched-tokens 8192 显式写上,别依赖默认值。
  • MTP 就开 K1:--speculative-config '{"method":"mtp","num_speculative_tokens":1}',K2 无增益。
  • 采样参数由客户端发送(Ling 官方推荐 temperature=0.6, top_p=0.95, top_k=20, enable_thinking=true),服务端不预设。

资源

  • GRUB 侧需要给 GPU 划够 GTT(本机 amd_iommu=off amdgpu.gttsize=126976 ttm.pages_limit=32505856 ttm.page_pool_size=32505856)。
  • 重启/重载后每个新会话的第一个请求会触发 Triton JIT,需要约 1 分钟,不是卡死。

七、展望:395 的 vLLM 时代才刚开始

几个值得关注的趋势:

  1. 上游正在收编这些修复。CIRU 分支里已包含 AMD 工程师 liminfei-amd 的 Wave32 top-k 修复(vLLM PR #46012);kyuz0 的 amd-strix-halo-vllm-toolboxes 近期也在集中修 AITER on gfx1151(wave32 支持、rc1 注意力修复、运行时 JIT),并已支持 DeepSeek V4 Flash;此前社区本地的 ViT 检测补丁已被上游 vLLM 正式合入。社区补丁 → 上游合入的管道已经打通。
  2. ROCm TheRock nightly(7.15+)对 gfx1151 的支持在快速成熟,官方 wheel 与社区构建的差距在以月为单位缩小。今天的”定制分支”,大概率会变成明天官方 wheel 的默认行为。
  3. 新模型架构越来越”395 友好”:混合线性注意力、原生 MTP 头、官方 int4/FP4 checkpoint——每一项都直接削减每 token 的带宽成本,这正是统一内存平台的命门。Qwen3.6 的实测(同机 3~5 倍提升)证明 Ling 不是孤例。
  4. 当下的使用画像已经清晰
  • 单流短对话、追求极致 TG → llama.cpp(40+ tok/s);
  • 长上下文、RAG、多轮 Agent 工具调用、多并发 → CIRU vLLM(256K 上下文、145 万 token KV 池、连续批处理、原生工具解析);
  • 两者共存,按场景切换,这在一年前是不可想象的奢侈。


结语

ryzen ai halo的发布果然还是让amd倾注了一些更实在的东西。我那时候就预言,395将凭借Ryzen AI Halo获得长线的技术支持,但凡AMD想把这台官方设备卖的体面点,就得大费心力把395优化的像那么回事,而这些,对之前买过395的用户来说,是实打实能喝口汤的。

如何评价 AMD Ryzen AI Halo ?

395 用户等这一天等了太久:你想比肩DGX Spark,vLLM 或者Sglang是必须要迈过的坎,不能只是”装得上、跑不动”的摆设。如今从ling-3.0-flash开始,395也开始能用得上vllm作为生产力了,这是个不错的开始。

编辑于 2026-08-11 · 著作权归作者所有