A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 2, 07:15 UTC
[DSV4] Remove unncessary classes & functions (#44246)
Signed-off-by: Woosuk Kwon <woosuk@inferact.ai>
Woosuk Kwon committed
Jun 1, 2026 at 14:43 UTC
8c3cc98cffd31b910c41b11076e8c175fc6dabe9
3 files changed
+62
-124
vllm/models/deepseek_v4/amd/model.py
+14
-18
@@ -48,8 +48,7 @@ from vllm.model_executor.models.utils import (
48
)
49
from vllm.models.deepseek_v4.attention import (
50
DeepseekV4Indexer,
51
- DeepseekV4MLAModules,
52
- DeepseekV4MultiHeadLatentAttentionWrapper,
51
+ DeepseekV4MLA,
52
)
53
from vllm.platforms import current_platform
54
from vllm.sequence import IntermediateTensors
@@ -314,7 +313,7 @@ class DeepseekV4Attention(nn.Module):
313
314
self.rope_parameters = config.rope_scaling
315
317
- # Initialize rotary embedding BEFORE DeepseekV4MLAModules (which needs it)
316
+ # Initialize rotary embedding BEFORE DeepseekV4MLA (which needs it)
317
rope_parameters = config.rope_parameters
318
rope_parameters["rope_theta"] = (
319
config.compress_rope_theta if self.compress_ratio > 1 else config.rope_theta
@@ -351,7 +350,17 @@ class DeepseekV4Attention(nn.Module):
350
prefix=f"{prefix}.indexer",
351
)
352
354
- mla_modules = DeepseekV4MLAModules(
353
+ self.mla_attn = DeepseekV4MLA(
354
+ hidden_size=self.hidden_size,
355
+ num_heads=self.n_local_heads,
356
+ head_dim=self.head_dim,
357
+ scale=self.softmax_scale,
358
+ qk_nope_head_dim=self.nope_head_dim,
359
+ qk_rope_head_dim=self.rope_head_dim,
360
+ v_head_dim=self.head_dim,
361
+ q_lora_rank=self.q_lora_rank,
362
+ kv_lora_rank=self.head_dim,
363
+ o_lora_rank=self.o_lora_rank,
364
vllm_config=vllm_config,
365
fused_wqa_wkv=self.fused_wqa_wkv,
366
q_norm=self.q_norm,
@@ -365,19 +374,6 @@ class DeepseekV4Attention(nn.Module):
374
indexer_rotary_emb=self.rotary_emb,
375
topk_indices_buffer=topk_indices_buffer,
376
aux_stream_list=aux_stream_list,
368
- )
369
- self.mla_attn = DeepseekV4MultiHeadLatentAttentionWrapper(
370
- hidden_size=self.hidden_size,
371
- num_heads=self.n_local_heads,
372
- head_dim=self.head_dim,
373
- scale=self.softmax_scale,
374
- qk_nope_head_dim=self.nope_head_dim,
375
- qk_rope_head_dim=self.rope_head_dim,
376
- v_head_dim=self.head_dim,
377
- q_lora_rank=self.q_lora_rank,
378
- kv_lora_rank=self.head_dim,
379
- o_lora_rank=self.o_lora_rank,
380
- mla_modules=mla_modules,
377
window_size=self.window_size,
378
compress_ratio=self.compress_ratio,
379
cache_config=vllm_config.cache_config,
@@ -618,7 +614,7 @@ class DeepseekV4Model(nn.Module):
614
self.rms_norm_eps = config.rms_norm_eps
615
616
# Three aux streams: one per non-default input GEMM in
621
- # DeepseekV4MultiHeadLatentAttentionWrapper.attn_gemm_parallel_execute
617
+ # DeepseekV4MLA.attn_gemm_parallel_execute
618
# (compressor kv_score, indexer.weights_proj, indexer.compressor
619
# kv_score). fused_wqa_wkv stays on the default stream.
620
# Disable them on ROCm because of hang issues.
vllm/models/deepseek_v4/attention.py
+34
-88
@@ -5,7 +5,6 @@ DeepseekV4 MLA Attention Layer
5
"""
6
7
from collections.abc import Callable
8
-from dataclasses import dataclass
8
from typing import TYPE_CHECKING, Any, cast
9
10
import torch
@@ -38,9 +37,8 @@ from vllm.config import (
37
get_current_vllm_config,
38
)
39
from vllm.distributed import get_tensor_model_parallel_world_size
41
-from vllm.forward_context import ForwardContext, get_forward_context
40
+from vllm.forward_context import get_forward_context
41
from vllm.logger import init_logger
43
-from vllm.model_executor.custom_op import PluggableLayer
42
from vllm.model_executor.layers.attention_layer_base import AttentionLayerBase
43
from vllm.model_executor.layers.layernorm import RMSNorm
44
from vllm.model_executor.layers.quantization import QuantizationConfig
@@ -90,46 +88,7 @@ def _select_v4_sparse_impl() -> "type[DeepseekV4SparseMLAAttentionImpl]":
88
return DeepseekV4FlashMLASparseImpl
89
90
93
-@dataclass
94
-class DeepseekV4MLAModules:
95
- """Modules used in DeepseekV4 MLA."""
96
-
97
- vllm_config: VllmConfig
98
- fused_wqa_wkv: torch.nn.Module
99
- q_norm: torch.nn.Module
100
- wq_b: torch.nn.Module
101
- kv_norm: torch.nn.Module
102
- wo_a: torch.nn.Module
103
- wo_b: torch.nn.Module
104
- attn_sink: torch.nn.Module
105
- rotary_emb: torch.nn.Module
106
- indexer: torch.nn.Module | None
107
- indexer_rotary_emb: torch.nn.Module
108
- topk_indices_buffer: torch.Tensor | None
109
- aux_stream_list: list[torch.cuda.Stream] | None = None
110
-
111
-
112
-# --8<-- [start:multi_head_latent_attention]
113
-@PluggableLayer.register("deepseek_v4_multi_head_latent_attention")
114
-class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
115
- """Pluggable MLA layer which allows OOT backends to add
116
- custom implementations of the outer MLA layer (including rope & o_proj).
117
- Note that currently oot platforms can still use CustomOp.register_oot to
118
- replace MLA layer entirely, although we use PluggableLayer to register
119
- this layer now.
120
-
121
- This class takes positions and hidden_states as input.
122
- The input tensors can either contain prefill tokens or decode tokens.
123
- The class does the following:
124
-
125
- 1. MLA Preprocess.
126
- 2. Perform multi-head attention to prefill tokens and
127
- multi-query attention to decode tokens separately.
128
- 3. Return the output tensor.
129
- """
130
-
131
- # --8<-- [end:multi_head_latent_attention]
132
-
91
+class DeepseekV4MLA(nn.Module):
92
def __init__(
93
self,
94
hidden_size: int,
@@ -142,7 +101,19 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
101
q_lora_rank: int | None,
102
kv_lora_rank: int,
103
o_lora_rank: int | None,
145
- mla_modules: DeepseekV4MLAModules,
104
+ vllm_config: VllmConfig,
105
+ fused_wqa_wkv: torch.nn.Module,
106
+ q_norm: torch.nn.Module,
107
+ wq_b: torch.nn.Module,
108
+ kv_norm: torch.nn.Module,
109
+ wo_a: torch.nn.Module,
110
+ wo_b: torch.nn.Module,
111
+ attn_sink: torch.nn.Module,
112
+ rotary_emb: torch.nn.Module,
113
+ indexer: torch.nn.Module | None,
114
+ indexer_rotary_emb: torch.nn.Module,
115
+ topk_indices_buffer: torch.Tensor | None,
116
+ aux_stream_list: list[torch.cuda.Stream] | None,
117
window_size: int,
118
compress_ratio: int | None,
119
cache_config: CacheConfig | None = None,
@@ -162,7 +133,7 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
133
self.prefix = prefix
134
135
# Extract config from vllm_config
165
- config = mla_modules.vllm_config.model_config.hf_config
136
+ config = vllm_config.model_config.hf_config
137
tp_size = get_tensor_model_parallel_world_size()
138
139
# DeepseekV4-specific attributes (num_heads is already TP-adjusted)
@@ -173,12 +144,12 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
144
self.o_lora_rank = config.o_lora_rank
145
146
# Store projection modules
176
- self.fused_wqa_wkv = mla_modules.fused_wqa_wkv
177
- self.q_norm = mla_modules.q_norm
178
- self.wq_b = mla_modules.wq_b
147
+ self.fused_wqa_wkv = fused_wqa_wkv
148
+ self.q_norm = q_norm
149
+ self.wq_b = wq_b
150
180
- self.kv_norm = mla_modules.kv_norm
181
- self.wo_a = mla_modules.wo_a
151
+ self.kv_norm = kv_norm
152
+ self.wo_a = wo_a
153
154
self._wo_a_act_quant = QuantFP8(
155
static=False,
@@ -188,7 +159,7 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
159
# Bypass packed-for-deepgemm path — we need FP32 scales (not packed
160
# INT32) so fp8_einsum can handle layout transform internally.
161
self._wo_a_act_quant.use_deep_gemm_supported = False
191
- self.wo_b = mla_modules.wo_b
162
+ self.wo_b = wo_b
163
164
# Pick fp8_einsum recipe based on GPU arch:
165
# SM90: FP32 block scales stay [g, r/128, d/128] → sfb_gran_mn=128
@@ -198,11 +169,11 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
169
self._einsum_recipe = (1, 128, 128) if cap.major <= 9 else (1, 1, 128)
170
self._tma_aligned_scales = cap.major >= 10
171
201
- self.rotary_emb = mla_modules.rotary_emb
202
- self.indexer_rotary_emb = mla_modules.indexer_rotary_emb
203
- self.topk_indices_buffer = mla_modules.topk_indices_buffer
172
+ self.rotary_emb = rotary_emb
173
+ self.indexer_rotary_emb = indexer_rotary_emb
174
+ self.topk_indices_buffer = topk_indices_buffer
175
205
- self.indexer = mla_modules.indexer
176
+ self.indexer = indexer
177
178
# Per-head RMS normalization for Q (no learnable weights)
179
self.q_head_norm = RMSNorm(head_dim, eps=self.eps, has_weight=False)
@@ -216,7 +187,7 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
187
)
188
189
# Will be None on ROCm for now.
219
- self.aux_stream_list = mla_modules.aux_stream_list
190
+ self.aux_stream_list = aux_stream_list
191
# [0]: GEMM start / post-GEMM event0. [1..3]: GEMM done events;
192
# [1] doubles as post-GEMM event1. Reuse is safe: GEMM fully joins
193
# before post-GEMM starts.
@@ -243,7 +214,7 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
214
window_size=self.window_size,
215
head_bytes=head_bytes,
216
swa_cache_layer=self.swa_cache_layer,
246
- attn_sink=mla_modules.attn_sink, # already padded with -inf
217
+ attn_sink=attn_sink, # already padded with -inf
218
cache_config=cache_config,
219
quant_config=quant_config,
220
prefix=prefix,
@@ -253,21 +224,12 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
224
# Mirror the inner layer's padded head count (single source of truth).
225
self.padded_heads = self.mla_attn.padded_heads
226
256
- # Register this layer in the compilation config's static forward context
257
- # This allows the custom op to retrieve the layer during execution
258
- compilation_config = mla_modules.vllm_config.compilation_config
259
- # HACK
260
- self.layer_name = prefix + ".deepseek_v4_multi_head_latent_attention"
261
- if self.layer_name in compilation_config.static_forward_context:
262
- raise ValueError(f"Duplicate layer name: {self.layer_name}")
263
- compilation_config.static_forward_context[self.layer_name] = self
264
-
227
# Create the compressor for layers with compress_ratio > 1; after
228
# creating the DeepseekV4MLAAttention layer to get its cache.
229
self.compressor = None
230
if self.compress_ratio > 1:
231
self.compressor = DeepseekCompressor(
270
- vllm_config=mla_modules.vllm_config,
232
+ vllm_config=vllm_config,
233
compress_ratio=self.compress_ratio,
234
hidden_size=self.hidden_size,
235
head_dim=self.head_dim,
@@ -291,15 +253,10 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
253
device=hidden_states.device,
254
)
255
294
- # @eager_break_during_capture: this is where the breakable
295
- # cudagraph capture breaks (the attention op runs eagerly between
296
- # captured graph segments).
297
- deepseek_v4_attention(
298
- hidden_states,
299
- positions,
300
- o_padded,
301
- self.layer_name,
302
- )
256
+ # attention_impl is wrapped with @eager_break_during_capture: this is
257
+ # where the breakable cudagraph capture breaks (the attention op runs
258
+ # eagerly between captured graph segments).
259
+ self.attention_impl(hidden_states, positions, o_padded)
260
o = o_padded[:, : self.n_local_heads, :]
261
262
# Keep ROCm on the BF16 reference wo_a path util kernel ready.
@@ -405,6 +362,7 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
362
363
return qr_kv, kv_score, indexer_kv_score, indexer_weights
364
365
+ @eager_break_during_capture
366
def attention_impl(
367
self,
368
hidden_states: torch.Tensor,
@@ -541,18 +499,6 @@ class DeepseekV4MultiHeadLatentAttentionWrapper(PluggableLayer):
499
)
500
501
544
-@eager_break_during_capture
545
-def deepseek_v4_attention(
546
- hidden_states: torch.Tensor,
547
- positions: torch.Tensor,
548
- out: torch.Tensor,
549
- layer_name: str,
550
-) -> None:
551
- forward_context: ForwardContext = get_forward_context()
552
- self = forward_context.no_compile_layers[layer_name]
553
- self.attention_impl(hidden_states, positions, out)
554
-
555
-
502
class DeepseekV4MLAAttention(nn.Module, AttentionLayerBase):
503
def __init__(
504
self,
vllm/models/deepseek_v4/nvidia/model.py
+14
-18
@@ -54,8 +54,7 @@ from vllm.model_executor.models.utils import (
54
from vllm.model_executor.utils import set_weight_attrs
55
from vllm.models.deepseek_v4.attention import (
56
DeepseekV4Indexer,
57
- DeepseekV4MLAModules,
58
- DeepseekV4MultiHeadLatentAttentionWrapper,
57
+ DeepseekV4MLA,
58
)
59
from vllm.models.deepseek_v4.nvidia.ops.prepare_megamoe import prepare_megamoe_inputs
60
from vllm.sequence import IntermediateTensors
@@ -697,7 +696,7 @@ class DeepseekV4Attention(nn.Module):
696
697
self.rope_parameters = config.rope_scaling
698
700
- # Initialize rotary embedding BEFORE DeepseekV4MLAModules (which needs it)
699
+ # Initialize rotary embedding BEFORE DeepseekV4MLA (which needs it)
700
rope_parameters = config.rope_parameters
701
rope_parameters["rope_theta"] = (
702
config.compress_rope_theta if self.compress_ratio > 1 else config.rope_theta
@@ -741,7 +740,17 @@ class DeepseekV4Attention(nn.Module):
740
aux_stream=indexer_aux_stream,
741
)
742
744
- mla_modules = DeepseekV4MLAModules(
743
+ self.mla_attn = DeepseekV4MLA(
744
+ hidden_size=self.hidden_size,
745
+ num_heads=self.n_local_heads,
746
+ head_dim=self.head_dim,
747
+ scale=self.softmax_scale,
748
+ qk_nope_head_dim=self.nope_head_dim,
749
+ qk_rope_head_dim=self.rope_head_dim,
750
+ v_head_dim=self.head_dim,
751
+ q_lora_rank=self.q_lora_rank,
752
+ kv_lora_rank=self.head_dim,
753
+ o_lora_rank=self.o_lora_rank,
754
vllm_config=vllm_config,
755
fused_wqa_wkv=self.fused_wqa_wkv,
756
q_norm=self.q_norm,
@@ -755,19 +764,6 @@ class DeepseekV4Attention(nn.Module):
764
indexer_rotary_emb=self.rotary_emb,
765
topk_indices_buffer=topk_indices_buffer,
766
aux_stream_list=aux_stream_list,
758
- )
759
- self.mla_attn = DeepseekV4MultiHeadLatentAttentionWrapper(
760
- hidden_size=self.hidden_size,
761
- num_heads=self.n_local_heads,
762
- head_dim=self.head_dim,
763
- scale=self.softmax_scale,
764
- qk_nope_head_dim=self.nope_head_dim,
765
- qk_rope_head_dim=self.rope_head_dim,
766
- v_head_dim=self.head_dim,
767
- q_lora_rank=self.q_lora_rank,
768
- kv_lora_rank=self.head_dim,
769
- o_lora_rank=self.o_lora_rank,
770
- mla_modules=mla_modules,
767
window_size=self.window_size,
768
compress_ratio=self.compress_ratio,
769
cache_config=vllm_config.cache_config,
@@ -955,7 +951,7 @@ class DeepseekV4Model(nn.Module):
951
self.rms_norm_eps = config.rms_norm_eps
952
953
# Three aux streams: one per non-default input GEMM in
958
- # DeepseekV4MultiHeadLatentAttentionWrapper.attn_gemm_parallel_execute
954
+ # DeepseekV4MLA.attn_gemm_parallel_execute
955
# (compressor kv_score, indexer.weights_proj, indexer.compressor
956
# kv_score). fused_wqa_wkv stays on the default stream.
957
aux_stream_list = [torch.cuda.Stream() for _ in range(3)]