TAI BUI
Back to curriculum
BuildPython

Native Sparse Attention (DeepSeek NSA)

At 64k tokens, attention takes 70-80% of decode latency. Every open-model lab has a plan to fix it, and DeepSeek's NSA (ACL 2025 best paper) is one that stuck. It runs three parallel attention branches: compressed coarse-grained tokens, selectively retained fine-grained tokens, and a sliding window for local context, combined through a learned gate. It is kernel-friendly, it trains from the start of pre-training instead of being bolted on at inference, and on 64k decodes the paper reports it running faster than FlashAttention while matching or beating full attention quality. This lesson builds the three branches end to end and shows why the sparsity stays differentiable.

TIME: ~60 minutesPREREQUISITES: Phase 7 · 12 (KV cache, flash-attention), Phase 7 · 15 (attention variants), Phase 10 · 16 (differential attention)

Learning Objectives

  • State the three NSA attention branches and what each one captures.
  • Explain why NSA is "natively trainable" where prior sparse-attention methods were inference-only.
  • Compute the attention compute savings of NSA versus full attention at 64k context as a function of compression block size and selection top-k.
  • Implement the three-branch combination in stdlib Python on a short synthetic sequence and verify the gating weights behave.

The Problem

Full attention at sequence length N costs O(N^2) time and O(N) KV cache per layer. At 64k tokens, the compute and memory bandwidth bill is brutal. The NSA paper's theoretical estimate puts attention at 70-80% of total decode latency at 64k, so TTFT, tokens/sec, and cost per million tokens all follow attention cost.

Sparse attention is the obvious answer, and prior attempts fall into two buckets. Fixed-pattern sparsity (sliding-window, strided, block-local) throws information away and fails on long-range recall tasks. Inference-time sparsity (KV cache pruning, H2O, StreamingLLM) gets applied to a model pre-trained on dense attention. It recovers only a fraction of the potential speedup, because the model was never asked to route information through the sparse pattern.

Native Sparse Attention (Yuan et al., DeepSeek + PKU + UW, ACL 2025 best paper, arXiv:2502.11089) goes after both problems. The model learns the sparsity pattern during pre-training, and the algorithm is built around the GPU kernel so the compute savings show up at inference. I'd bet NSA or a close descendant becomes a default on long-context models, though that is a bet and not something this lesson can show.

Warm-up0/3
1. How does the KV cache of one attention layer grow with sequence length N?Warm-up
A row of token boxes, tok 1 through tok N, with an arrow down into a KV cache box whose size after N tokens is left as a question mark. A question asks how the cache size scales as N grows.
Setup only, from the stem; the scaling law is the question.
2. What does FlashAttention change about full attention?Warm-up
A box describing full attention as computing scores for every pair of the N tokens, with an arrow down into a FlashAttention box whose change is left as a question mark. A question asks what FlashAttention changes about computing full attention.
Setup only, from the stem; what changes is the question.
3. How does grouped-query attention (GQA) differ from standard multi-head attention?Warm-up
A box describing standard multi-head attention as H query heads, each with its own key head and value head, with an arrow down into a grouped-query attention box whose difference is left as a question mark. A question asks how GQA differs from this standard design.
Setup only, from the stem; what GQA changes is the question.
Check: The Problem0/2
1. Why do TTFT, tokens/sec and cost per million tokens all improve at 64k when attention cost drops?Explain
A box labelled attention compute, drops per NSA's design, with three arrows fanning out to three target boxes: TTFT, tokens per second, and cost per 1 million tokens, each left as a question mark. A question asks why all three move together when attention cost drops.
Setup only, from the stem; why the three metrics move together is the question.
2. Why do inference-time sparsity methods such as H2O and StreamingLLM recover only part of the potential speedup?Explain
Two boxes: pre-training, full dense attention throughout, and inference, where H2O or StreamingLLM prune the KV cache. A question asks why these recover only part of the potential speedup.
Both stages are given directly in the stem.

The Concept

Three parallel branches

