Repository navigation
cuda: the NVFP4 lane matmul and prompt GEMM write fp32 too (qlinear decodeF32 and promptF32) - #757
Conversation
…ecodeF32 and promptF32) A tensor-parallel family sums its ranks' partial rows before rounding, so it needs a projection's fp32 sums as the kernel holds them. qmmf.cu and prompt16.cu already take F32 as a template argument; this instantiates FP4's fp32 tiles (and reduce_kernel<true> for the split path), loads them beside the bf16 ones, and adds Lane.matmulOut, Prompt.matmulOut and qlinear's decodeF32 and promptF32. Other formats refuse fp32 out with EpilogueNotBuilt, as the experts do. matmul, decode and prompt keep their signatures and bf16 bits.
2f3988f to
9a14da6
Compare
|
Rebased onto 1.0.9 ( |
A tensor-parallel family sums its ranks' partial rows before rounding, so an EXL3 projection must hand out its fp32 sums as ashhart#757 does for NVFP4. The decode kernel already takes an fp32 output flag; the prompt kernel gains the same flag (tf_exl3_store), and qlinear's decodeF32 and promptF32 route .exl3 to them. decode and prompt keep their bf16 bits: the bf16 out is the fp32 out rounded. The new exl3 test checks both entries within FP64 bounds, the same bits at every row count, and the bf16 out as their rounding; it fails with EpilogueNotBuilt before this change.
|
Thank you, @Bizuayeu. Writing the fp32 sums the lane matmul and prompt GEMM already hold, instead of rounding them first, is what a rank-order sum needs. It ships in TensorFold 1.0.12 under your name ( On a GB10, GLM-5.3-Flash on CUDA (#804) is the first caller. Posted by Ash's AI Assistant Synthena |
A tensor-parallel family sums its ranks' partial rows before rounding, so an EXL3 projection must hand out its fp32 sums as #757 does for NVFP4. The decode kernel already takes an fp32 output flag; the prompt kernel gains the same flag (tf_exl3_store), and qlinear's decodeF32 and promptF32 route .exl3 to them. decode and prompt keep their bf16 bits: the bf16 out is the fp32 out rounded. The new exl3 test checks both entries within FP64 bounds, the same bits at every row count, and the bf16 out as their rounding; it fails with EpilogueNotBuilt before this change.
The contributor's commit landed above with the same code; this keeps the PR's head in the history with no change to the tree.
…and ashhart#757 onto the candidate
…date The contributor's five GLM commits landed above, with our fixes after them; the head's first seven commits are the same changes as ashhart#757, ashhart#758, ashhart#766, ashhart#762, ashhart#764 and ashhart#763, which the candidate already has from their own heads. This keeps the PR's head in the history with no change to the tree.
A tensor-parallel family sums its ranks' partial rows before rounding, so an EXL3 projection must hand out its fp32 sums as ashhart#757 does for NVFP4. The decode kernel already takes an fp32 output flag; the prompt kernel gains the same flag (tf_exl3_store), and qlinear's decodeF32 and promptF32 route .exl3 to them. decode and prompt keep their bf16 bits: the bf16 out is the fp32 out rounded. The new exl3 test checks both entries within FP64 bounds, the same bits at every row count, and the bf16 out as their rounding; it fails with EpilogueNotBuilt before this change.
What this changes
A tensor-parallel family sums its ranks' partial rows before rounding, so it needs a projection's fp32 sums as the
kernel holds them.
qmmf.cuandprompt16.cualready take the output type as a template argument; thisinstantiates FP4's fp32 tiles (and
reduce_kernel<true>for the split-K path), loads them beside the bf16 ones, andadds
Lane.matmulOut,Prompt.matmulOutandqlinear'sdecodeF32andpromptF32. Other formats refuse fp32 outwith
EpilogueNotBuilt, as the experts do.matmul,decodeandpromptkeep their signatures, kernels and bits.The GLM-5.3-Flash CUDA family (#548) is the first user: each rank's attention and MLP projections go out in fp32 and
are summed across ranks in rank order before the one rounding.
Receipt
c36b536d) plus this commit; one GB10 (DGX Spark, sm_121, CUDA 13.3).tf-cuda-test quant-refnow also checks nvfp4'sdecodeF32andpromptF32on synthetic weights ([320, 2560] and [2560, 512], 1 to 300 rows): within the float64tolerance the bf16 checks use, the same bits at every row count, and the bf16 out equal to the fp32 out rounded,
element for element.
tf-cuda-test quant-ref: 4 PASS, 0 FAIL. The new fp32 checks need this change to compile; their largestdifference is 0.000 of the bf16 checks' tolerance, and no element of the bf16 out differs from the fp32 out rounded.
zig build test-cuda-host: 429 passed, 0 failed. Its test "a lane weight whose mode is not its format's is refusedbefore any launch" now also covers fp32 out refused for fp8g and bf16.
zig build test: 517 passed, 5 skipped, 0 failed.zig fmt --check zig/src zig/tests build.zig: clean.lean_check: 538, the same as main.Checklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo.