Skip to content

Commit 2ab4f47

Browse files
committed
handle uneven gathered lm_head shards
Signed-off-by: iLeGend <824040212@qq.com>
1 parent ab457b5 commit 2ab4f47

2 files changed

Lines changed: 27 additions & 3 deletions

File tree

deepspeed/module_inject/auto_tp.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,21 @@ def _create_row_parallel_layer(self, module, spec: TPLayerSpec, name: str):
475475

476476
def _create_column_parallel_layer(self, module, spec: TPLayerSpec, name: str):
477477
"""Create column-parallel layer (AllReduce in backward)."""
478+
if spec.gather_output and self.mp_size is not None and self.mp_size > 1:
479+
output_dim = module.weight.shape[0]
480+
if output_dim % self.mp_size != 0:
481+
if any(part in ("lm_head", "embed_out") for part in name.split('.')):
482+
print_dist(
483+
f"AutoTP: '{name}' uses gather_output with uneven output dim {output_dim} and tp_size="
484+
f"{self.mp_size}; falling back to legacy LmHeadLinearAllreduce for checkpoint-safe "
485+
"consolidation.",
486+
ranks=[0],
487+
)
488+
return LmHeadLinearAllreduce(module, self.mp_group)
489+
raise NotImplementedError(
490+
f"AutoTP gather_output requires output dimension divisible by tp_size. Layer '{name}' has "
491+
f"output dim {output_dim} with tp_size={self.mp_size}.")
492+
478493
if self.conv_linear_layer:
479494
return conv_LinearLayer(module, self.mp_group, name=name, gather_output=spec.gather_output)
480495
# Only use fused-QKV heuristics when no partition_config is provided.

tests/unit/module_inject/test_tp_partition_config_path.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import torch.nn as nn
1313

1414
from deepspeed.module_inject.auto_tp import AutoTP, AutoTPConfig, PartitionType, TPLayerSpec
15-
from deepspeed.module_inject.layers import LinearLayer
15+
from deepspeed.module_inject.layers import LinearLayer, LmHeadLinearAllreduce
1616

1717

1818
class SubAttn(nn.Module):
@@ -135,7 +135,7 @@ def test_nested_depth_correct():
135135
assert f"layers.{layer_idx}.self_attn.o_proj" in matched_names
136136

137137

138-
def _build_gathered_lm_head_autotp(model):
138+
def _build_gathered_lm_head_autotp(model, mp_size=1):
139139
config = AutoTPConfig(layer_specs=[
140140
TPLayerSpec(
141141
patterns=[r".*lm_head\.weight$"],
@@ -152,7 +152,7 @@ def _build_gathered_lm_head_autotp(model):
152152
orig_layer_impl=None,
153153
partition_config=config,
154154
)
155-
autotp.set_tensor_parallel_config(1, None)
155+
autotp.set_tensor_parallel_config(mp_size, None)
156156
autotp.update_linear_policies()
157157
return autotp
158158

@@ -176,5 +176,14 @@ def test_gathered_lm_head_falls_back_for_runtime_parameter_tie():
176176
assert model.lm_head.weight is model.embed_tokens.weight
177177

178178

179+
def test_gathered_lm_head_falls_back_to_legacy_allreduce_when_output_dim_is_uneven():
180+
model = OutputModel(tied=False)
181+
model.lm_head = nn.Linear(32, 101, bias=False)
182+
183+
_build_gathered_lm_head_autotp(model, mp_size=2)._replace_module(model)
184+
185+
assert isinstance(model.lm_head, LmHeadLinearAllreduce)
186+
187+
179188
if __name__ == "__main__":
180189
pytest.main([__file__, "-v"])

0 commit comments

Comments
 (0)