For each query, NSA runs attention three times, against three different views of the KV cache:

  1. Compressed branch. Tokens are grouped into blocks of size l (typically 32 or 64). Each block is compressed into a single summary token via a small learned MLP. The query attends over these compressed tokens, getting a coarse-grained view of the whole sequence.

  2. Selected branch. Using attention scores from the compressed branch, the top-k blocks most relevant to the current query are identified. Fine-grained (uncompressed) tokens from those blocks are read and the query attends over all of them. Think of compressed-branch attention as the routing signal for the selection.

  3. Sliding-window branch. The query attends to the most recent W tokens (typically 512) for local context. This branch covers the short-range patterns (syntax, local coreference) that the other two might miss.

The three branch outputs are combined via a learned per-position gate:

out = g_cmp * out_cmp + g_sel * out_sel + g_win * out_win

g_cmp, g_sel, g_win are gate weights from a small MLP on the query. They do not have to sum to 1, so each branch gets weighted on its own.

Why this is "natively trainable"

The selection step (top-k blocks) is discrete. Discrete operations break gradient flow. Prior sparse-attention work either skipped backprop through selection (limiting training) or used continuous relaxations that did not give real sparsity at inference.

NSA sidesteps this: the compressed-branch attention is itself a differentiable coarse-grained attention over the whole sequence. The top-k operation just reuses the top attention scores from the compressed branch to pick which fine-grained blocks to load. Gradients flow through the compressed-branch scores (which influence both the compressed output AND the selection logic), and the selected blocks' contribution to the final output is also differentiable. The non-differentiable top_k operation adds nothing to the forward computation. It only controls which blocks get loaded from memory.

That is why NSA can be used in pre-training end to end. The model learns to route information through the three branches jointly, producing a sparse pattern that at inference actually delivers the promised speedup.

Hardware-aligned kernel

NSA's kernel is designed for modern GPU memory hierarchies. The kernel loads queries by GQA groups (outer loop), fetches the corresponding sparse KV blocks per group (inner loop), and runs attention on SRAM. Because each query group sees the same selected blocks (selection is per-query-group, not per-query-head), the KV loads are amortized across the group. Arithmetic intensity stays high.

The paper reports Triton kernels running 9x faster than FlashAttention on 64k decodes, with the speedup ratio growing with sequence length. Forward and backward kernels are both provided.

The compute budget

Let N be sequence length, l the compression block size, k the top-k selection count, w the sliding window, b the selected block size (typically equals l).

  • Compressed branch: O(N/l) keys per query, so O(N * N / l) total.
  • Selected branch: O(k * b) keys per query, so O(N * k * b).
  • Sliding branch: O(w) keys per query, so O(N * w).

Total: O(N * (N/l + k*b + w)).

With N = 64k, l = 64, k = 16, b = 64, w = 512: per-query cost is 1000 + 1024 + 512 = 2536 keys. Full attention is 64000 keys. 25x compute reduction.

With N = 128k, l = 64, k = 16, b = 64, w = 512: per-query cost is 2000 + 1024 + 512 = 3536 keys. Full attention is 128000 keys. 36x reduction. The benefit grows with sequence length, which is what the design is after.

How does it compare

MethodDifferentiableReal inference speedupLong-range recall
Sliding window onlyyesyesfails
Strided / block-sparseyesyespartial
KV pruning (H2O, StreamingLLM)N/A (inference-time)yespartial
MoBA (Moonshot)partialyesgood
NSAyes (natively)yes (9x at 64k)matches full attention

MoBA (Moonshot, arXiv:2502.13189) was concurrently published and takes a similar three-is-better-than-one approach, applying the MoE principle to attention blocks. NSA and MoBA are the two architectures I'd read first for long-context pre-training.

