Skip to content

deepseek-v4 branch: backport #1505 (blockwise-FP8 asserts on public ckpts); BF16-training drift data point #1583

Description

@hvgazula

Summary

We're reproducing the 8×8 H200 DeepSeek-V4-Flash GRPO profile entirely from public artifacts — the radixark/miles:deepseek-v4 image (digest-pinned), the #1046 overlay (yueming-yuan/miles@032721cd + sgl-project/sglang@b69485ff), and sgl-project/DeepSeek-V4-Flash-FP8 — on Modal (clustered RDMA, no shared NFS). We believe this is the first outside-radixark reproduction. Everything runs end-to-end (checkpoint pipeline, 64-GPU load, SGLang rollout, weight sync, training step); this issue reports two findings from getting there and asks one question.

Finding 1: the deepseek-v4 branch predates the PR #1505 fix — blockwise-FP8 training asserts on public checkpoints

With the profile's --fp8-format e4m3 --fp8-recipe blockwise, the first train step raises:

AssertionError: All-gather requires quantizable tensor for quantizer Float8BlockQuantizer

We traced this to what #1505 (72696ef, merged 2026-06-29) fixes on main — keeping the DSA indexer linear_weights_proj in BF16 via --te-precision-config-file. The pinned deepseek-v4 branch (2026-05-15) predates it. Backporting just the precision-config YAML from #1505 onto the branch resolves the assert (the branch's Megatron already supports te_precision_config_file).

Suggestion: backport #1505 to the deepseek-v4 branch (or note it in the #1046 instructions), since that branch is what the roadmap points public reproducers at.

Finding 2 (data point): pure-BF16 training measures step-0 train/rollout KL ≈ 0.5 on V4-Flash

Before finding #1505 we worked around the assert by dropping the two FP8 flags (BF16 training). Result: train_rollout_kl ≈ 0.506, logprob_abs_diff ≈ 0.69 at step 0 — vs ≈0.02 in the published day-0 numbers — with the R3 replay check (when enabled via --ci-test) reporting 5–20% zero-overlap router top-6 per micro-batch. Everything consistent with FP8-rollout vs BF16-training activation divergence over 43 layers. Presumably why the profile trains blockwise-FP8; sharing since the day-0 write-up's "FP8 rollout + BF16 training" phrasing might lead others down the same path.

Question: is that phrasing intended to describe BF16 master weights with FP8 GEMMs (i.e. the blockwise recipe), rather than pure-BF16 training? A clarifying note would save reproducers a few $290/hr runs.

Minor: tools/fp8_cast_bf16.py on the public FP8 checkpoint

mtp.0.e_proj.weight / mtp.0.h_proj.weight in sgl-project/DeepSeek-V4-Flash-FP8 carry no scale_inv, so the cast passes them through as FP8 ("Warning: Missing scale_inv tensor"), which later breaks torch dist-ckpt serialization (inline_container.cc:664 unexpected pos). Upcasting the two tensors to BF16 before conversion fixes it — a fallback upcast in the cast tool would make the public checkpoint work out of the box.

Happy to share full logs/configs, and to test patches — we have the pipeline cached and can turn runs around quickly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions