run pass llm cp

(cherry picked from commit 1d85394563d96cf22d5d84f15c0e9043582419e4)
This commit is contained in:
abing
2026-09-20 22:07:23 +08:00
committed by minke.yu
parent 6880a47955
commit c2059c4fb2
6 changed files with 63 additions and 16 deletions
+4 -2
View File
@@ -966,12 +966,14 @@ def handle_language_model_only(server_args: Any):
): ):
if flag: if flag:
raise ValueError(f"--language-model-only cannot be combined with {name}") raise ValueError(f"--language-model-only cannot be combined with {name}")
if cfg.disaggregation_mode != "null": hf_config = model_config_of(server_args).hf_config
# V4.1 text-only workers use the standard PD KV transfer path.
if cfg.disaggregation_mode != "null" and hf_config.model_type != "deepseek_v41":
raise ValueError( raise ValueError(
"--language-model-only is incompatible with --disaggregation-mode " "--language-model-only is incompatible with --disaggregation-mode "
"prefill/decode" "prefill/decode"
) )
architectures = model_config_of(server_args).hf_config.architectures architectures = hf_config.architectures
if not any( if not any(
a in server_args.LANGUAGE_MODEL_ONLY_ARCHITECTURES for a in architectures a in server_args.LANGUAGE_MODEL_ONLY_ARCHITECTURES for a in architectures
): ):
@@ -934,9 +934,16 @@ class CommonKVManager(BaseKVManager):
"enable DSpark with the same block size and target/draft KV " "enable DSpark with the same block size and target/draft KV "
"layout. Upgrade both servers together." "layout. Upgrade both servers together."
) )
if info.attn_tp_size != self.attn_tp_size: same_tp_with_prefill_cp = (
info.attn_cp_size > 1
and (self.is_mla_backend or self.is_hybrid_mla_backend)
and self.attn_cp_size == 1
and info.attn_tp_size * info.attn_cp_size == self.attn_tp_size
)
if info.attn_tp_size != self.attn_tp_size and not same_tp_with_prefill_cp:
raise RuntimeError( raise RuntimeError(
"DeepSeek-V4.1 DSpark PD requires the same TP size on both servers" "DeepSeek-V4.1 DSpark PD requires the same TP size on both "
"servers (including prefill CP ranks for MLA)"
) )
if self.dcp_size > 1: if self.dcp_size > 1:
+4
View File
@@ -155,6 +155,10 @@ def free_kv_row_segments(
def maybe_cache_unfinished_req(req: Req, tree_cache: BasePrefixCache, **kwargs): def maybe_cache_unfinished_req(req: Req, tree_cache: BasePrefixCache, **kwargs):
if getattr(req, "skip_radix_cache_insert", False): if getattr(req, "skip_radix_cache_insert", False):
kv_indices = tree_cache.req_to_token_pool.req_to_token[
req.kv.req_pool_idx, : len(req.get_fill_ids())
]
req.prefix_indices = kv_indices.to(dtype=torch.int64, copy=True)
return return
tree_cache.cache_unfinished_req(req, **kwargs) tree_cache.cache_unfinished_req(req, **kwargs)
@@ -385,14 +385,22 @@ class EagerRunner(BaseRunner):
""" """
model = self.model_runner.model model = self.model_runner.model
input_ids = forward_batch.input_ids
input_embeds = kwargs.get("input_embeds") input_embeds = kwargs.get("input_embeds")
# Multimodal spans must be embedded in global token order, before CP
# slicing. The model may also normalize image hash IDs for its router.
prepare_inputs = getattr(model, "prepare_language_model_inputs", None)
if prepare_inputs is not None:
input_ids, input_embeds = prepare_inputs(
input_ids, forward_batch, input_embeds
)
if input_embeds is None: if input_embeds is None:
input_embeds = model.get_input_embeddings()(forward_batch.input_ids) input_embeds = model.get_input_embeddings()(input_ids)
with cp_shard_model_inputs( with cp_shard_model_inputs(
input_embeds, input_embeds,
forward_batch.positions, forward_batch.positions,
forward_batch, forward_batch,
forward_batch.input_ids, input_ids,
) as (sharded_input_embeds, sharded_positions, model_input_ids): ) as (sharded_input_embeds, sharded_positions, model_input_ids):
model_kwargs = {"input_embeds": sharded_input_embeds} model_kwargs = {"input_embeds": sharded_input_embeds}
if (pp_proxy_tensors := kwargs.get("pp_proxy_tensors")) is not None: if (pp_proxy_tensors := kwargs.get("pp_proxy_tensors")) is not None:
@@ -437,7 +445,7 @@ class EagerRunner(BaseRunner):
if aux_hidden_states is None: if aux_hidden_states is None:
logits_kwargs["hidden_states_before_norm"] = hidden_states_before_norm logits_kwargs["hidden_states_before_norm"] = hidden_states_before_norm
return model.logits_processor( return model.logits_processor(
forward_batch.input_ids, input_ids,
hidden_states, hidden_states,
model.lm_head, model.lm_head,
forward_batch, forward_batch,
+34 -9
View File
@@ -2650,7 +2650,8 @@ class DeepseekV4DecoderLayer(nn.Module):
is_nextn=is_nextn, is_nextn=is_nextn,
is_deepseek_v4=True, is_deepseek_v4=True,
vl_correction_bias=config.model_type == "deepseek_v41" vl_correction_bias=config.model_type == "deepseek_v41"
and config.vision_n_layers > 0, and config.vision_n_layers > 0
and not getattr(config, "language_model_only", False),
) )
self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps) self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
@@ -3872,7 +3873,15 @@ class DeepseekV4DecoderLayer(nn.Module):
finally: finally:
forward_batch.num_token_non_padded = saved_num_token_non_padded forward_batch.num_token_non_padded = saved_num_token_non_padded
if _use_cp and get_moe_a2a_backend().is_none(): if _use_cp and get_moe_a2a_backend().is_none():
hidden_states = dsa_cp_reduce_scatter_hidden_states(hidden_states) if self.config.model_type == "deepseek_v41":
parallel = get_parallel()
hidden_states = parallel.tp_group.all_reduce(hidden_states)
parallel = get_parallel()
hidden_states = hidden_states.tensor_split(parallel.attn_cp_size)[
parallel.attn_cp_rank
].contiguous()
else:
hidden_states = dsa_cp_reduce_scatter_hidden_states(hidden_states)
elif _use_tp_moe_gather: elif _use_tp_moe_gather:
hidden_states, global_hidden_states = ( hidden_states, global_hidden_states = (
get_local_dp_buffer(get_parallel().tp_group), get_local_dp_buffer(get_parallel().tp_group),
@@ -4871,7 +4880,7 @@ class DeepseekV4ForCausalLM(nn.Module):
or not get_moe_a2a_backend().is_none() or not get_moe_a2a_backend().is_none()
): ):
raise ValueError( raise ValueError(
"V4.1 vision currently supports TP/EP/DP without CP, PP or MoE A2A" "V4.1 vision supports TP/EP/DP and prefill CP without PP or MoE A2A"
) )
args = SimpleNamespace(**vars(config), dim=config.hidden_size) args = SimpleNamespace(**vars(config), dim=config.hidden_size)
@@ -5078,16 +5087,19 @@ class DeepseekV4ForCausalLM(nn.Module):
0 if is_shared_experts_fusion_disabled() else self.config.n_shared_experts 0 if is_shared_experts_fusion_disabled() else self.config.n_shared_experts
) )
def forward( def prepare_language_model_inputs(
self, self,
input_ids: torch.Tensor, input_ids: torch.Tensor,
positions: torch.Tensor,
forward_batch: ForwardBatch, forward_batch: ForwardBatch,
input_embeds: Optional[torch.Tensor] = None, input_embeds: Optional[torch.Tensor] = None,
pp_proxy_tensors: Optional[PPProxyTensors] = None, ) -> Tuple[torch.Tensor, Optional[torch.Tensor]]:
) -> torch.Tensor: """Prepare full-sequence image embeddings and model IDs before CP splits.
Scheduler hash IDs stay intact for multimodal cache keys; the language
model uses image_token_id for Engram masking and visual MoE routing.
"""
if ( if (
self.vision is not None getattr(self, "vision", None) is not None
and not forward_batch.forward_mode.is_decode() and not forward_batch.forward_mode.is_decode()
and not forward_batch.forward_mode.is_target_verify() and not forward_batch.forward_mode.is_target_verify()
and forward_batch.mm_inputs is not None and forward_batch.mm_inputs is not None
@@ -5096,7 +5108,7 @@ class DeepseekV4ForCausalLM(nn.Module):
if input_embeds is not None: if input_embeds is not None:
raise ValueError("Cannot combine input_embeds and image inputs") raise ValueError("Cannot combine input_embeds and image inputs")
input_embeds = self._prepare_mm_embeddings(input_ids, forward_batch) input_embeds = self._prepare_mm_embeddings(input_ids, forward_batch)
if self.vision is not None and not ( if getattr(self, "vision", None) is not None and not (
forward_batch.forward_mode.is_decode_or_idle() forward_batch.forward_mode.is_decode_or_idle()
or forward_batch.forward_mode.is_target_verify() or forward_batch.forward_mode.is_target_verify()
): ):
@@ -5106,6 +5118,19 @@ class DeepseekV4ForCausalLM(nn.Module):
input_ids >= MM_PAD_SHIFT_VALUE, self.config.image_token_id input_ids >= MM_PAD_SHIFT_VALUE, self.config.image_token_id
) )
return input_ids, input_embeds
def forward(
self,
input_ids: torch.Tensor,
positions: torch.Tensor,
forward_batch: ForwardBatch,
input_embeds: Optional[torch.Tensor] = None,
pp_proxy_tensors: Optional[PPProxyTensors] = None,
) -> torch.Tensor:
input_ids, input_embeds = self.prepare_language_model_inputs(
input_ids, forward_batch, input_embeds
)
with get_attn_tp_context().maybe_input_scattered(forward_batch): with get_attn_tp_context().maybe_input_scattered(forward_batch):
hidden_states = self.model.forward( hidden_states = self.model.forward(
input_ids, positions, forward_batch, input_embeds, pp_proxy_tensors input_ids, positions, forward_batch, input_embeds, pp_proxy_tensors
+1
View File
@@ -331,6 +331,7 @@ class ServerArgs:
# ===== END TO BE REFACTORED ==== # ===== END TO BE REFACTORED ====
LANGUAGE_MODEL_ONLY_ARCHITECTURES = ( LANGUAGE_MODEL_ONLY_ARCHITECTURES = (
"DeepseekV4ForCausalLM",
"MuseGlimmerForConditionalGeneration", "MuseGlimmerForConditionalGeneration",
"Cosmos3ForConditionalGeneration", "Cosmos3ForConditionalGeneration",
"Cosmos3EdgeForConditionalGeneration", "Cosmos3EdgeForConditionalGeneration",