Check: The Concept0/23
1. Which three parallel branches does NSA run for each query?Define
Three unlabeled view boxes side by side, each marked with a question mark, with arrows down into a gated combine box that produces out. A question asks which three branches NSA runs, against which three views of the KV cache.
Setup only; the structure (three views feeding a gate) is given, the branches' identities are the question.
2. What does NSA's compressed branch compute?Define
A term card reading Compressed branch. Context: One of NSA's three parallel attention branches. A question asks: What does it compute?
The term as the lesson names it; its mechanism is the question.
3. What does the selected branch attend over?Define
A term card reading Selected branch. Context: The second of NSA's three parallel attention branches. A question asks: What does it attend over?
The term as the lesson names it; its mechanism is the question.
4. What is the role of NSA's sliding-window branch?Define
A term card reading Sliding-window branch. Context: The third of NSA's three parallel attention branches. A question asks: What is its role?
The term as the lesson names it; its mechanism is the question.
5. What does "natively trainable" mean for a sparse-attention method?Define
A term card reading Native trainability. Context: A property of how a sparse-attention method is trained. A question asks: What does it mean for a method to be natively trainable?
The term as the lesson names it; its mechanism is the question.
6. What does the compression block size l set in NSA?Define
A term card reading Compression block size l. Context: A setting inside NSA's compressed branch. A question asks: What does l set?
The term as the lesson names it; its mechanism is the question.
7. What does the top-k setting count in NSA?Define
A term card reading Top-k. Context: A setting inside NSA's selected branch. A question asks: What does the top-k setting count?
The term as the lesson names it; its mechanism is the question.
8. What is the trade-off when choosing the sliding window size W?Define
A term card reading Sliding window W. Context: A setting inside NSA's sliding-window branch. A question asks: What is the trade-off when choosing W?
The term as the lesson names it; its mechanism is the question.
9. What does hardware alignment mean for NSA's sparse pattern?Define
A term card reading Hardware alignment. Context: A property of how NSA's sparse pattern is designed. A question asks: What does it mean for NSA's sparse pattern?
The term as the lesson names it; its mechanism is the question.
10. What is NSA's gated combination of the three branch outputs?Define
Three boxes, out_cmp times g_cmp, out_sel times g_sel, out_win times g_win, each with an arrow down into a combine box whose operation is left as a question mark, producing out. A question asks how the three gated branch outputs are combined into out.
The three gate-weighted terms are the lesson's own variable names; how they combine is the question.
11. What does the NSA paper report for its Triton kernels against FlashAttention on 64k decodes?Define
Two boxes: FlashAttention as the baseline speed, and NSA's Triton kernels at an unspecified multiple of that speed, left as a question mark. A question asks what speed ratio the NSA paper reports here.
Setup only, from the stem; the reported ratio is the question.
12. In the comparison table, which method is differentiable and fast but fails on long-range recall?Define
A single-row excerpt of the lesson's comparison table, with the Method column left as a question mark and the Differentiable, Speedup, and Recall columns filled in exactly as the lesson states them for this row. The other four methods are not shown at all. A question asks which method matches this row.
Excerpt of the lesson's own comparison table (one row only), masking the method name. The other four methods are omitted so this picture cannot answer the sibling questions about them.
13. How does the comparison table characterize KV pruning methods such as H2O and StreamingLLM?Define
A single-row excerpt of the lesson's comparison table, showing only the KV pruning method name, with its Differentiable, Speedup, and Recall cells left as question marks. The other four methods are not shown at all. A question asks how the table characterizes this method.
Excerpt of the lesson's own comparison table (one row only), masking the three cells this question asks about. The other four methods are omitted so this picture cannot answer the sibling questions about them.
14. Why does NSA keep a sliding-window branch when the compressed and selected branches already cover the whole sequence?Explain
Two boxes, compressed branch covering the whole sequence coarsely and selected branch covering the top-k blocks finely, with a third box, sliding-window branch, whose reason for being kept is left as a question mark. A question asks why NSA still keeps the sliding-window branch.
Both existing branches' coverage is given directly in the stem; why a third branch is kept is the question.
15. How does NSA stay differentiable even though it does a discrete top-k block selection?Explain
A three-step flow: compressed scores, a top-k discrete selection step, and selected tokens. A note says this discrete step usually blocks gradients during backprop. A question asks how NSA stays differentiable despite it.
The forward pipeline is the lesson's own description; how training signal reaches it is the question.
16. Why does NSA's kernel load queries by GQA group in the outer loop?Explain
Three boxes in sequence: an outer loop over each GQA query group, an inner loop that fetches its selected KV blocks, and attention run on SRAM. A question asks why the kernel nests the loops in this order.
The loop structure is the lesson's own description of the hardware-aligned kernel; why this order is the question.
17. Why does NSA's savings ratio over full attention grow as the context gets longer?Explain
A formula panel giving NSA's total cost as N times the quantity N over l plus k times b plus w, against full attention's N times N. A question asks why NSA's savings ratio over full attention grows as N grows.
Both formulas are transcribed from the Concept section's compute-budget derivation.
18. In the comparison table, how does MoBA differ from NSA on differentiability?Explain
A two-row excerpt of the lesson's comparison table, showing only the MoBA and NSA rows, with the Differentiable column left as a question mark for both. The other three methods are not shown at all. A question asks how MoBA differs from NSA on differentiability.
Excerpt of the lesson's own comparison table (MoBA and NSA rows only), masking the two cells this question asks about. The other three methods are omitted so this picture cannot answer the sibling questions about them.
19. At N=64k, l=64, k=16, b=64, w=512, what per-query key count does the compute budget give for NSA?Apply
A panel giving N = 64000, l = 64, k = 16, b = 64, w = 512, with the per-query key count left as a question mark against a full-attention count of 64000.
Setup only, the stem's own figures.
20. At N=128k with l=64, k=16, b=64, w=512, what does the compute budget give for NSA?Apply
A panel giving N = 128000, l = 64, k = 16, b = 64, w = 512, with the per-query key count left as a question mark against a full-attention count of 128000.
Setup only, the stem's own figures.
21. A variant of NSA picks blocks with a separate hard top-k router whose scores never enter any branch output. What goes wrong in pre-training?Analyze
Two boxes: a hard router whose scores feed only the top-k pick, and the branch outputs, compressed plus selected plus window, combined into the result, with no arrow connecting the router's scores to any branch output. A question asks what goes wrong in pre-training for a variant built this way.
The disconnected router is given directly in the stem's own description of this variant.
22. After pre-training with NSA, a model recalls a fact from 30k tokens back but writes locally incoherent text. Which setting is the likeliest culprit?Analyze
Two boxes: recalling a fact from 30k tokens back, and writing locally incoherent text, both outcomes after pre-training with NSA. A question asks which setting is the likeliest culprit for the second outcome.
Both outcomes are given directly in the stem.
23. A colleague proposes dropping the selected branch because the compressed branch already attends over the whole sequence. What would be lost?Analyze
Two boxes: the current design with three branches, compressed plus selected plus window, and the proposed design with only two, compressed plus window, dropping selected because compressed already covers the whole sequence. A question asks what dropping the selected branch would lose.
The proposal and its stated reason are given directly in the stem.

