后续:在四块DGX Spark上运行GLM-5.2 NVFP4——MTP谜题已解,现可在128K上下文下达到约24 tok/s
摘要
修复了vLLM中为四块DGX Spark配置GLM-5.2 NVFP4时的一个推测解码bug,解决了性能权衡问题,通过MTP4在128K上下文下实现了约24 tok/s。
后续:在四块DGX Spark上运行GLM-5.2 NVFP4——MTP谜题已解,现可在128K上下文下达到约24 tok/s
这是对我之前发布的关于在4x DGX Spark上以128K上下文运行GLM-5.2 NVFP4的文章的后续。那篇文章的简短版本是:128K上下文在MTP1下工作正常,速度约为15 tok/s,但存在一个痛苦的权衡:要么拥有128K上下文,要么获得约23 tok/s(DCP1下32K),但无法两者兼得。我还指出,在DCP4下MTP2/MTP3的接受率崩溃“看起来确实有bug”,但30小时的深入排查未能解决。它确实有bug。现在解决了。权衡消失了。以下是详细情况:
TL;DR 旧配置 (DCP4/128K/MTP1) → 现在 (DCP4/128K/MTP3) → 现在 (DCP4/128K/MTP4)
解码,短代码生成(热) 14.5-15.2 tok/s → 22-23 tok/s
MTP每位置接受率 0.74 (仅MTP1) → 0.90 / 0.79 / 0.67
上下文 131,072 → 131,072
硬件 4x GB10 Spark + MikroTik RoCE 未变
编辑:预填充仍约为475 tps;bs=3解码约为48 tps。是的,MTP4——递归重用的单MTP层在第4位置仍有条件接受率约为0.84,这与我在RTX 6000 Pro机器上看到的峰值MTP4一致。
一个配置陷阱:MAX_CUDAGRAPH_CAPTURE_SIZE需要大于num_speculative_tokens + 1(草稿派生出的上限小于目标;恰好N+1会导致启动失败,提示“No valid cudagraph sizes”)。我设置MTP4为10。我偶尔看到当主机页面交换频繁时运行速度下降——MTP3是我的保守默认值,MTP4是峰值配置。
相同的机器、相同的交换机、相同的检查点、相同的每节点1.81GB KV预算。全部收益来自于vLLM中缺失的一行配置管道,以及将基础代码迁移到更新的上游分支。DCP1/32K这种折中配置现在已无意义:DCP4在全上下文下完全胜出。
bug到底是什么?
在我的原帖中,我写道接受率看起来像是0.9, 0.75^4, 0.6^4,并猜测存在某种秩交集效应。指数的直觉指向了真实问题(损害确实随DCP世界大小扩展),但机制隐藏得更好——它能在30多个小时的消融实验中存活下来的原因确实很邪恶:SpeculativeConfig.create_draft_parallel_config()通过从目标配置复制字段来构建草稿模型的并行配置——而decode_context_parallel_size并不是它复制的字段之一。它静默地默认为1。在我的技术栈使用的代码路径上,这个值被原样使用。因此,在TP4/DCP4下,MTP草稿层的KV缓存、元数据和稀疏索引器状态都是DCP分片的(写入端在目标配置下运行),而草稿的注意力机制则认为它根本没有DCP:没有全量查询聚合,没有LSE合并,全局top-k索引被当作本地四分之一缓存是全部缓存来使用。张量转储显示,草稿前向中,四个秩中有三个没有选择任何内容,并为它们64个头中的48个生成了字面全零注意力。
邪恶的部分来了:注意力之后的下一个操作是o_proj,它是行并行的——它的TP全归约将四个不一致的每秩结果求和成一个隐藏状态,该状态在每个秩上是比特一致的。我在原始调查中运行的每一次跨秩差异检查都返回干净,因为损坏在发生后一个操作就被清洗成共识。而且由于草稿以目标的隐藏状态作为输入,单步MTP1大部分情况下可以依靠该信号存活(约0.75接受率),而递归步骤2-3则加剧了垃圾内容并崩溃。这就是我第一篇文章中的崩溃曲线。
这也解释了为什么bug对所有旋钮都无动于衷:KV交错大小、ag_rs与a2a DCP通信后端、全局与秩本地top-k、CUDA图与eager模式——它们都没有触及草稿并行配置的构建方式。我在放弃配置空间并构建张量分接之前测试了所有这些问题(接受曲线精确到两位小数都相同)。
它是如何被发现的?
方法说明,因为我知道有些人喜欢详细过程:将代码栈重新基于一个更新的上游分支(见下文)。容量完全复现;MTP3仍然崩溃。这排除了“上游已修复”和“我的旧分支有问题”的可能性。又进行了四次启动,否定了剩下的配置假设(交错/通信后端/top-k模式/eager)。全部相同。在这一点上,bug一定在计算中,而不是在配置表面。
写了一个小的环境门控分接,插入MLA解码路径,在每个草稿层前向时转储:全量聚合后的查询、实际使用的top-k索引、每秩部分输出+LSE、合并后的输出、元数据以及原始fp8 KV页面。在DCP1上校准了分接:对反量化后的fp8_ds_mla缓存进行的fp64参考注意力,每次前向都以余弦≥0.9999复现了核函数的输出。因此仪器是可信赖的。
在DCP4上运行相同的探针并读取转储:每个秩上的impl.dcp_world_size == 1,合并后的输出与合并前的部分逐字节相同(即从未运行过合并),DCP本地序列长度(全局22时为6/6/5/5)输入到非DCP注意力中,输出秩为零。从那里追踪配置回到create_draft_parallel_config花了大约二十分钟。
修复大约有10行代码,镜像了上游在新运行器路径上已有的逻辑(这就是为什么大型SM120设备从未遇到这个问题——它们运行的是包含修复的代码路径;而我的技术栈运行的是没有该修复的路径)。包含修复、三个针对GLM路由检查点的配套补丁以及完整证据的PR已经以草稿形式发布:https://github.com/local-inference-lab/vllm/pull/72
更新后的配方
所有内容都在之前的同一仓库中,相同的配方目录:github.com/m9e/blackwell-llm-docker → recipes/4x-spark-cluster/glm52-b12x-spark/
新的生产入口点:start-glm52-production.sh(DCP4 / MTP3 / 128K,关闭诊断)
镜像现在基于一个更新的上游基础(local-inference-lab/vllm eldritch line,June 29 + b12x),上面覆盖了5个文件:来自原帖的Spark Ray启动修复和加载后malloc_trim,以及DCP草稿修复。配方目录中有构建脚本。
配方目录中的ELDRITCH_REBASE_NOTES.md记录了整个调查——每个被否定的假设及其数值、转储证据和内存账本。
一个值得指出的尴尬发现,如果你关注了原帖:我在内存优化中描述的NCCL通道缩减(NCCL_MAX/MIN_NCHANNELS=4,固定NCCL_IB_HCA)实际上从未被包含在提交的启动脚本中——在原始测试中是手动应用的。现在已经提交了。如果你之前克隆了该配方,你运行的是默认通道数,会导致内存浪费。
原帖中的其他所有内容仍然适用:激进的OS/Ray修剪、主机网络、fp8_ds_mla KV、混合检查点组装脚本(你仍然需要真实的model.layers.78.* MTP层)、以及通过Spark结构的IB/RDMA。硬件部分一直到交换机都没有变化。
我会对原帖所做的修改:
“MTP2/MTP3属于研究领域”→错误,它们只是坏了。现在MTP3是生产默认值。
“这个设置恰好有一个MTP层,所以MTP1是干净的生产点”→一旦草稿能够实际看到它从中推导的上下文,单层递归工作得很好。位置3接受率为0.67,对于递归重用的单步头来说,这实际上比我预期的要好。
原帖中的409/512预填充振荡:仍然存在,仍然未解释,仍然不太重要。
未解决的问题
在修复后的技术栈上进行干净的长上下文解码测量(我的第一次深度探测是在主机页面交换期间运行的,报告结果不公平;旧MTP1基线在32K-112K之间TTFT后约为13 tok/s,接受率随深度下降不大,所以我预计可以达到十几到二十tok/s——将在评论中跟进一个干净的数字)。
对草稿进行b12x-MoE A/B测试以及在修复后的技术栈上进行DCP2重新测试,主要是为了形成配置矩阵。
原帖中的fp8_ds_mla质量问题仍然值得单独撰写一篇文章。
还有一个参考点,由于经过专家剪枝的GL
相似文章
GLM-5.2-Int4-Int8 在 8× GB10 上:约 1,200 t/s 预填充,33–54 t/s 平均解码
描述了在 8 节点 DGX Spark (GB10) 集群上使用定制 vLLM 分支部署和基准测试量化后的 GLM-5.2-Int4-Int8Mix 模型,实现了约 1,200 t/s 的预填充和约 35 t/s 的解码,支持 MTP 工具调用。
在4× DGX Spark (GB10)上成功运行GLM-5.2 + MTP投机解码——并发现公开构建配方中缺失的组件
作者在4× DGX Spark (GB10)设备上成功运行了配备MTP投机解码的GLM-5.2,并揭示了公开构建配方中缺失的一个组件。
GLM 5.2 在 4 个 Sparks 上运行是否合理?
用户询问在四个 Ascend GX10 或 DGX Sparks 上以 4 位量化运行 GLM-5.2 的可行性,想知道在 100k 上下文下的速度和内存情况。
@TheAhmadOsman: Luke Alonso 已上传了一个 NVFP4 量化版本的 GLM 5.2,大小为 467GB,可适配 4 块 DGX Sparks(约 2 万美元)
Luke Alonso 上传了一个 NVFP4 量化版本的 GLM 5.2(467GB),可适配 4 块 DGX Sparks 硬件,成本约 2 万美元。
@Ex0byt: 更新:通往GLM-5.2之路:我们快到了,各位!未量化、未剪枝的DeepSeek-v4-Flash。单台……上11 tok/s
关于在单台DGX Spark上使用sglang推理和自定义mega-kernel以11 tok/s运行未量化的DeepSeek-v4-Flash模型的更新,正在向GLM-5.2迈进。