mirror of
https://github.com/deepseek-ai/DeepGEMM.git
synced 2026-11-05 00:47:26 +00:00
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
deepseek-ai/DeepGEMM#188
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @maci0 on GitHub (Aug 24, 2026).
Original GitHub issue: https://github.com/deepseek-ai/DeepGEMM/issues/417
Summary
Between
a6b593dand8b1392bonnv_dev, the SM12x pure-fp8 path regressed.Verified diff (
git diff a6b593d..8b1392b):csrc/jit_kernels/impls/sm100_fp8_gemm_1d1d.hpp(−416) anddeep_gemm/include/deep_gemm/impls/sm100_fp8_gemm_1d1d.cuh(−567) — thepure-fp8 1d1d kernels.
fp8_fp4_mqa_logitsdispatch rewritten: genericsmxx_fp8_mqa_logits→ per-arch
sm90_fp8_mqa_logits/sm100_mqa_logits/sm120_mqa_logits.fp8_gemm_nt = fp8_fp4_gemm_ntalias is not new — it exists in
a6b593dalready (gemm.hpp:792).The regression is the 1d1d kernel removal, not the alias.
Impact (measured on 2x DGX Spark, GB10 / sm_121a)
With
--linear-backend deep_gemm(DeepSeek-V4-Flash FP8 linear + MLA),fp8xfp8 inputs on SM12x run the combined
sm120_fp8_fp4_gemm_1d1dkernel,which misreads fp8 weights as fp4: silent numerical corruption. Greedy
France output degenerates (
' Septy Septy…') and DSpark draft acceptancecollapses, dropping decode from ~25.8 tok/s (b12x linear baseline) to
~4.4 tok/s.
a6b593d(the last good commit, frozen by eugr/spark-vllm-docker and usedby vLLM v0.25.1) serves correctly.
Request
Restore the pure-fp8 1d1d kernels on
nv_dev(or route fp8xfp8 on SM12xback to a pure-fp8 kernel) so the fp8 path is correct again. vLLM's cmake
pin is currently
8b1392b; we have opened a vLLM PR(#53680) to pin back to
a6b593din the interim.@maci0 commented on GitHub (Aug 26, 2026):
Status update: with the
a6b593dwheel, the SM12x fp8 einsum path (fp8_einsum "bhr,hdr->bhd", DSV4 o_proj) now passes DeepGEMM's host layout checks and launches on sm_121a with finite output at T=10 / T=96 / T=8192 (real DeepSeek-V4-Flash-0731 shapes). The remaining blocker for the fullfp8_gemm_nt1d1d path is the JIT toolchain: stock CUDA 13.0/13.3 ptxas rejects tcgen05.mma for sm_12x targets, and the NVRTC cubin route is rejected by the driver (CUDA_ERROR_INVALID_IMAGE). We are evaluating the driver-JIT PTX route (nvrtcGetPTX + cuModuleLoadDataEx) and will open a PR with the fix.@maci0 commented on GitHub (Aug 26, 2026):
The restore is now proposed in #419 (pure-fp8 1d1d kernel + header fixes: the
a6b593dTU cannot compile as-is — math.cuh/cuda_bf16.h were missing from the include chain; the NVRTC frontend compiles it to PTX once fixed). Note the GB10 JIT toolchain gap still blocks runtime assembly of the tcgen05 instructions on stock CUDA 13.x (ptxas rejects tcgen05 for sm_121a; NVRTC cubin and driver-JIT PTX are both rejected by the driver) — the kernel needs build-time compilation or a fixed toolchain, same as the golden stack does today.@lucifer1004 commented on GitHub (Sep 16, 2026):
In #447 the SM12x dispatch is dtype-driven end to end:
fp8_gemm_ntenters a unified fp8/fp4 dispatcher, but the actual operand dtypes select the instantiation — fp8×fp8 compiles the 1D1D kernel withkIsFP4=false(native pure-fp8; SF granularity, swizzle modes and MMA kind all follow the fp8 path). There is no fp8-as-fp4 reinterpretation anywhere, so the silent-corruption mode is gone.The reverse direction is loud rather than silent: combos with no SM120 implementation (e.g. K-grouped FP4 NT) hit
DG_HOST_UNREACHABLEwith an explicit message, covered by rejection tests (test_sm120_k_grouped_fp4_unsupported_rejection,test_sm120_native_rejections.py). Pure-fp8 correctness is covered by the dense fp8 suites and thefmt=(False,False)SF-branch regressions.@maci0 commented on GitHub (Sep 16, 2026):
Thanks, that matches what we measure. We built
vllm-project/DeepGEMM@ad1f1726on 2x GB10 (sm_121) and the dtype-driven instantiation is what we see: fp8 x fp8 selects the 1D1D kernel withkIsFP4=false, and with packed ue8m0 scale factors the result is exact against a dequantised reference (relative error 0) at 1x128x256 and 7x512x4096.One failure mode we hit on that commit, which is a different mechanism from the fp8-as-fp4 alias and is worth checking against #447. A float32 SF with
disable_ue8m0_cast=Trueis read by the SM120 kernel as packed ue8m0, becauselayout.hpp:38/42keep a float SF in the SM90 float layout whenever that flag is set, and the flag's clause only ever fires on arch 10/12. So the raw fp32 bytes are read as exponents (0xFFis2^128, which is the NaN) andmax_abs_erris inf or ~1e30; the NaN fraction is allocator-dependent (1/128 = 0.781% at 1x128x256, matching the number we reported here earlier). For SFB the TMA descriptor is sized fromnrather thann / gran_mn, so it reads past the tensor, which is probably theXid 43seen on that path.f9d0e2361(#9) addedDG_HOST_ASSERT(sfa.scalar_type() == torch::kInt and sfb.scalar_type() == torch::kInt)after the transform and that turns it into a clean rejection. If #447 carries the same guard plus thetest_sm120_native_rejections.pycases you mention, I would expect the silent mode to be closed on both sides.We can run #447's SM120 path on sm_121 when it is at a buildable commit, including the DSv4.1 sparse MQA and fp8 einsum paths, since that is the stack we serve (DeepSeek-V4-Flash-0731, TP=2). Say the word and we will post the results here.
Two questions, since #447 changes what is needed around it:
a6b593dTU)? If #447 brings a native SM120 fp8 path into nv_dev, that port looks moot for SM12x, and the SM100 side may not need it either. If so, we would rather close it than leave two overlapping proposals.For context on why we care about the nv_dev arm specifically: our image pins nv_dev at
a6b593d(eugr's freeze, taken because8b1392bdropped the pure-fp8 1d1d kernels), and we carry local ports on top. Landing #447 would let us drop that freeze and follow nv_dev.