Build It

code/main.py implements the three branches on a short synthetic sequence and shows:

  • The compression MLP (a mean-pool baseline here, to keep it readable; the real NSA uses a learned MLP).
  • The top-k block selection driven by compressed-branch scores.
  • The sliding-window attention on the last w tokens.
  • The gated combination.
  • A compute-count printout comparing to full attention.

Step 1: compress tokens into blocks

python
def compress_mean(K, l):
    n = len(K)
    n_blocks = (n + l - 1) // l
    out = []
    for b in range(n_blocks):
        start, end = b * l, min((b + 1) * l, n)
        block = K[start:end]
        summary = [sum(row[d] for row in block) / len(block) for d in range(len(K[0]))]
        out.append(summary)
    return out

Step 2: compressed-branch attention

Run softmax attention of the query against the compressed keys. The compressed-branch scores double as the signal for top-k selection.

Step 3: top-k block selection

Pick the indices of the k highest-scoring compressed blocks. Load the original uncompressed tokens from those blocks and run attention on them.

Step 4: sliding-window attention

Take the last w tokens and run standard attention against them.

Step 5: gate + combine

A gate on the query produces three weights (in main.py it is one linear layer plus a sigmoid on random weights; the paper uses a small MLP). The final output is a weighted sum of the three branch outputs.

Step 6: compute counting

Print the number of keys attended per query for each branch and the total. Compare to N (full attention). On a 1024-token synthetic with l = 32, k = 4, w = 128, NSA sees 32 + 128 + 128 = 288 keys per query versus 1024 for full attention, about 3.6x fewer.

