mirror of
https://github.com/deepseek-ai/DeepGEMM.git
synced 2026-11-05 00:47:26 +00:00
[PR #452] perf: Use full-rate FADD relu in SM90 FP8 MQA logits epilogue #457
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#457
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?
📋 Pull Request Information
Original PR: https://github.com/deepseek-ai/DeepGEMM/pull/452
Author: @Chtholly-Boss
Created: 9/18/2026
Status: 🔄 Open
Base:
main← Head:sm90-mqa-logits-relu-fadd📝 Commits (1)
ee53a16Use full-rate FADD relu in SM90 FP8 MQA logits epilogue📊 Changes
1 file changed (+3 additions, -3 deletions)
View changed files
📝
deep_gemm/include/deep_gemm/impls/sm90_fp8_mqa_logits.cuh(+3 -3)📄 Description
Summary
Replace
fmaxf(x, 0)withx + fabsf(x)in the SM90 FP8 MQA logits epilogue, recovering the 2× throughput gap between FMNMX (half-rate) and FADD (full-rate) on Hopper. The factor-of-2 introduced by the identity is resolved by folding0.5finto the existingscale_kvmultiply — zero extra instructions, bit-exact numerics.Background
On SM90,
fmaxf(x, 0)compiles to a single FMNMX, which issues at 64 ops/clk/SM — half the rate of FADD/FFMA (128 ops/clk/SM). Meanwhilex + |x|compiles to a single FADD with the absolute-value operand modifier, which is a free encoding bit in the instruction word:The relu executes once per
(token, head, kv)score element in the MQA logits epilogue, so at 64 vs 128 ops/clk/SM the FMNMX form doubles the FP32 pipe time spent on relu alone.Since
x + |x| = 2 · relu(x)holds exactly for all finite IEEE-754 floats (+0for x ≤ 0), the doubled sum is simply halved by folding* 0.5finto the already-existingscale_kvmultiplication (an exponent decrement, also exact):The same technique is already used by the SM100 kernel (
sm100_mqa_logits.cuh, packedFADD2variant); this PR brings it to SM90. Verified viacuobjdump -sass: zero FMNMX across all JIT-instantiatedsm90_fp8_mqa_logitscubins.Performance (H200, 132 SMs, SM90A)
Production indexer shapes, best of 3 reps, before → after:
Full
tests/test_attention.pysweep (192 contiguous MQA cases on SM90): avg +3.7% (SK=65536 subset +4.4%, H=64 subset +5.5%, best case +11.3%). Gains scale with the relu's share of kernel time: larger SKV, more heads, smaller head dim → bigger win. Paged MQA logits (separate kernel, untouched) is unaffected.Correctness
x + |x| = 2 · relu(x)exactly for all finite IEEE-754 floats (x > 0:x + x = 2x; x ≤ 0:x + (−x) = +0); the ÷2 via* 0.5fis an exact exponent decrement.tests/test_attention.pypass (numeric diff vs simulated reference, 20× bitwise self-consistency, mask equality) — verified on H200.x + |x|propagates NaN;fmaxf(NaN, 0)returns 0), but WGMMA accumulator outputs are finite in practice; this matches the SM100 kernel's existing behavior.Changes
deep_gemm/include/deep_gemm/impls/sm90_fp8_mqa_logits.cuh— 3 lines modified (transform lambda + two* 0.5ffolds).🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.