Prhub

#25190 fix(nvfp4): make process_weights_after_loading hot-reload-safe via alias-when-same-shape

原始 PR 作者 ch-wan 合并时间 2026-05-14 07:57 文件变更 2 提交数 7 评论 4 代码增减 +59 / -19

执行摘要

使 NVFP4 权重后处理支持热重载

PR #25107 在 process_weights_after_loading 中删除了 source scales 以节省约 15 GiB/rank 内存,但破坏了热重载:第二次调用 process_weights_after_loading 时因 AttributeError 崩溃,即使设置防护绕过也会因权重与缓存布局不匹配产生垃圾 token。需要一种既能保留内存节省又能确保热重载正确性的方案。

PR 值得精读,特别是 alias_or_bind_derived_param 的实现和在 process_weights_after_loading 中的调用方式。该 PR 展示了如何在保持内存优化的同时解决热重载正确性问题,设计模式(别名共享 vs. 回退分配)对类似问题有参考价值。建议关注 scalar 参数不别名背后的原因,避免未来重蹈覆辙。

讨论亮点

该 PR 无 review 评论,但 PR body 中详细阐述了设计权衡:(1) 为什么不用 _weights_postprocessed 跳过标志?因为跳过会导致模型在热重载后输出垃圾 token,不可接受。(2) 为什么标量参数不能别名到源参数?尝试后发现 fused-QKV 线性层的下游内核期望标量形状,别名到 [N_partitions] 形状会引发运行时错误,且内存节省微不足道,因此回退。(3) 为什么在形状不兼容时回退到单独分配?保持正确性优先,不因内存优化牺牲可靠性。

实现拆解

  1. python/sglang/srt/layers/utils/common.py 中新增 alias_or_bind_derived_param 函数。该函数接受模块、源参数名、派生参数名和派生张量。如果派生张量与源 Parameter 形状广播兼容且 dtype 相同,则将派生值广播后复制到源存储中,并将派生名注册为源参数的别名(即共享同一 Parameter 对象);否则回退到 copy_or_rebind_param 分配新的 Parameter。

  2. modelopt_quant.pyModelOptFp4LinearMethod.process_weights_after_loading 中,将原来对 weight_scale_interleavedcopy_or_rebind_param + del layer.weight_scale 替换为 alias_or_bind_derived_param(layer, 'weight_scale', 'weight_scale_interleaved', scale),并在 TRTLLM 和 CUTLASS 分支上均采用此调用。移除 del layer.input_scale, layer.weight_scale_2 行。alphainput_scale_inv 等标量参数保留 copy_or_rebind_param,因为别名到 [N_partitions] 形状会破坏 fused-QKV 的下游内核(期望标量形状)。

  3. ModelOptNvFp4FusedMoEMethod.process_weights_after_loading 中,移除删除 w13_input_scale / w2_input_scale 的行;对于 TRTLLM 分支,将原来删除 w13_blockscale_swizzled / w2_blockscale_swizzled 的语句改为将这两个派生名别名到同型的 w13_weight_scale / w2_weight_scalealign_fp4_moe_weights_for_flashinfer_trtllm 已对源 scale 进行了原地重排);对于非 TRTLLM 分支,将 copy_or_rebind_param + del 替换为 alias_or_bind_derived_param。标量 g{1,2}_alphas / w{13,2}_input_scale_quant 保持 copy_or_rebind_param

  4. 测试复用现有 test_update_weights_from_disk_blackwell.py,不新增测试文件。已在 4×GB300 节点上验证解码 logprobs 在 atol=1e-4 内一致,内存节省与 PR #25107 相同(~15 GiB/rank)。

文件 模块 状态 重要度
python/sglang/srt/layers/utils/common.py 工具层 modified 7.06
python/sglang/srt/layers/quantization/modelopt_quant.py 量化层 modified 7.14

关键符号

alias_or_bind_derived_param ModelOptFp4LinearMethod.process_weights_after_loading ModelOptNvFp4FusedMoEMethod.process_weights_after_loading

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  • 热重载正确性:仅涉及 NVFP4 量化路径,不影响 FP8 和其他量化。如果 alias_or_bind_derived_param 的广播逻辑有 bug(如错误地假设形状兼容),可能导致权重布局错误,但测试覆盖了典型场景。
  • 内存回退:当派生张量形状与源 Parameter 不可广播时(如需要 padding 的非对齐维度),会回退到单独分配,峰值内存为源+派生两倍。此情况在 Kimi-K2.5 NVFP4 标准维度下不会发生(所有相关对等大小),但可能发生在自定义模型上。
  • 修改了模型初始化路径,可能影响其他 NVFP4 模型加载;但 process_weights_after_loading 仅在启动和热重载时调用,无在线风险。
  • 用户影响:修复 NVFP4 模型(如 Kimi-K2.5)的热重载功能,/update_weights_from_disk 可正常工作,无需回退到原始行为。
  • 性能影响:process_weights_after_loading 仅启动和热重载时各调用一次,不增加推理延迟。别名操作本身可以忽略不计。
  • 内存影响:保留 ~15 GiB/rank 的内存节省;仅在需要 padding 时回退到双倍分配(罕见场景)。
  • 团队影响:引入的 alias_or_bind_derived_param 可作为通用工具函数,供未来其他量化方案使用。
热重载正确性 仅 NVFP4 路径 广播兼容性依赖

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论