Check: Build It0/7
1. In Build It's 1024-token synthetic run (l=32, k=4, w=128), how many keys per query does NSA attend to against full attention?Apply
A panel giving N = 1024, l = 32, k = 4, w = 128, with the per-query key count left as a question mark against a full-attention count of 1024.
Setup only, the stem's own figures, matching Build It's synthetic run.
2. compress_mean is called on 10 key vectors with l=4. What does it return?Apply
An excerpt of the real compress_mean function, computing the block count as n plus l minus 1, floor-divided by l, and noting the last block slices K from its start up to the minimum of its end and n. A question asks how many summary vectors compress_mean returns on 10 key vectors with l equals 4, and what happens to the last one.
Code excerpted from the lesson's main.py; the 10 vectors and l=4 are the stem's own numbers.
3. top_k_blocks is called with scores [0.10, 0.30, 0.05, 0.45] and k=2. What does it return?Apply
An excerpt of the real top_k_blocks function, sorting block indices by descending score and returning the sorted top k indices. A question asks for the result of top_k_blocks on scores 0.10, 0.30, 0.05, 0.45 with k equals 2, left as a question mark.
Code excerpted from the lesson's main.py; the four scores and k=2 are the stem's own numbers.
4. sliding_window is called on 100 keys with W=512. What does it return?Apply
An excerpt of the real sliding_window function, computing start as the max of 0 and n minus W, then slicing K and V from start to the end. A question asks how many keys sliding_window returns on 100 keys with W equals 512.
Code excerpted from the lesson's main.py; the 100 keys and W=512 are the stem's own numbers.
5. What does count_nsa(16384, 32, 16, 512) return, and how does that compare with full attention at N=16384?Apply
An excerpt of the real count_nsa function, returning N divided by l, plus k times l, plus W. A question asks for the result of count_nsa(16384, 32, 16, 512), left as a question mark, against a full-attention count of 16384.
Code excerpted from the lesson's main.py; the four argument values are the stem's own numbers.
6. You are sizing a 64k (N=65536) run with l=128, k=8, b=128, w=512. How many keys does each query attend to, and how does that compare with full attention?Apply
A panel giving N = 65536, l = 128, k = 8, b = 128, w = 512, with the per-query key count left as a question mark against a full-attention count of 65536.
Setup only, the stem's own figures.
7. A teammate reads the 25x figure from count_nsa and says NSA decodes 25 times faster at 64k. What is wrong with that claim?Analyze
A panel noting that count_nsa reports a 25x figure, fewer keys per query, at 64k context. A teammate concludes from this that NSA decodes 25 times faster at 64k. A question asks what's wrong with that conclusion.
The 25x figure and the teammate's claim are the stem's own wording; count_nsa is the lesson's real function, named but not re-run for this question.

Use It

NSA is shipping in DeepSeek's own long-context pre-training pipeline. Integration status in public inference stacks as of April 2026:

  • DeepSeek internal: native, published weights use NSA or its successor DSA (Deepseek Sparse Attention).
  • vLLM: experimental NSA support in development for DeepSeek-V3.x weights.
  • SGLang: NSA benchmarks published; production path follows vLLM.
  • llama.cpp / CPU: not supported; overhead of the kernel decomposition is not worth it at CPU throughput.

When to reach for NSA:

  • Pre-training or continued-training run targeting 64k-plus context with a serious compute budget.
  • Inference of DeepSeek's own long-context checkpoints. The weights are NSA-native.

When not to:

  • Serving an existing dense-attention pre-trained model. You cannot retrofit NSA without continued training.
  • Context under 16k. The three-branch overhead dominates the savings.
  • Batch-1 interactive chat. Latency-sensitive decode benefits, but only at long contexts.
