Prhub

#42169 [Bugfix] Fix DeepSeek v4 topk numerical issue for unaligned max-model-len

原始 PR 作者 wzhao18 合并时间 2026-05-10 11:30 文件变更 1 提交数 2 评论 1 代码增减 +2 / -2

执行摘要

修复 DSv4 topk 对未对齐 max-model-len 的数值问题

当 --max-model-len 设置为 900000 等非 256 对齐值时,DeepSeek V4 生成 token 分布出现显著偏移,GPQA 准确率从 ~89% 降至 ~82%,且大量无响应。根因是 topk 内核 stride 计算错误。

值得精读:这是一个典型的内存布局假设引发数值问题的小而精修复,展示了在 CUDA kernel 中正确处理 tensor stride 的重要性。

讨论亮点

无 review 讨论,仅有 bot 自动评论和 zyongye 的批准。

实现拆解

  1. 修改 csrc/topk.cu 中 launch_persistent_topk 函数:将 const int64_t stride = logits.size(1) 改为 const int64_t stride = logits.stride(0),正确获取 logits tensor 在行方向上的内存步长。
  2. 修改同文件中 persistent_topk 函数:同样的修改,确保统一使用 stride(0) 代替 size(1)。
  3. 此改动确保即使 logits 的最后一维因 deepgemm 填充而不连续时,stride 仍能正确反映实际内存布局,避免 kernel 内部计算错误。
文件 模块 状态 重要度
csrc/topk.cu CUDA 内核 modified 4.04

关键符号

launch_persistent_topk persistent_topk

关键源码片段

csrc/topk.cu core-logic

修复核心:将 stride 计算从 logits.size(1) 改为 logits.stride(0),解决非连续 logits 导致的 topk 数值错误。

// csrc/topk.cuvoid launch_persistent_topk(const torch::Tensor& logits,
                            ...) {
  const int64_t num_rows = logits.size(0);
  // 修复:使用 stride(0) 代替 size(1),因为 deepgemm 可能对最后一维
  // 进行 256 对齐填充,导致 size(1) != stride(0) 当 max_model_len 未对齐时。
  const int64_t stride = logits.stride(0);
  // ... kernel launch ...
}void persistent_topk(const torch::Tensor& logits,
                     ...) {
  const int64_t num_rows = logits.size(0);
  // 同上,统一使用 stride(0) 确保内存步长正确。
  const int64_t stride = logits.stride(0);
  // ... kernel 执行 ...
}

评论区精华

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

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

风险与影响

风险极低:仅改动两个相同语义的 int64_t 赋值,从 size(1) 改为 stride(0)。在 logits 连续时两者等价,在非连续时能正确获取步长。但不影响 kernel 其他逻辑,无回归风险。

影响范围:DeepSeek V4 模型在非 256 对齐的 --max-model-len 配置下的推理正确性和稳定性。修复后 token 分布恢复正常,GPQA 准确率恢复至 ~88.9%。影响程度:高,但限于特定配置。

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论