Skip to content

Commit 986497b

Browse files
committed
Fix AutoTP training lm_head routing
Signed-off-by: gaoxiaomo <165135449+gaoxiaomo@users.noreply.github.com>
1 parent 573ce48 commit 986497b

2 files changed

Lines changed: 90 additions & 5 deletions

File tree

deepspeed/module_inject/auto_tp.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,12 +394,15 @@ def _replace(self, child, name, conv_linear_layer):
394394
down_proj = False
395395
if 'down_proj' in name:
396396
down_proj = True
397-
if name in self.all_reduce_linears or arctic_w2_all_reduce_linear or down_proj:
397+
legacy_lm_head = name == "lm_head" or name == 'embed_out'
398+
training_column_lm_head = is_autotp_training_mode() and legacy_lm_head
399+
if (name in self.all_reduce_linears or arctic_w2_all_reduce_linear
400+
or down_proj) and not training_column_lm_head:
398401

399402
setattr(child, "replaced", True)
400403
if self.conv_linear_layer:
401404
return Conv_LinearALlreduce(child, self.mp_group, name=name)
402-
elif name == "lm_head" or name == 'embed_out':
405+
elif legacy_lm_head:
403406
return LmHeadLinearAllreduce(child, self.mp_group)
404407

405408
return LinearAllreduce(child, self.mp_group, name=name)
@@ -451,8 +454,7 @@ def _create_row_parallel_layer(self, module, spec: TPLayerSpec, name: str):
451454
"""Create row-parallel layer (AllReduce after forward)."""
452455
if self.conv_linear_layer:
453456
return Conv_LinearALlreduce(module, self.mp_group, name=name)
454-
# Check for lm_head / embed_out
455-
if name == "lm_head" or name == 'embed_out':
457+
if (name == "lm_head" or name == 'embed_out') and not is_autotp_training_mode():
456458
return LmHeadLinearAllreduce(module, self.mp_group)
457459

458460
if spec.shape is not None:

tests/unit/module_inject/test_tp_partition_config_path.py

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
because the name was just ``0.self_attn.q_proj``.
99
"""
1010

11+
from contextlib import contextmanager
12+
1113
import pytest
1214
import torch.nn as nn
1315

1416
from deepspeed.module_inject.auto_tp import AutoTP, AutoTPConfig, PartitionType, TPLayerSpec
15-
from deepspeed.module_inject.layers import LinearLayer
17+
from deepspeed.module_inject.layers import LinearAllreduce, LinearLayer, LmHeadLinearAllreduce, set_autotp_mode
1618
from deepspeed.module_inject.tp_plan_converter import TPPlanConverter
1719

1820

@@ -158,6 +160,49 @@ def _build_gathered_lm_head_autotp(model, mp_size=1):
158160
return autotp
159161

160162

163+
def _build_legacy_lm_head_autotp(model):
164+
autotp = AutoTP(
165+
module=model,
166+
all_reduce_linears=("lm_head", "embed_out"),
167+
prefix="",
168+
state_dict=None,
169+
linear_layer_setting=(nn.Linear, nn.Embedding),
170+
orig_layer_impl=None,
171+
)
172+
autotp.mp_size = 1
173+
autotp.mp_group = None
174+
autotp.update_linear_policies()
175+
return autotp
176+
177+
178+
def _build_row_output_head_autotp(model, head="lm_head"):
179+
config = AutoTPConfig(layer_specs=[
180+
TPLayerSpec(patterns=[rf".*{head}\.weight$"], partition_type=PartitionType.ROW),
181+
])
182+
autotp = AutoTP(
183+
module=model,
184+
all_reduce_linears=(),
185+
prefix="",
186+
state_dict=None,
187+
linear_layer_setting=(nn.Linear, nn.Embedding),
188+
orig_layer_impl=None,
189+
partition_config=config,
190+
)
191+
autotp.mp_size = 1
192+
autotp.mp_group = None
193+
autotp.update_linear_policies()
194+
return autotp
195+
196+
197+
@contextmanager
198+
def _training_mode():
199+
set_autotp_mode(training=True)
200+
try:
201+
yield
202+
finally:
203+
set_autotp_mode(training=False)
204+
205+
161206
def test_gathered_lm_head_uses_column_parallel_layer_when_untied():
162207
model = OutputModel(tied=False)
163208
_build_gathered_lm_head_autotp(model)._replace_module(model)
@@ -209,5 +254,43 @@ def test_gathered_lm_head_uses_column_parallel_layer_when_output_dim_is_uneven()
209254
assert model.lm_head.gather_output
210255

211256

257+
@pytest.mark.parametrize("head", ["lm_head", "embed_out"])
258+
def test_legacy_output_head_defaults_to_column_parallel_during_training(head):
259+
model = OutputModel(tied=False)
260+
if head == "embed_out":
261+
model.embed_out = model.lm_head
262+
del model.lm_head
263+
264+
with _training_mode():
265+
_build_legacy_lm_head_autotp(model)._replace_last_linear_module(model)
266+
267+
output_head = getattr(model, head)
268+
assert isinstance(output_head, LinearLayer)
269+
assert not output_head.gather_output
270+
271+
272+
def test_legacy_lm_head_keeps_inference_allreduce_routing():
273+
model = OutputModel(tied=False)
274+
_build_legacy_lm_head_autotp(model)._replace_last_linear_module(model)
275+
276+
assert isinstance(model.lm_head, LmHeadLinearAllreduce)
277+
278+
279+
def test_explicit_row_parallel_lm_head_is_not_overridden_by_its_name():
280+
model = OutputModel(tied=False)
281+
with _training_mode():
282+
_build_row_output_head_autotp(model)._replace_module(model)
283+
284+
assert isinstance(model.lm_head, LinearAllreduce)
285+
assert not isinstance(model.lm_head, LmHeadLinearAllreduce)
286+
287+
288+
def test_explicit_row_parallel_lm_head_keeps_inference_specialization():
289+
model = OutputModel(tied=False)
290+
_build_row_output_head_autotp(model)._replace_module(model)
291+
292+
assert isinstance(model.lm_head, LmHeadLinearAllreduce)
293+
294+
212295
if __name__ == "__main__":
213296
pytest.main([__file__, "-v"])

0 commit comments

Comments
 (0)