@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 53b19ccdd5
Fork 0

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 14, 05:30 UTC

[Core] Allow disabling TP sharding for parallel Linear layer (#23024)

Signed-off-by: Isotr0py <mozf@mail2.sysu.edu.cn> Signed-off-by: Isotr0py <2037008807@qq.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

Isotr0py committed Sep 6, 2025 at 13:53 UTC 53b19ccdd5a04f442283a9b077b78da3b0df79d4
7 files changed +205 -282
vllm/model_executor/layers/linear.py
+70 -105
@@ -223,6 +223,7 @@ class LinearBase(CustomOp):
223 quant_config: Quantization configure.
224 prefix: Prefix for parameter names.
225 return_bias: If true, return bias together with outputs in forward pass.
226 + disable_tp: If true, tensor parallelism will be disabled for this layer.
227 """
228
229 def __init__(
@@ -235,6 +236,7 @@ class LinearBase(CustomOp):
236 prefix: str = "",
237 *,
238 return_bias: bool = True,
239 + disable_tp: bool = False,
240 ):
241 super().__init__()
242
@@ -254,6 +256,17 @@ class LinearBase(CustomOp):
256 self.quant_method = quant_config.get_quant_method(self,
257 prefix=prefix)
258 self.return_bias = return_bias
259 + self.disable_tp = disable_tp
260 + self.tp_rank = (get_tensor_model_parallel_rank()
261 + if not disable_tp else 0)
262 + self.tp_size = (get_tensor_model_parallel_world_size()
263 + if not disable_tp else 1)
264 +
265 + def __post_init__(self):
266 + for param in self.parameters():
267 + if isinstance(param, BasevLLMParameter):
268 + param.tp_rank = self.tp_rank
269 + param.tp_size = self.tp_size
270
271
272 @CustomOp.register("replicated_linear")
@@ -270,6 +283,7 @@ class ReplicatedLinear(LinearBase):
283 prefix: The name of the layer in the state dict, including all parents
284 (e.g. model.layers.0.qkv_proj)
285 return_bias: If true, return bias together with outputs in forward pass.
286 + disable_tp: Take no effect for replicated linear layers.
287 """
288
289 def __init__(
@@ -283,26 +297,21 @@ class ReplicatedLinear(LinearBase):
297 prefix: str = "",
298 *,
299 return_bias: bool = True,
300 + disable_tp: bool = False,
301 ):
287 - # If MergedReplicatedLinear, use output size of each partition.
288 - if hasattr(self, "output_sizes"):
289 - self.output_partition_sizes = self.output_sizes
290 - else:
291 - self.output_partition_sizes = [output_size]
292 -
302 super().__init__(input_size,
303 output_size,
304 skip_bias_add,
305 params_dtype,
306 quant_config,
307 prefix=prefix,
299 - return_bias=return_bias)
308 + return_bias=return_bias,
309 + disable_tp=disable_tp)
310
311 # All the linear layer supports quant method.
312 assert self.quant_method is not None
313 self.quant_method.create_weights(self,
304 - self.input_size,
305 - self.output_partition_sizes,
314 + self.input_size, [self.output_size],
315 self.input_size,
316 self.output_size,
317 self.params_dtype,
@@ -358,74 +367,6 @@ class ReplicatedLinear(LinearBase):
367 return s
368
369
361 -class MergedReplicatedLinear(ReplicatedLinear):
362 - """Replicated linear layer.
363 -
364 - Args:
365 - input_size: input dimension of the linear layer.
366 - output_sizes: list of output dimensions of the linear layer.
367 - bias: If true, add bias.
368 - skip_bias_add: If true, skip adding bias but instead return it.
369 - params_dtype: Data type for the parameters.
370 - quant_config: Quantization configure.
371 - prefix: The name of the layer in the state dict, including all parents
372 - (e.g. model.layers.0.qkv_proj)
373 - return_bias: If true, return bias together with outputs in forward pass.
374 - """
375 -
376 - def __init__(
377 - self,
378 - input_size: int,
379 - output_sizes: list[int],
380 - bias: bool = True,
381 - skip_bias_add: bool = False,
382 - params_dtype: Optional[torch.dtype] = None,
383 - quant_config: Optional[QuantizationConfig] = None,
384 - prefix: str = "",
385 - *,
386 - return_bias: bool = True,
387 - ):
388 - self.output_sizes = output_sizes
389 - super().__init__(input_size,
390 - sum(output_sizes),
391 - bias,
392 - skip_bias_add,
393 - params_dtype,
394 - quant_config,
395 - prefix=prefix,
396 - return_bias=return_bias)
397 -
398 - def weight_loader(self,
399 - param: Union[Parameter, BasevLLMParameter],
400 - loaded_weight: torch.Tensor,
401 - loaded_shard_id: Optional[int] = None):
402 - assert loaded_shard_id is not None
403 - assert loaded_shard_id < len(self.output_sizes)
404 -
405 - if isinstance(param, BlockQuantScaleParameter):
406 - from vllm.model_executor.layers.quantization.fp8 import (
407 - Fp8LinearMethod, Fp8MoEMethod)
408 - assert self.quant_method is not None
409 - assert isinstance(self.quant_method,
410 - (Fp8LinearMethod, Fp8MoEMethod))
411 - weight_block_size = self.quant_method.quant_config.weight_block_size
412 - assert weight_block_size is not None
413 - block_n, _ = weight_block_size[0], weight_block_size[1]
414 - shard_offset = (
415 - (sum(self.output_sizes[:loaded_shard_id]) + block_n - 1) //
416 - block_n)
417 - shard_size = ((self.output_sizes[loaded_shard_id] + block_n - 1) //
418 - block_n)
419 - elif isinstance(param, PerTensorScaleParameter):
420 - shard_offset = loaded_shard_id
421 - shard_size = 1
422 - else:
423 - shard_offset = sum(self.output_sizes[:loaded_shard_id])
424 - shard_size = self.output_sizes[loaded_shard_id]
425 -
426 - param.data[shard_offset:shard_offset + shard_size] = loaded_weight
427 -
428 -
370 @CustomOp.register("column_parallel_linear")
371 class ColumnParallelLinear(LinearBase):
372 """Linear layer with column parallelism.
@@ -448,7 +389,9 @@ class ColumnParallelLinear(LinearBase):
389 output_sizes: list of output sizes packed into one output, like for QKV
390 the list would be size 3.
391 prefix: The name of the layer in the state dict, including all parents
451 - (e.g. model.layers.0.qkv_proj)
392 + (e.g. model.layers.0.qkv_proj)
393 + return_bias: If true, return bias together with outputs in forward pass.
394 + disable_tp: If true, weights matrix won't be sharded through tp rank.
395 """
396
397 def __init__(
@@ -464,9 +407,13 @@ class ColumnParallelLinear(LinearBase):
407 prefix: str = "",
408 *,
409 return_bias: bool = True,
410 + disable_tp: bool = False,
411 ):
412 # Divide the weight matrix along the last dimension.
469 - self.tp_size = get_tensor_model_parallel_world_size()
413 + self.tp_rank = (get_tensor_model_parallel_rank()
414 + if not disable_tp else 0)
415 + self.tp_size = (get_tensor_model_parallel_world_size()
416 + if not disable_tp else 1)
417 self.input_size_per_partition = input_size
418 self.output_size_per_partition = divide(output_size, self.tp_size)
419 self.output_partition_sizes = [self.output_size_per_partition]
@@ -483,7 +430,8 @@ class ColumnParallelLinear(LinearBase):
430 params_dtype,
431 quant_config,
432 prefix,
486 - return_bias=return_bias)
433 + return_bias=return_bias,
434 + disable_tp=disable_tp)
435
436 self.gather_output = gather_output
437
@@ -512,8 +460,6 @@ class ColumnParallelLinear(LinearBase):
460 else:
461 self.register_parameter("bias", None)
462
515 - self.tp_rank = get_tensor_model_parallel_rank()
516 -
463 def weight_loader(self, param: Parameter, loaded_weight: torch.Tensor):
464
465 output_dim = getattr(param, "output_dim", None)
@@ -554,7 +500,8 @@ class ColumnParallelLinear(LinearBase):
500 assert param_data.shape == loaded_weight.shape
501 param_data.copy_(loaded_weight)
502
557 - def weight_loader_v2(self, param: Parameter, loaded_weight: torch.Tensor):
503 + def weight_loader_v2(self, param: BasevLLMParameter,
504 + loaded_weight: torch.Tensor):
505 # Special case for loading scales off disk, which often do not
506 # have a shape (such as in the case of AutoFP8).
507 if len(loaded_weight.shape) == 0:
@@ -570,7 +517,7 @@ class ColumnParallelLinear(LinearBase):
517 # Matrix multiply.
518 assert self.quant_method is not None
519 output_parallel = self.quant_method.apply(self, input_, bias)
573 - if self.gather_output:
520 + if self.gather_output and self.tp_size > 1:
521 # All-gather across the partitions.
522 output = tensor_model_parallel_all_gather(output_parallel)
523 else:
@@ -584,7 +531,7 @@ class ColumnParallelLinear(LinearBase):
531 s = f"in_features={self.input_size}"
532 s += f", output_features={self.output_size_per_partition}"
533 s += f", bias={self.bias is not None}"
587 - s += f", tp_size={get_tensor_model_parallel_world_size()}"
534 + s += f", tp_size={self.tp_size}"
535 s += f", gather_output={self.gather_output}"
536 return s
537
@@ -611,6 +558,8 @@ class MergedColumnParallelLinear(ColumnParallelLinear):
558 prefix: The name of the layer in the state dict, including all parents
559 (e.g. model.layers.0.qkv_proj)
560 return_bias: If true, return bias together with outputs in forward pass.
561 + disable_tp: If true, all weights matrix won't be sharded, this layer
562 + will be treated as a "Replicated" MergedLinear.
563 """
564
565 def __init__(
@@ -625,10 +574,13 @@ class MergedColumnParallelLinear(ColumnParallelLinear):
574 prefix: str = "",
575 *,
576 return_bias: bool = True,
577 + disable_tp: bool = False,
578 ):
579 self.output_sizes = output_sizes
630 - self.tp_size = get_tensor_model_parallel_world_size()
631 - self.tp_rank = get_tensor_model_parallel_rank()
580 + self.tp_size = (get_tensor_model_parallel_world_size()
581 + if not disable_tp else 1)
582 + self.tp_rank = (get_tensor_model_parallel_rank()
583 + if not disable_tp else 0)
584
585 assert all(output_size % self.tp_size == 0
586 for output_size in output_sizes)
@@ -640,7 +592,8 @@ class MergedColumnParallelLinear(ColumnParallelLinear):
592 params_dtype=params_dtype,
593 quant_config=quant_config,
594 prefix=prefix,
643 - return_bias=return_bias)
595 + return_bias=return_bias,
596 + disable_tp=disable_tp)
597
598 def weight_loader(self,
599 param: Parameter,
@@ -832,8 +785,6 @@ class MergedColumnParallelLinear(ColumnParallelLinear):
785
786 assert loaded_shard_id < len(self.output_sizes)
787
835 - tp_size = get_tensor_model_parallel_world_size()
836 -
788 if isinstance(param, BlockQuantScaleParameter):
789 from vllm.model_executor.layers.quantization.fp8 import (
790 Fp8LinearMethod, Fp8MoEMethod)
@@ -845,17 +796,19 @@ class MergedColumnParallelLinear(ColumnParallelLinear):
796 block_n, _ = weight_block_size[0], weight_block_size[1]
797 shard_offset = (
798 (sum(self.output_sizes[:loaded_shard_id]) + block_n - 1) //
848 - block_n) // tp_size
799 + block_n) // self.tp_size
800 shard_size = ((self.output_sizes[loaded_shard_id] + block_n - 1) //
850 - block_n // tp_size)
801 + block_n // self.tp_size)
802 else:
852 - shard_offset = sum(self.output_sizes[:loaded_shard_id]) // tp_size
853 - shard_size = self.output_sizes[loaded_shard_id] // tp_size
803 + shard_offset = sum(
804 + self.output_sizes[:loaded_shard_id]) // self.tp_size
805 + shard_size = self.output_sizes[loaded_shard_id] // self.tp_size
806
807 param.load_merged_column_weight(loaded_weight=loaded_weight,
808 shard_id=loaded_shard_id,
809 shard_offset=shard_offset,
858 - shard_size=shard_size)
810 + shard_size=shard_size,
811 + tp_rank=self.tp_rank)
812
813
814 class QKVParallelLinear(ColumnParallelLinear):
@@ -883,6 +836,7 @@ class QKVParallelLinear(ColumnParallelLinear):
836 prefix: The name of the layer in the state dict, including all parents
837 (e.g. model.layers.0.qkv_proj)
838 return_bias: If true, return bias together with outputs in forward pass.
839 + disable_tp: If true, weights matrix won't be sharded through tp rank.
840 """
841
842 def __init__(
@@ -898,6 +852,7 @@ class QKVParallelLinear(ColumnParallelLinear):
852 prefix: str = "",
853 *,
854 return_bias: bool = True,
855 + disable_tp: bool = False,
856 ):
857 self.hidden_size = hidden_size
858 self.head_size = head_size
@@ -906,7 +861,8 @@ class QKVParallelLinear(ColumnParallelLinear):
861 total_num_kv_heads = total_num_heads
862 self.total_num_kv_heads = total_num_kv_heads
863 # Divide the weight matrix along the last dimension.
909 - tp_size = get_tensor_model_parallel_world_size()
864 + tp_size = (get_tensor_model_parallel_world_size()
865 + if not disable_tp else 1)
866 self.num_heads = divide(self.total_num_heads, tp_size)
867 if tp_size >= self.total_num_kv_heads:
868 self.num_kv_heads = 1
@@ -932,7 +888,8 @@ class QKVParallelLinear(ColumnParallelLinear):
888 params_dtype=params_dtype,
889 quant_config=quant_config,
890 prefix=prefix,
935 - return_bias=return_bias)
891 + return_bias=return_bias,
892 + disable_tp=disable_tp)
893
894 def _get_shard_offset_mapping(self, loaded_shard_id: str):
895 shard_offset_mapping = {
@@ -993,10 +950,13 @@ class QKVParallelLinear(ColumnParallelLinear):
950 loaded_shard_id: Optional[str] = None):
951 if loaded_shard_id is None: # special case for certain models
952 if isinstance(param, PerTensorScaleParameter):
996 - param.load_qkv_weight(loaded_weight=loaded_weight, shard_id=0)
953 + param.load_qkv_weight(loaded_weight=loaded_weight,
954 + shard_id=0,
955 + tp_rank=self.tp_rank)
956 return
957 elif type(param) in (RowvLLMParameter, BasevLLMParameter):
999 - param.load_qkv_weight(loaded_weight=loaded_weight)
958 + param.load_qkv_weight(loaded_weight=loaded_weight,
959 + tp_rank=self.tp_rank)
960 return
961 # TODO: @dsikka - move to parameter.py
962 self._load_fused_module_from_checkpoint(param, loaded_weight)
@@ -1020,7 +980,8 @@ class QKVParallelLinear(ColumnParallelLinear):
980 num_heads=self.num_kv_head_replicas,
981 shard_id=loaded_shard_id,
982 shard_offset=shard_offset,
1023 - shard_size=shard_size)
983 + shard_size=shard_size,
984 + tp_rank=self.tp_rank)
985
986 def weight_loader(self,
987 param: Parameter,
@@ -1226,6 +1187,7 @@ class RowParallelLinear(LinearBase):
1187 prefix: The name of the layer in the state dict, including all parents
1188 (e.g. model.layers.0.down_proj)
1189 return_bias: If true, return bias together with outputs in forward pass.
1190 + disable_tp: If true, weights matrix won't be sharded through tp rank.
1191 """
1192
1193 def __init__(
@@ -1241,10 +1203,13 @@ class RowParallelLinear(LinearBase):
1203 prefix: str = "",
1204 *,
1205 return_bias: bool = True,
1206 + disable_tp: bool = False,
1207 ):
1208 # Divide the weight matrix along the first dimension.
1246 - self.tp_rank = get_tensor_model_parallel_rank()
1247 - self.tp_size = get_tensor_model_parallel_world_size()
1209 + self.tp_rank = (get_tensor_model_parallel_rank()
1210 + if not disable_tp else 0)
1211 + self.tp_size = (get_tensor_model_parallel_world_size()
1212 + if not disable_tp else 1)
1213 self.input_size_per_partition = divide(input_size, self.tp_size)
1214 self.output_size_per_partition = output_size
1215 self.output_partition_sizes = [output_size]
@@ -1255,7 +1220,8 @@ class RowParallelLinear(LinearBase):
1220 params_dtype,
1221 quant_config,
1222 prefix,
1258 - return_bias=return_bias)
1223 + return_bias=return_bias,
1224 + disable_tp=disable_tp)
1225
1226 self.input_is_parallel = input_is_parallel
1227 self.reduce_results = reduce_results
@@ -1339,10 +1305,9 @@ class RowParallelLinear(LinearBase):
1305 if self.input_is_parallel:
1306 input_parallel = input_
1307 else:
1342 - tp_rank = get_tensor_model_parallel_rank()
1308 splitted_input = split_tensor_along_last_dim(
1309 input_, num_partitions=self.tp_size)
1345 - input_parallel = splitted_input[tp_rank].contiguous()
1310 + input_parallel = splitted_input[self.tp_rank].contiguous()
1311
1312 # Matrix multiply.
1313 assert self.quant_method is not None
vllm/model_executor/model_loader/bitsandbytes_loader.py
+19 -4
@@ -69,6 +69,7 @@ class BitsAndBytesModelLoader(BaseModelLoader):
69 # Store all module names (from transformers) that support
70 # BNB quantization.
71 self.target_modules: list[str] = []
72 + self.tp_disabled_modules: list[str] = []
73 # Store the mapping of expert parameters for MoE models.
74 self.expert_params_mapping: list[tuple[str, str, int, str]] = []
75 # mapping weight names from transformers to vllm.
@@ -322,14 +323,24 @@ class BitsAndBytesModelLoader(BaseModelLoader):
323 quant_state_dict) -> Generator:
324 from bitsandbytes.functional import quantize_4bit
325
325 - tp_size = get_tensor_model_parallel_world_size()
326 - tp_rank = get_tensor_model_parallel_rank()
326 + global_tp_size = get_tensor_model_parallel_world_size()
327 + global_tp_rank = get_tensor_model_parallel_rank()
328
329 for (
330 org_weight_name,
331 mapped_weight_name,
332 weight_tensor,
333 ) in self._hf_weight_iter(hf_weights_files, use_safetensors):
334 +
335 + # override tp_size and tp_rank if the module has disabled TP
336 + if any(tp_disabled_module in mapped_weight_name
337 + for tp_disabled_module in self.tp_disabled_modules):
338 + tp_size = 1
339 + tp_rank = 0
340 + else:
341 + tp_size = global_tp_size
342 + tp_rank = global_tp_rank
343 +
344 if any(target_module in mapped_weight_name
345 for target_module in self.target_modules
346 ) and mapped_weight_name.endswith(".weight"):
@@ -418,12 +429,16 @@ class BitsAndBytesModelLoader(BaseModelLoader):
429 # Map vllm's names to transformers's names.
430 rep_name, sub_modules = modules_info
431 for sub_name in sub_modules:
421 - self.target_modules.append(
422 - name.replace(rep_name, sub_name))
432 + new_name = name.replace(rep_name, sub_name)
433 + self.target_modules.append(new_name)
434 + if module.disable_tp:
435 + self.tp_disabled_modules.append(new_name)
436 # Add original module name even if the module has stacked map,
437 # in case model has a mixture of disk-merged and disk-split
438 # weights with same last name.
439 self.target_modules.append(name)
440 + if module.disable_tp:
441 + self.tp_disabled_modules.append(name)
442 elif isinstance(module, FusedMoE) and hasattr(
443 module.quant_method, "quant_config"):
444 # TODO: support FusedMoE with prequant and 8bit.
vllm/model_executor/models/deepseek_v2.py
+3 -3
@@ -43,7 +43,6 @@ from vllm.model_executor.layers.fused_moe import FusedMoE
43 from vllm.model_executor.layers.layernorm import RMSNorm
44 from vllm.model_executor.layers.linear import (ColumnParallelLinear,
45 MergedColumnParallelLinear,
46 - MergedReplicatedLinear,
46 ReplicatedLinear,
47 RowParallelLinear)
48 from vllm.model_executor.layers.logits_processor import LogitsProcessor
@@ -435,12 +434,13 @@ class DeepseekV2MLAAttention(nn.Module):
434 self.max_position_embeddings = max_position_embeddings
435
436 if self.q_lora_rank is not None:
438 - self.fused_qkv_a_proj = MergedReplicatedLinear(
437 + self.fused_qkv_a_proj = MergedColumnParallelLinear(
438 self.hidden_size,
439 [self.q_lora_rank, self.kv_lora_rank + self.qk_rope_head_dim],
440 bias=False,
441 quant_config=quant_config,
443 - prefix=f"{prefix}.fused_qkv_a_proj")
442 + prefix=f"{prefix}.fused_qkv_a_proj",
443 + disable_tp=True)
444 else:
445 self.kv_a_proj_with_mqa = ReplicatedLinear(
446 self.hidden_size,
vllm/model_executor/models/glm4_1v.py
+50 -78
@@ -51,14 +51,10 @@ from vllm.distributed import utils as dist_utils
51 from vllm.logger import init_logger
52 from vllm.model_executor import SamplingMetadata
53 from vllm.model_executor.layers.layernorm import RMSNorm
54 -# yapf: disable
54 from vllm.model_executor.layers.linear import (ColumnParallelLinear,
55 MergedColumnParallelLinear,
57 - MergedReplicatedLinear,
56 QKVParallelLinear,
59 - ReplicatedLinear,
57 RowParallelLinear)
61 -# yapf: enable
58 from vllm.model_executor.layers.quantization import QuantizationConfig
59 from vllm.model_executor.model_loader.weight_utils import default_weight_loader
60 from vllm.model_executor.models.module_mapping import MultiModelKeys
@@ -174,20 +170,22 @@ class Glm4vVisionMLP(nn.Module):
170 use_data_parallel: bool = False,
171 ):
172 super().__init__()
177 - cls_gate_up = (MergedReplicatedLinear
178 - if use_data_parallel else MergedColumnParallelLinear)
179 - self.gate_up_proj = cls_gate_up(input_size=in_features,
180 - output_sizes=[hidden_features] * 2,
181 - bias=bias,
182 - quant_config=quant_config,
183 - prefix=f"{prefix}.gate_up_proj")
184 - cls_down = (ReplicatedLinear
185 - if use_data_parallel else RowParallelLinear)
186 - self.down_proj = cls_down(hidden_features,
187 - in_features,
188 - bias=bias,
189 - quant_config=quant_config,
190 - prefix=f"{prefix}.down_proj")
173 + self.gate_up_proj = MergedColumnParallelLinear(
174 + input_size=in_features,
175 + output_sizes=[hidden_features] * 2,
176 + bias=bias,
177 + quant_config=quant_config,
178 + prefix=f"{prefix}.gate_up_proj",
179 + disable_tp=use_data_parallel,
180 + )
181 + self.down_proj = RowParallelLinear(
182 + hidden_features,
183 + in_features,
184 + bias=bias,
185 + quant_config=quant_config,
186 + prefix=f"{prefix}.down_proj",
187 + disable_tp=use_data_parallel,
188 + )
189 self.act_fn = SiluAndMul()
190
191 def forward(self, x: torch.Tensor):
@@ -234,48 +232,32 @@ class Glm4vVisionAttention(nn.Module):
232 # Per attention head and per partition values.
233 self.tp_size = (1 if use_data_parallel else
234 get_tensor_model_parallel_world_size())
237 - self.tp_rank = parallel_state.get_tensor_model_parallel_rank()
235 + self.tp_rank = (0 if use_data_parallel else
236 + parallel_state.get_tensor_model_parallel_rank())
237 self.hidden_size_per_attention_head = dist_utils.divide(
238 projection_size, num_heads)
239 self.num_attention_heads_per_partition = dist_utils.divide(
240 num_heads, self.tp_size)
241
243 - if use_data_parallel:
244 - self.qkv = ReplicatedLinear(
245 - input_size=embed_dim,
246 - output_size=3 * projection_size,
247 - bias=False,
248 - quant_config=quant_config,
249 - # Change qkv prefix to align with GLM-4.5V-FP8 quantization cfg
250 - prefix=f"{prefix}.qkv_proj"
251 - if quant_config else f"{prefix}.qkv",
252 - )
253 - self.proj = ReplicatedLinear(
254 - input_size=projection_size,
255 - output_size=embed_dim,
256 - quant_config=quant_config,
257 - prefix=f"{prefix}.proj",
258 - bias=False,
259 - )
260 - else:
261 - self.qkv = QKVParallelLinear(
262 - hidden_size=embed_dim,
263 - head_size=self.hidden_size_per_attention_head,
264 - total_num_heads=num_heads,
265 - total_num_kv_heads=num_heads,
266 - bias=False,
267 - quant_config=quant_config,
268 - # Change qkv prefix to align with GLM-4.5V-FP8 quantization cfg
269 - prefix=f"{prefix}.qkv_proj"
270 - if quant_config else f"{prefix}.qkv",
271 - )
272 - self.proj = RowParallelLinear(
273 - input_size=projection_size,
274 - output_size=embed_dim,
275 - quant_config=quant_config,
276 - prefix=f"{prefix}.proj",
277 - bias=False,
278 - )
242 + self.qkv = QKVParallelLinear(
243 + hidden_size=embed_dim,
244 + head_size=self.hidden_size_per_attention_head,
245 + total_num_heads=num_heads,
246 + total_num_kv_heads=num_heads,
247 + bias=False,
248 + quant_config=quant_config,
249 + # Change qkv prefix to align with GLM-4.5V-FP8 quantization cfg
250 + prefix=f"{prefix}.qkv_proj" if quant_config else f"{prefix}.qkv",
251 + disable_tp=use_data_parallel,
252 + )
253 + self.proj = RowParallelLinear(
254 + input_size=projection_size,
255 + output_size=embed_dim,
256 + quant_config=quant_config,
257 + prefix=f"{prefix}.proj",
258 + bias=False,
259 + disable_tp=use_data_parallel,
260 + )
261
262 # Detect attention implementation.
263 self.attn_backend: _Backend = get_vit_attn_backend(support_fa=True)
@@ -494,41 +476,31 @@ class Glm4vPatchMerger(nn.Module):
476 ) -> None:
477 super().__init__()
478 self.hidden_size = d_model
497 - if use_data_parallel:
498 - self.proj = ReplicatedLinear(
499 - input_size=self.hidden_size,
500 - output_size=self.hidden_size,
501 - bias=bias,
502 - quant_config=quant_config,
503 - prefix=f"{prefix}.proj",
504 - )
505 - else:
506 - self.proj = ColumnParallelLinear(
507 - self.hidden_size,
508 - self.hidden_size,
509 - bias=bias,
510 - gather_output=True,
511 - quant_config=quant_config,
512 - prefix=f"{prefix}.proj",
513 - )
479 + self.proj = ColumnParallelLinear(
480 + self.hidden_size,
481 + self.hidden_size,
482 + bias=bias,
483 + gather_output=True,
484 + quant_config=quant_config,
485 + prefix=f"{prefix}.proj",
486 + disable_tp=use_data_parallel,
487 + )
488 self.post_projection_norm = nn.LayerNorm(self.hidden_size)
515 - cls_gate_up = (MergedReplicatedLinear
516 - if use_data_parallel else MergedColumnParallelLinear)
517 - self.gate_up_proj = cls_gate_up(
489 + self.gate_up_proj = MergedColumnParallelLinear(
490 input_size=self.hidden_size,
491 output_sizes=[context_dim] * 2,
492 bias=bias,
493 quant_config=quant_config,
494 prefix=f"{prefix}.gate_up_proj",
495 + disable_tp=use_data_parallel,
496 )
524 - cls_down = (ReplicatedLinear
525 - if use_data_parallel else RowParallelLinear)
526 - self.down_proj = cls_down(
497 + self.down_proj = RowParallelLinear(
498 context_dim,
499 self.hidden_size,
500 bias=bias,
501 quant_config=quant_config,
502 prefix=f"{prefix}.down_proj",
503 + disable_tp=use_data_parallel,
504 )
505 self.act_fn = SiluAndMul()
506 self.extra_activation_func = nn.GELU()
vllm/model_executor/models/qwen2_5_vl.py
+25 -37
@@ -48,7 +48,6 @@ from vllm.model_executor.layers.layernorm import RMSNorm
48 # yapf: disable
49 from vllm.model_executor.layers.linear import (ColumnParallelLinear,
50 MergedColumnParallelLinear,
51 - MergedReplicatedLinear,
51 QKVParallelLinear,
52 ReplicatedLinear,
53 RowParallelLinear)
@@ -178,22 +177,20 @@ class Qwen2_5_VisionMLP(nn.Module):
177 prefix: str = "",
178 use_data_parallel: bool = False):
179 super().__init__()
181 - cls_gate_up_proj = (MergedReplicatedLinear if use_data_parallel else
182 - MergedColumnParallelLinear)
183 - self.gate_up_proj = cls_gate_up_proj(
180 + self.gate_up_proj = MergedColumnParallelLinear(
181 input_size=in_features,
182 output_sizes=[hidden_features] * 2, # [gate_proj, up_proj]
183 bias=bias,
184 quant_config=quant_config,
188 - prefix=f"{prefix}.gate_up_proj")
189 -
190 - cls_down_proj = (ReplicatedLinear
191 - if use_data_parallel else RowParallelLinear)
192 - self.down_proj = cls_down_proj(hidden_features,
193 - in_features,
194 - bias=bias,
195 - quant_config=quant_config,
196 - prefix=f"{prefix}.down_proj")
185 + prefix=f"{prefix}.gate_up_proj",
186 + disable_tp=use_data_parallel)
187 +
188 + self.down_proj = RowParallelLinear(hidden_features,
189 + in_features,
190 + bias=bias,
191 + quant_config=quant_config,
192 + prefix=f"{prefix}.down_proj",
193 + disable_tp=use_data_parallel)
194 self.act_fn = act_fn
195
196 def forward(self, x: torch.Tensor):
@@ -243,30 +240,21 @@ class Qwen2_5_VisionAttention(nn.Module):
240 self.num_attention_heads_per_partition = dist_utils.divide(
241 num_heads, self.tp_size)
242
246 - if use_data_parallel:
247 - self.qkv = ReplicatedLinear(embed_dim,
248 - self.hidden_size_per_attention_head *
249 - 3 * num_heads,
250 - bias=True,
251 - quant_config=quant_config,
252 - prefix=f"{prefix}.qkv")
253 -
254 - else:
255 - self.qkv = QKVParallelLinear(
256 - hidden_size=embed_dim,
257 - head_size=self.hidden_size_per_attention_head,
258 - total_num_heads=num_heads,
259 - total_num_kv_heads=num_heads,
260 - bias=True,
261 - quant_config=quant_config,
262 - prefix=f"{prefix}.qkv")
263 -
264 - cls_proj = (ReplicatedLinear
265 - if use_data_parallel else RowParallelLinear)
266 - self.proj = cls_proj(input_size=projection_size,
267 - output_size=embed_dim,
268 - quant_config=quant_config,
269 - prefix=f"{prefix}.proj")
243 + self.qkv = QKVParallelLinear(
244 + hidden_size=embed_dim,
245 + head_size=self.hidden_size_per_attention_head,
246 + total_num_heads=num_heads,
247 + total_num_kv_heads=num_heads,
248 + bias=True,
249 + quant_config=quant_config,
250 + prefix=f"{prefix}.qkv",
251 + disable_tp=use_data_parallel)
252 +
253 + self.proj = RowParallelLinear(input_size=projection_size,
254 + output_size=embed_dim,
255 + quant_config=quant_config,
256 + prefix=f"{prefix}.proj",
257 + disable_tp=use_data_parallel)
258
259 # Detect attention implementation.
260 self.attn_backend: _Backend = get_vit_attn_backend(support_fa=True)
vllm/model_executor/models/step3_vl.py
+27 -44
@@ -21,7 +21,6 @@ from vllm.distributed import get_tensor_model_parallel_world_size
21 from vllm.model_executor.layers.activation import get_act_fn
22 from vllm.model_executor.layers.linear import (ColumnParallelLinear,
23 QKVParallelLinear,
24 - ReplicatedLinear,
24 RowParallelLinear)
25 from vllm.model_executor.layers.quantization import QuantizationConfig
26 from vllm.model_executor.layers.sampler import SamplerOutput, get_sampler
@@ -667,35 +666,21 @@ class Step3VisionAttention(nn.Module):
666
667 self.q_size = self.num_heads * self.head_dim
668
670 - if use_data_parallel:
671 - self.qkv_proj = ReplicatedLinear(
672 - self.embed_dim,
673 - 3 * self.q_size,
674 - bias=True,
675 - quant_config=quant_config,
676 - prefix=prefix,
677 - )
678 - self.out_proj = ReplicatedLinear(
679 - self.total_num_heads * self.head_dim,
680 - self.embed_dim,
681 - bias=True,
682 - quant_config=quant_config,
683 - prefix=prefix,
684 - )
685 - else:
686 - self.qkv_proj = QKVParallelLinear(
687 - self.embed_dim,
688 - self.head_dim,
689 - self.total_num_heads,
690 - bias=True,
691 - quant_config=quant_config,
692 - prefix=prefix,
693 - )
694 - self.out_proj = RowParallelLinear(self.embed_dim,
695 - self.embed_dim,
696 - bias=True,
697 - quant_config=quant_config,
698 - prefix=prefix)
669 + self.qkv_proj = QKVParallelLinear(
670 + self.embed_dim,
671 + self.head_dim,
672 + self.total_num_heads,
673 + bias=True,
674 + quant_config=quant_config,
675 + prefix=f"{prefix}.qkv_proj",
676 + disable_tp=use_data_parallel,
677 + )
678 + self.out_proj = RowParallelLinear(self.embed_dim,
679 + self.embed_dim,
680 + bias=True,
681 + quant_config=quant_config,
682 + prefix=f"{prefix}.out_proj",
683 + disable_tp=use_data_parallel)
684
685 def _shape(self, tensor: torch.Tensor, seq_len: int, bsz: int):
686 return tensor.view(bsz, seq_len, self.num_heads,
@@ -740,20 +725,18 @@ class Step3VisionMLP(nn.Module):
725 super().__init__()
726 self.config = config
727 self.activation_fn = get_act_fn(config.hidden_act)
743 - cls_fc1 = (ReplicatedLinear
744 - if use_data_parallel else ColumnParallelLinear)
745 - self.fc1 = cls_fc1(config.hidden_size,
746 - config.intermediate_size,
747 - bias=True,
748 - quant_config=quant_config,
749 - prefix=prefix)
750 - cls_fc2 = (ReplicatedLinear
751 - if use_data_parallel else RowParallelLinear)
752 - self.fc2 = cls_fc2(config.intermediate_size,
753 - config.hidden_size,
754 - bias=True,
755 - quant_config=quant_config,
756 - prefix=prefix)
728 + self.fc1 = ColumnParallelLinear(config.hidden_size,
729 + config.intermediate_size,
730 + bias=True,
731 + quant_config=quant_config,
732 + prefix=f"{prefix}.fc1",
733 + disable_tp=use_data_parallel)
734 + self.fc2 = RowParallelLinear(config.intermediate_size,
735 + config.hidden_size,
736 + bias=True,
737 + quant_config=quant_config,
738 + prefix=f"{prefix}.fc2",
739 + disable_tp=use_data_parallel)
740
741 def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
742 hidden_states, _ = self.fc1(hidden_states)
vllm/model_executor/parameter.py
+11 -11
@@ -57,6 +57,8 @@ class BasevLLMParameter(Parameter):
57 weight_loader = _make_synced_weight_loader(weight_loader)
58
59 self._weight_loader = weight_loader
60 + self.tp_rank = get_tensor_model_parallel_rank()
61 + self.tp_size = get_tensor_model_parallel_world_size()
62
63 @property
64 def weight_loader(self):
@@ -116,10 +118,10 @@ class _ColumnvLLMParameter(BasevLLMParameter):
118 return self._output_dim
119
120 def load_column_parallel_weight(self, loaded_weight: torch.Tensor):
119 - tp_rank = get_tensor_model_parallel_rank()
121 shard_size = self.data.shape[self.output_dim]
122 loaded_weight = loaded_weight.narrow(self.output_dim,
122 - tp_rank * shard_size, shard_size)
123 + self.tp_rank * shard_size,
124 + shard_size)
125 assert self.data.shape == loaded_weight.shape
126 self.data.copy_(loaded_weight)
127
@@ -127,6 +129,7 @@ class _ColumnvLLMParameter(BasevLLMParameter):
129
130 shard_offset = kwargs.get("shard_offset")
131 shard_size = kwargs.get("shard_size")
132 +
133 # TODO: move these to PackedColumnParameter and PackedvLLMParameter
134 if isinstance(
135 self,
@@ -137,11 +140,11 @@ class _ColumnvLLMParameter(BasevLLMParameter):
140
141 param_data = self.data
142
140 - tp_rank = get_tensor_model_parallel_rank()
143 param_data = param_data.narrow(self.output_dim, shard_offset,
144 shard_size)
145 loaded_weight = loaded_weight.narrow(self.output_dim,
144 - tp_rank * shard_size, shard_size)
146 + self.tp_rank * shard_size,
147 + shard_size)
148 assert param_data.shape == loaded_weight.shape
149 param_data.copy_(loaded_weight)
150
@@ -161,8 +164,8 @@ class _ColumnvLLMParameter(BasevLLMParameter):
164 shard_offset=shard_offset, shard_size=shard_size)
165
166 param_data = self.data
164 - tp_rank = get_tensor_model_parallel_rank()
165 - shard_id = tp_rank if shard_id == "q" else tp_rank // num_heads
167 + shard_id = (self.tp_rank if shard_id == "q" else self.tp_rank //
168 + num_heads)
169 param_data = param_data.narrow(self.output_dim, shard_offset,
170 shard_size)
171 loaded_weight = loaded_weight.narrow(self.output_dim,
@@ -189,10 +192,10 @@ class RowvLLMParameter(BasevLLMParameter):
192 return self._input_dim
193
194 def load_row_parallel_weight(self, loaded_weight: torch.Tensor):
192 - tp_rank = get_tensor_model_parallel_rank()
195 shard_size = self.data.shape[self.input_dim]
196 loaded_weight = loaded_weight.narrow(self.input_dim,
195 - tp_rank * shard_size, shard_size)
197 + self.tp_rank * shard_size,
198 + shard_size)
199
200 if len(loaded_weight.shape) == 0:
201 loaded_weight = loaded_weight.reshape(1)
@@ -414,9 +417,6 @@ class SharedWeightParameter(BasevLLMParameter):
417 "weight_loader": self._fake_weight_loader
418 }
419
417 - self.tp_rank = get_tensor_model_parallel_rank()
418 - self.tp_size = get_tensor_model_parallel_world_size()
419 -
420 if self.tp_size > 1:
421 raise NotImplementedError(f"{self.__class__.__name__} does not "
422 "currently support tensor parallelism")