[Qwen3.5] Support Qwen3.5 Pipeline Parallelism (#19670)
Co-authored-by: luoyuan.luo <luoyuan.luo@antgroup.com>
This commit is contained in:
@@ -30,7 +30,7 @@ from sglang.srt.configs.qwen3_5 import (
|
||||
)
|
||||
|
||||
# Distributed
|
||||
from sglang.srt.distributed import get_pp_group
|
||||
from sglang.srt.distributed import get_pp_group, get_pp_indices
|
||||
from sglang.srt.eplb.expert_distribution import get_global_expert_distribution_recorder
|
||||
from sglang.srt.eplb.expert_location import ModelConfigForExpertLocation
|
||||
|
||||
@@ -59,6 +59,7 @@ from sglang.srt.layers.quantization.base_config import QuantizationConfig
|
||||
from sglang.srt.layers.radix_attention import RadixAttention
|
||||
from sglang.srt.layers.radix_linear_attention import RadixLinearAttention
|
||||
from sglang.srt.layers.rotary_embedding import get_rope
|
||||
from sglang.srt.layers.utils import PPMissingLayer
|
||||
from sglang.srt.layers.vocab_parallel_embedding import VocabParallelEmbedding
|
||||
from sglang.srt.model_executor.cuda_graph_runner import get_is_capture_mode
|
||||
from sglang.srt.model_executor.forward_batch_info import ForwardBatch, PPProxyTensors
|
||||
@@ -680,6 +681,8 @@ class Qwen3_5ForCausalLM(nn.Module):
|
||||
org_num_embeddings=config.vocab_size,
|
||||
enable_tp=not is_dp_attention_enabled(),
|
||||
)
|
||||
else:
|
||||
self.embed_tokens = PPMissingLayer()
|
||||
|
||||
# Decoder layers
|
||||
def get_layer(idx: int, prefix: str):
|
||||
@@ -703,13 +706,36 @@ class Qwen3_5ForCausalLM(nn.Module):
|
||||
prefix=f"{prefix}.layers",
|
||||
)
|
||||
|
||||
pp_rank = self.pp_group.rank_in_group
|
||||
pp_size = self.pp_group.world_size
|
||||
num_layers = config.num_hidden_layers
|
||||
self._start_layer, self._end_layer = (
|
||||
get_pp_indices(
|
||||
num_layers,
|
||||
pp_rank,
|
||||
pp_size,
|
||||
)
|
||||
if pp_rank is not None and pp_size is not None
|
||||
else (0, num_layers)
|
||||
)
|
||||
|
||||
# Final normalization
|
||||
if self.pp_group.is_last_rank:
|
||||
self.norm = GemmaRMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
||||
else:
|
||||
self.norm = PPMissingLayer()
|
||||
|
||||
def get_input_embeddings(self) -> nn.Embedding:
|
||||
def get_input_embeddings(self):
|
||||
return self.embed_tokens
|
||||
|
||||
@property
|
||||
def start_layer(self) -> int:
|
||||
return self._start_layer
|
||||
|
||||
@property
|
||||
def end_layer(self) -> int:
|
||||
return self._end_layer
|
||||
|
||||
@torch.no_grad()
|
||||
def forward(
|
||||
self,
|
||||
@@ -733,7 +759,7 @@ class Qwen3_5ForCausalLM(nn.Module):
|
||||
residual = pp_proxy_tensors["residual"]
|
||||
|
||||
# Pass through decoder layers
|
||||
for layer_idx in range(len(self.layers)):
|
||||
for layer_idx in range(self.start_layer, self.end_layer):
|
||||
layer = self.layers[layer_idx]
|
||||
with get_global_expert_distribution_recorder().with_current_layer(
|
||||
layer_idx
|
||||
@@ -1045,14 +1071,31 @@ class Qwen3_5ForConditionalGeneration(Qwen3VLForConditionalGeneration):
|
||||
|
||||
self.deepstack_visual_indexes = self.visual.deepstack_visual_indexes
|
||||
|
||||
@property
|
||||
def start_layer(self) -> int:
|
||||
return getattr(getattr(self, "model", None), "start_layer", 0)
|
||||
|
||||
@property
|
||||
def end_layer(self) -> int:
|
||||
model = getattr(self, "model", None)
|
||||
end_layer = getattr(model, "end_layer", None)
|
||||
if end_layer is not None:
|
||||
return end_layer
|
||||
cfg = getattr(model, "config", None)
|
||||
return int(getattr(cfg, "num_hidden_layers", 0))
|
||||
|
||||
def get_embed_and_head(self):
|
||||
return self.model.embed_tokens.weight, self.lm_head.weight
|
||||
embed = self.model.embed_tokens.weight if self.pp_group.is_first_rank else None
|
||||
head = self.lm_head.weight if self.pp_group.is_last_rank else None
|
||||
return embed, head
|
||||
|
||||
def set_embed_and_head(self, embed, head):
|
||||
del self.model.embed_tokens.weight
|
||||
del self.lm_head.weight
|
||||
self.model.embed_tokens.weight = embed
|
||||
self.lm_head.weight = head
|
||||
if self.pp_group.is_first_rank and embed is not None:
|
||||
del self.model.embed_tokens.weight
|
||||
self.model.embed_tokens.weight = embed
|
||||
if self.pp_group.is_last_rank and head is not None:
|
||||
del self.lm_head.weight
|
||||
self.lm_head.weight = head
|
||||
torch.cuda.empty_cache()
|
||||
torch.cuda.synchronize()
|
||||
|
||||
@@ -1138,13 +1181,17 @@ class Qwen3_5MoeForConditionalGeneration(Qwen3VLForConditionalGeneration):
|
||||
self.deepstack_visual_indexes = self.visual.deepstack_visual_indexes
|
||||
|
||||
def get_embed_and_head(self):
|
||||
return self.model.embed_tokens.weight, self.lm_head.weight
|
||||
embed = self.model.embed_tokens.weight if self.pp_group.is_first_rank else None
|
||||
head = self.lm_head.weight if self.pp_group.is_last_rank else None
|
||||
return embed, head
|
||||
|
||||
def set_embed_and_head(self, embed, head):
|
||||
del self.model.embed_tokens.weight
|
||||
del self.lm_head.weight
|
||||
self.model.embed_tokens.weight = embed
|
||||
self.lm_head.weight = head
|
||||
if self.pp_group.is_first_rank and embed is not None:
|
||||
del self.model.embed_tokens.weight
|
||||
self.model.embed_tokens.weight = embed
|
||||
if self.pp_group.is_last_rank and head is not None:
|
||||
del self.lm_head.weight
|
||||
self.lm_head.weight = head
|
||||
torch.cuda.empty_cache()
|
||||
torch.cuda.synchronize()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user