[Dev] fix: account for DSA top-k sparsity and indexer cost in FLOPs - #6148
Open
niyunsheng wants to merge 2 commits into
Open
[Dev] fix: account for DSA top-k sparsity and indexer cost in FLOPs#6148niyunsheng wants to merge 2 commits into
niyunsheng wants to merge 2 commits into
Conversation
`num_floating_point_operations` only applied sparse-attention corrections when `experimental_attention_variant == "dsv4_hybrid"`. The `"dsa"` variant (GLM-5.2) fell through to the plain multi-latent-attention branch, which counts core attention over the full causal mask and ignores the indexer entirely. DSA scores every past position with the indexer but attends only to the `dsa_indexer_topk` best keys, so the dense `L^2 / 2` pair count overcounts once sequences exceed top-k -- 65% too high for a 32K-token batch and over 5x for the 256K-token GLM-5.2 recipe -- while the indexer's own projections and its dense O(L^2) scoring pass were never counted at all. Scale the core-attention coefficient by the ratio of top-k attended pairs to dense causal pairs, and add the indexer cost on the layers that compute their own index (layers in between reuse the most recent result, per `is_dsa_skip_topk_layer`). Also document the accounting convention: the KL-divergence indexer loss and top-k selection are excluded like other auxiliary operations, and the figure follows the non-absorbed model-FLOPs convention (DSA actually executes the absorbed-MLA path, ~2x cheaper per pair for GLM-5.2), so it is comparable across configs but must not be used directly as an MFU numerator. Add `TestDSA` to `test_num_floating_point_operations.py`, following the same pattern as `TestDSv4Hybrid`: `_make_dsa_args` uses `topk_freq=1`/ `skip_offset=0` so every layer computes its own index, `_dsa_golden_flops` independently reimplements the formula, and `test_bshd`/`test_thd` pin both paths and verify THD < BSHD. Signed-off-by: Yunsheng Ni <yunshengn@nvidia.com>
niyunsheng
force-pushed
the
yunshengn/fix-dsa-flops-accounting
branch
from
July 31, 2026 14:00
c220ef8 to
73948b4
Compare
niyunsheng
marked this pull request as ready for review
July 31, 2026 14:15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
num_floating_point_operationsonly applies sparse-attention correctionswhen
experimental_attention_variant == "dsv4_hybrid". The"dsa"variant (GLM-5.2) falls through to the plain multi-latent-attention branch, which counts core attention over the full causal mask and drops the indexerentirely.
Problem
DSA scores every past position with the indexer but attends only to the
dsa_indexer_topkbest keys, so the denseL^2 / 2pair count overcountsonce sequences exceed top-k, while the indexer's own projections and its
dense
O(L^2)scoring pass were never counted at all.Measured on the full GLM-5.2 architecture (78L, hidden 6144, MoE 256E,
MTP 1,
dsa_indexer_topk=2048,topk_freq=4,skip_offset=3; BSHDuniform sequences; "before" = the plain-MLA branch the
"dsa"variantpreviously fell into, i.e. this function with the variant unset):
Before the fix, per-token FLOPs grow linearly with context because of the
dense
L^2/2term; after, top-k caps the core-attention term and only theindexer's dense scoring keeps a (much smaller) per-token growth — the
physically correct shape for sparse attention. At 4K the two nearly
coincide: the mean sequence length barely exceeds top-k, so the sparsity
saving and the newly counted indexer cost roughly cancel.
Changes
megatron/training/training.py:to dense causal pairs (
_dsa_sparse_core_scale). Short sequences(
mean_seqlen <= topk) clamp the scale to 1.0, reducing exactly to thedense count — zero behavior change for non-DSA configs and for DSA runs
within top-k.
_dsa_indexer_flops: indexer projections (wq_b,wk,weights_proj) plus the denseO(L^2)scoring pass, charged only onlayers that compute their own top-k index (intermediate layers reuse the
most recent result, per
is_dsa_skip_topk_layer).all other auxiliary/sorting operations in this file;
executes the absorbed-MLA path (
AbsorbedMLASelfAttention), whose coreattention costs roughly 2x less per (query, key) pair for GLM-5.2 — so
it is comparable across configs and attention variants, but it is NOT
an executed-FLOPs count and must not be used directly as an MFU
numerator.
tests/unit_tests/test_num_floating_point_operations.py:TestDSA, following the existingTestDSv4Hybridpattern:_make_dsa_args: MLA + DSA args withdsa_indexer_topk_freq=1/dsa_indexer_skip_topk_offset=0, so every layer computes its own indexand the golden reference needs no skip-layer predicate;
_dsa_golden_flops: independent reimplementation of the formula (thetest does not just call the same code twice);
test_bshd/test_thd: exact-match both paths against the goldencalculator and verify THD < BSHD.
Test plan
tests/unit_tests/test_num_floating_point_operations.pyon a GB200 node: 35 passed, 0 failed, 2 skipped (the two skipped classes exercise the multi-rank seqlen-stats collectives, untouched by this change).TestDSA.test_bshd/test_thdpass; all pre-existing classes(BSHD backward-compat, THD scaling, hybrid, padding removal, accumulator, DSv4-hybrid) unaffected.
accounting, reported TFLOP/s/GPU is consistent across sequence lengths
(430 @ 4K vs 382 @ 32K) instead of inflating with
L^2.Notes for reviewers
sum_i min(i, topk)over query positions; the THD path applies the same scale through theseqlen_squared_summachinery using the batch mean sequence length.dsa_indexer_topk_freq, intermediate layers reuse the previous index.