Check: Use It0/4
1. What is DSA and how does it relate to NSA?Define
An excerpt of the Use It section listing integration status by stack. DeepSeek internal says published weights use NSA or its successor, with that successor's name masked as a placeholder. The vLLM and SGLang rows follow, unmasked. A question asks what the masked term stands for and how it relates to NSA.
Transcribed from the lesson's own Use It section, with only the successor's name masked.
2. Your team has a dense-attention 13B checkpoint and wants cheaper 64k serving next month. What does Use It advise?Design
Two boxes: having a dense-attention 13B checkpoint, and wanting cheap 64k serving next month. A question asks what the Use It section advises here.
Both the checkpoint and the serving goal are given directly in the stem.
3. You are planning a new pre-training run for a 128k-context model with a large compute budget and a hard long-range recall requirement. Which attention plan fits?Design
Three boxes: a target of 128k context, a large compute budget, and a hard long-range recall requirement. A question asks which attention plan fits this run.
All three constraints are given directly in the stem.
4. An interactive chat product serves a dense model at batch size 1 with contexts under 8k. A teammate suggests NSA. What is the better call?Design
Two boxes: serving today, a dense model at batch size 1 with contexts under 8k, and a teammate's suggestion to adopt NSA. A question asks what the better call is here.
Both the current setup and the suggestion are given directly in the stem.

Ship It

This lesson produces outputs/skill-nsa-integrator.md. Given a long-context pre-training run specification, it produces an NSA integration plan: compression block size, top-k, sliding window, gate MLP width, kernel choice, and the specific long-context evals that would justify the architecture change.

Author's Note

I'd run main.py before reading the formulas again. On the 1024-token synthetic it prints 32 compressed keys, 128 selected keys, and 128 window keys, then checks whether the blocks carrying the planted signal were retrieved. The selected count is just k * l, and the total of 288 is the number the Build It section compares against 1024.

The line worth rereading is in nsa_step: the picks come from top_k_blocks(cmp_w, cfg.k), the softmax weights of the compressed branch, with no separate router. That reuse is the trainability argument from The Concept, in one call. The toy has no backward pass though, so it shows the routing and leaves the gradient claim to the paper.

Keep the toy in proportion. Mean-pool stands in for the learned compressor, and the gate is one linear layer plus a sigmoid on random weights, so the gate values it prints say nothing about trained behavior. The 25x and 36x figures come from count_nsa, which counts keys per query and does not time any kernel. The 9x speedup is the paper's number from its Triton kernels, and nothing in this file measures it.

Exercises

  1. Run code/main.py on a 1024-token synthetic. Sweep (l, k, w) across three presets and print compute counts. Identify the preset that achieves the lowest key-count per query while keeping 95% recall against full attention on a needle-in-haystack test.

  2. Replace the mean-pool compressor with a tiny learned MLP (2-layer, hidden 32). Train it on a synthetic task where the signal is the average of a block. Measure the perplexity gap against the mean-pool baseline on held-out data.

  3. Implement the gate MLP. It takes the query as input and outputs three scalars. Show that the gate behaves sensibly: near-uniform weighting on random queries, heavy weight on the selected branch when the query hits a far-back block.

  4. Compute the KV cache memory budget for an NSA-enabled 70B model at 128k context. KV heads are 8, head dim 128, BF16. Compare to full attention and to MLA (Phase 10 · 14 showed MLA's numbers). Identify the sequence length where NSA's fine-grained branch KV cache equals full attention.

  5. Read Section 4 of the NSA paper (arXiv:2502.11089) and explain in three sentences why the compressed branch's attention scores are reused for top-k selection rather than computing a separate routing score. Tie the answer to gradient flow.

Key Terms

TermWhat people sayWhat it actually means
Compressed branch"Coarse view"Attention over block-averaged keys that provides global context in O(N/l) keys per query
Selected branch"Top-k blocks"Fine-grained attention over the k blocks with highest compressed-branch scores
Sliding window"Local context"Attention over the last W tokens for short-range patterns
Native trainability"Pre-train with the sparsity on"The sparsity pattern is learned during pre-training, not bolted on at inference
Compression block size l"Group size for coarse view"How many tokens get merged into one summary; 32-64 typical
Top-k"Blocks to keep"Number of compressed blocks whose uncompressed tokens get read; 16 typical
Sliding window W"Local attention radius"Typically 512; shorter hurts local coherence, longer wastes compute
Branch gate"How to mix the three"Per-position MLP output that weights the three branches' contributions
Hardware alignment"Kernel-friendly sparsity"Sparse pattern chosen so that the actual GPU kernel achieves the theoretical speedup
DSA"NSA's successor"Deepseek Sparse Attention, the architecture that followed NSA in DeepSeek's lineage

Further Reading

Code

Ships With