现在怎么没有人提用AMD MAX395去跑本地大模型了?
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) |
|---|---|---|
| 4K | 1487.15 | 11.55 |
| 8K | 1448.76 | 9.32 |
| 16K | 1169.86 | 6.73 |
| 32K | 826.51 | 4.33 |
| 64K | 518.86 | 2.52 |
| 128K | 297.24 | 1.38 |
你看这PP,你看这TG……这还只是一个小小的35B-A3B的moe啊……
- 单流解码本来就慢。才4K,TG就跌到 11.55 tok/s,就连 llama.cpp 的一半都不到,PP都没好哪儿去,要知道llama.cpp这时候的pp大约也是1300~1400这个数。
- 长上下文衰减是崩塌式的。从 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-int4packed-INT4(W4A16)checkpoint,77GB,权重一个字节都没改,钉死 revision; - 引擎:vLLM 上游 commit
d35eb6c4+ CIRU 16 个提交的分支(head91fab4e6d),净改动仅 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/s | 28.16x |
| 编译档 mode 3 + decode size 1 + 关 cudagraph | 11.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 K1 | 25.13 tok/s | +27.3% |
| 精确形状的 gfx1151 SiLU-mul kernel | 26.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) |
|---|---|---|
| 4K | 1038.88 | 27.28 |
| 8K | 947.83 | 27.27 |
| 16K | 872.97 | 24.21 |
| 32K | 769.98 | 23.91 |
| 64K | 636.17 | 21.20 |
| 128K | 474.88 | 16.75 |
| 256K | 315.36 | 11.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 PP | llama.cpp TG | CIRU vLLM PP | CIRU vLLM TG |
|---|---|---|---|---|
| 4K | 613.88 | 40.24 | 1038.88 | 27.27 |
| 8K | 569.52 | 48.37 | 947.83 | 27.27 |
| 16K | 487.03 | 43.46 | 872.97 | 24.21 |
| 32K | 384.12 | 33.48 | 769.98 | 23.91 |
| 64K | (缓存命中,无效) | 30.03 | 636.17 | 21.20 |
| 128K | 超时失败 | — | 474.88 | 16.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) |
|---|---|---|
| 4K | 1001.06 | 42.40 |
| 8K | 926.63 | 41.92 |
| 16K | 850.73 | 24.35 |
| 32K | 711.74 | 6.61 |
五并发实测:
| 提示词长度 | 聚合 PP (tok/s) | 聚合 TG (tok/s) |
|---|---|---|
| 4K | 1038.27 | 55.27 |
| 8K | 937.45 | 6.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(同模型、同机、同协议):
| 提示词长度 | 旧官方 PP | CIRU PP | 旧官方 TG | CIRU TG | TG 提升 |
|---|---|---|---|---|---|
| 4K | 1487.15 | 2008.64 | 11.55 | 33.01 | 2.86x |
| 8K | 1448.76 | 1465.64 | 9.32 | 31.00 | 3.33x |
| 16K | 1169.86 | 1472.33 | 6.73 | 25.49 | 3.79x |
| 32K | 826.51 | 1241.67 | 4.33 | 19.53 | 4.51x |
| 64K | 518.86 | 909.08 | 2.52 | 13.09 | 5.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=1、HSA_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 时代才刚开始
几个值得关注的趋势:
- 上游正在收编这些修复。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 正式合入。社区补丁 → 上游合入的管道已经打通。 - ROCm TheRock nightly(7.15+)对 gfx1151 的支持在快速成熟,官方 wheel 与社区构建的差距在以月为单位缩小。今天的”定制分支”,大概率会变成明天官方 wheel 的默认行为。
- 新模型架构越来越”395 友好”:混合线性注意力、原生 MTP 头、官方 int4/FP4 checkpoint——每一项都直接削减每 token 的带宽成本,这正是统一内存平台的命门。Qwen3.6 的实测(同机 3~5 倍提升)证明 Ling 不是孤例。
- 当下的使用画像已经清晰:
- 单流短对话、追求极致 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作为生产力了,这是个不错的开始。