[dev] DeepSeek V3.2 support - #2154
Conversation
Signed-off-by: kunlunl <kunlunl@nvidia.com>
Signed-off-by: kunlunl <kunlunl@nvidia.com>
Signed-off-by: kunlunl <kunlunl@nvidia.com>
|
Great work—this has been really helpful to me. Quick question: what are the typical values used for |
Signed-off-by: kunlunl <kunlunl@nvidia.com>
@iansheng Thanks for your interest. Currently, I don't have relevant experience about indexer loss coefficient, still working on refining this MR. and haven't actually used it to train a model yet. |
Signed-off-by: kunlunl <kunlunl@nvidia.com>
|
Thanks for your quick and great work. I've preliminarily view the code and it overall LGTM. Please add UTs for the new features, especially for the functionality of DSA and its parallel correctness. I'll do a second-round review after everything is ready. |
Signed-off-by: kunlunl <kunlunl@nvidia.com>
Signed-off-by: kunlunl <kunlunl@nvidia.com>
Signed-off-by: kunlunl <kunlunl@nvidia.com>
|
Please also do not forget to create a mirror PR to the main branch once ready for review. Thanks! |
…-attention-variant Signed-off-by: kunlunl <kunlunl@nvidia.com>
Signed-off-by: kunlunl <kunlunl@nvidia.com>
Signed-off-by: kunlunl <kunlunl@nvidia.com>
|
/ok to test 6fe2f35 |
Signed-off-by: kunlunl <kunlunl@nvidia.com>
|
/ok to test 33684d2 |
Signed-off-by: kunlunl <kunlunl@nvidia.com>
|
/ok to test a0b6fd9 |
Signed-off-by: kunlunl <kunlunl@nvidia.com>
Signed-off-by: kunlunl <kunlunl@nvidia.com>
|
/ok to test 1d2f01c |
|
/ok to test 23ba310 |
Signed-off-by: kunlunl <kunlunl@nvidia.com>
|
/ok to test cbfa053 |
|
Please adapt the MTP function of DSA as soon as possible |
|
Would it be possible to also make this code compatible with the first-stage training of DSA? |
Under the current mcore architecture, it’s difficult to have an independent computational graph (the indexer loss) perform a backward pass in isolation. It would require a major architectural overhaul, especially since this graph isn't attached to the end of the model. As a workaround, you could try multiplying the main model loss by zero. Although the main model will still undergo the backward pass, its gradients will all be zero, effectively training only the indexer. Given that the training data for the first stage is relatively small, the redundant computation is a manageable trade-off. |
DeepSeek V3.2 Sparse Attention Support
Main PR: #2440
1. TL;DR
What: This PR adds support for DeepSeek V3.2-style sparse attention (DSA) to Megatron-LM, enabling models to use learned attention sparsity patterns via a lightweight indexer module.
Why: Dense attention has O(n²) complexity which becomes computationally prohibitive for long sequences. DSA reduces this by learning to predict which key-value pairs are most relevant for each query, allowing the model to attend to only top-k tokens instead of all tokens.
Impact: Users can now train models with DeepSeek V3.2's sparse attention mechanism in Megatron-LM, which combines Multi-Latent Attention with a trainable sparse indexer. The PR also refactors the linear attention infrastructure to be more extensible for future attention variants.
2. Big Picture
2.1 Before vs After Architecture
graph TB subgraph "Before: Standard Dense Attention" A1[Hidden States] --> B1[QKV Projection] B1 --> C1[Dense Attention] C1 --> D1[Output Projection] end subgraph "After: DeepSeek Sparse Attention" A2[Hidden States] --> B2[QKV Projection] A2 --> E2[DSA Indexer] B2 --> E2 E2 --> F2[Top-K Selection] B2 --> G2[Sparse Attention] F2 --> G2 G2 --> D2[Output Projection] E2 --> H2[Indexer Loss] H2 --> D2 end style E2 fill:#90EE90 style F2 fill:#90EE90 style H2 fill:#FFD700Key Changes:
2.2 Change Scope Summary
megatron/core/transformer/experimental_attention_variant/dsa.pymegatron/core/models/gpt/experimental_attention_variant_module_specs.pytests/unit_tests/transformer/test_attention_variant_dsa.pymegatron/core/transformer/multi_latent_attention.pymegatron/core/transformer/transformer_config.pymegatron/training/arguments.pymegatron/training/training.pymegatron/core/models/gpt/gpt_layer_specs.pygpt_builders.pymegatron/core/models/gpt/linear_attention_module_specs.py3. Key Design Points
Core Abstractions Introduced:
DSAIndexer: Computes index scores to identify top-k most relevant tokensx[seqlen, batch, hidden_size] + compressed queryqr[seqlen, batch, q_lora_rank]DSAttention: Sparse attention mechanism using indexer outputsDSAIndexerand applies sparse attention kernelDSAIndexerLossAutoScaler: Custom autograd functionInterface Contracts:
Important Invariants:
x,qr) are always detached - gradients don't flow back to main modelDSAIndexerLossAutoScaler.apply()- backpropagates separatelymulti_latent_attention=Trueandcontext_parallel_size=14. Execution Path Deep Dive
4.1 Entry Point
DSA is triggered when creating a GPT model with
--experimental-attention-variant dsaflag:4.2 Call Chain Visualization
sequenceDiagram participant User participant GPTBuilder participant LayerSpec participant AttentionSpec participant MLAAttention participant DSAttention participant DSAIndexer User->>GPTBuilder: gpt_builder(args with --experimental-attention-variant dsa) GPTBuilder->>LayerSpec: get_gpt_layer_with_transformer_engine_spec(...) LayerSpec->>AttentionSpec: get_attention_module_spec_for_backend(experimental_attention_variant='dsa') AttentionSpec->>AttentionSpec: get_experimental_attention_variant_module_spec_for_backend() AttentionSpec->>AttentionSpec: get_dsa_module_spec_for_backend() Note over AttentionSpec: Creates ModuleSpec for MLASelfAttention<br/>with DSAttention as core_attention AttentionSpec-->>LayerSpec: ModuleSpec(MLASelfAttention + DSAttention) LayerSpec-->>GPTBuilder: transformer_layer_spec Note over GPTBuilder: At runtime (forward pass)... User->>MLAAttention: forward(hidden_states, ...) MLAAttention->>MLAAttention: get_query_key_value_tensors(return_compressed_tensors=True) Note over MLAAttention: Returns query, key, value, q_compressed, _ MLAAttention->>DSAttention: forward(query, key, value, x=hidden_states, qr=q_compressed, ...) DSAttention->>DSAIndexer: forward_with_scores(x, qr, mask) DSAIndexer->>DSAIndexer: Compute index scores via indexer network DSAIndexer-->>DSAttention: (index_scores, topk_indices) DSAttention->>DSAttention: unfused_dsa_fn(query, key, value, topk_indices) Note over DSAttention: Sparse attention only on top-k tokens DSAttention->>DSAttention: compute_dsa_indexer_loss(index_scores, topk_indices, query, key, ...) Note over DSAttention: KL divergence between indexer & true attention DSAttention->>DSAttention: DSAIndexerLossAutoScaler.apply(output, indexer_loss) DSAttention-->>MLAAttention: output (with loss attached) MLAAttention-->>User: attention_output4.3 Data Flow
graph TD A["Input: hidden_states<br/>[sq, b, hidden]"] --> B["MLA Q Compression<br/>linear_q_proj→linear_q_down_proj"] A --> C["MLA KV Compression<br/>linear_kv_down_proj"] B --> D["q_compressed<br/>[sq, b, q_lora_rank]"] C --> E["kv_compressed<br/>[sq, b, kv_lora_rank]"] D --> F["MLA Q Upsampling<br/>linear_q_up_proj + RoPE"] E --> G["MLA KV Upsampling<br/>linear_kv_up_proj + RoPE"] F --> H["query<br/>[sq, b, np, hn]"] G --> I["key<br/>[sk, b, np, hn]"] G --> J["value<br/>[sk, b, np, hnv]"] A --> K["x.detach()"] D --> L["q_compressed.detach()"] K --> M["DSAIndexer"] L --> M M --> N["Indexer Q Proj<br/>linear_wq_b<br/>[sq, b, index_n_heads, index_head_dim]"] K --> O["Indexer K Proj<br/>linear_wk + k_norm<br/>[sk, b, index_head_dim]"] K --> P["Indexer Weights<br/>linear_weights_proj<br/>[sq, b, index_n_heads]"] N --> Q["Apply RoPE"] O --> R["Apply RoPE"] Q --> S["rotate_activation<br/>(Hadamard transform)"] R --> T["rotate_activation<br/>(Hadamard transform)"] S --> U["Index Scores<br/>q @ k^T → ReLU → weighted sum<br/>[b, sq, sk]"] T --> U P --> U U --> V["TopK Selection<br/>[b, sq, index_topk]"] H --> W["Sparse Attention"] I --> W J --> W V --> W W --> X["attention_output<br/>[sq, b, hidden]"] U --> Y["KL Divergence Loss<br/>KL(true_attn || index_scores)"] V --> Y H --> Y I --> Y Y --> Z["indexer_loss<br/>scalar"] X --> AA["DSAIndexerLossAutoScaler.apply"] Z --> AA AA --> AB["Final Output<br/>(with loss attached)"] style K fill:#FFE4B5 style L fill:#FFE4B5 style M fill:#90EE90 style U fill:#87CEEB style V fill:#87CEEB style W fill:#FFD700 style Y fill:#FF6347 style Z fill:#FF6347 style AA fill:#DDA0DD5. Module Relationships
classDiagram class TransformerConfig { +int num_layers +int hidden_size +str experimental_attention_variant } class MLATransformerConfig { +int q_lora_rank +int kv_lora_rank +int dsa_indexer_n_heads +int dsa_indexer_head_dim +int dsa_indexer_topk +float dsa_indexer_loss_coeff } class Attention { <<abstract>> +forward()* } class MultiLatentAttention { +get_query_key_value_tensors() +forward() } class MLASelfAttention { +linear_q_proj +linear_kv_down_proj +core_attention +get_query_key_value_tensors(return_compressed_tensors) } class DSAttention { +indexer: DSAIndexer +softmax_scale: float +forward(query, key, value, x, qr, ...) } class DSAIndexer { +linear_wq_b +linear_wk +k_norm +linear_weights_proj +rotary_pos_emb +forward(x, qr, mask) +forward_with_scores(x, qr, mask) -_apply_rope() -_compute_index_scores() } class DSAIndexerSubmodules { +linear_wq_b: ModuleSpec +linear_wk: ModuleSpec +k_norm: ModuleSpec +linear_weights_proj: ModuleSpec } class DSAttentionSubmodules { +indexer: ModuleSpec } class MLASelfAttentionSubmodules { +core_attention: ModuleSpec +linear_q_proj +linear_kv_down_proj +q_layernorm +kv_layernorm } class RotaryEmbedding { +forward(seq_len) } class DSAIndexerLossAutoScaler { <<autograd.Function>> +forward(output, loss)$ +backward(grad_output)$ +set_loss_scale(scale)$ +main_loss_backward_scale$ } class DSAIndexerLossLoggingHelper { +save_loss_to_tracker()$ +reduce_loss_in_tracker()$ +track_indexer_metrics()$ +tracker: dict$ } TransformerConfig <|-- MLATransformerConfig : extends Attention <|-- MultiLatentAttention : extends MultiLatentAttention <|-- MLASelfAttention : extends Attention <|-- DSAttention : implements (core_attention) MLASelfAttention --> DSAttention : uses as core_attention MLASelfAttention --> MLASelfAttentionSubmodules : configured by DSAttention --> DSAIndexer : contains DSAttention --> DSAttentionSubmodules : configured by DSAIndexer --> DSAIndexerSubmodules : configured by DSAIndexer --> RotaryEmbedding : uses DSAttention ..> DSAIndexerLossAutoScaler : uses DSAttention ..> DSAIndexerLossLoggingHelper : logs to MLASelfAttention ..> MLATransformerConfig : reads config DSAttention ..> MLATransformerConfig : reads config DSAIndexer ..> MLATransformerConfig : reads configKey Relationships:
Composition:
MLASelfAttentioncontainsDSAttentionas itscore_attentionmoduleDSAttentioncontainsDSAIndexerfor computing sparse indicesUtility Classes:
DSAIndexerLossAutoScaler: Custom autograd for loss attachmentDSAIndexerLossLoggingHelper: Singleton for collecting losses across layersNew Dependencies Introduced:
fast_hadamard_transform(optional): For Hadamard rotation activation6. Examples
6.1 Configuration Parameters
CLI Arguments Example (added in
arguments.py):TransformerConfig Example:
6.2 Example Usage
Training a GPT model with DSA:
python pretrain_gpt.py \ --num-layers 32 \ --hidden-size 4096 \ --num-attention-heads 32 \ --seq-length 8192 \ \ # Enable Multi-Latent Attention (required for DSA) --multi-latent-attention \ --q-lora-rank 512 \ --kv-lora-rank 512 \ --qk-head-dim 128 \ --qk-pos-emb-head-dim 64 \ --v-head-dim 128 \ \ # Enable DeepSeek Sparse Attention --experimental-attention-variant dsa \ --dsa-indexer-n-heads 16 \ --dsa-indexer-head-dim 128 \ --dsa-indexer-topk 256 \ --dsa-indexer-loss-coeff 0.001 \ \ # Standard training args --micro-batch-size 1 \ --global-batch-size 512 \ --lr 1.0e-4 \ --train-iters 100000 \ --lr-decay-iters 100000 \ --lr-decay-style cosine \ --min-lr 1.0e-5 \ --weight-decay 0.1 \ --clip-grad 1.0 \ --bf16Expected Behavior:
indexer lossFurther Reading