|
8 | 8 | because the name was just ``0.self_attn.q_proj``. |
9 | 9 | """ |
10 | 10 |
|
| 11 | +from contextlib import contextmanager |
| 12 | + |
11 | 13 | import pytest |
12 | 14 | import torch.nn as nn |
13 | 15 |
|
14 | 16 | 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 |
16 | 18 | from deepspeed.module_inject.tp_plan_converter import TPPlanConverter |
17 | 19 |
|
18 | 20 |
|
@@ -158,6 +160,49 @@ def _build_gathered_lm_head_autotp(model, mp_size=1): |
158 | 160 | return autotp |
159 | 161 |
|
160 | 162 |
|
| 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 | + |
161 | 206 | def test_gathered_lm_head_uses_column_parallel_layer_when_untied(): |
162 | 207 | model = OutputModel(tied=False) |
163 | 208 | _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() |
209 | 254 | assert model.lm_head.gather_output |
210 | 255 |
|
211 | 256 |
|
| 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 | + |
212 | 295 | if __name__ == "__main__": |
213 | 296 | pytest.main([__file__, "-v"]) |
0 commit comments