@@ -34,6 +34,7 @@ def parallel_state(monkeypatch):
3434 monkeypatch .setattr (mpu , "get_tensor_model_parallel_world_size" , lambda : 1 , raising = False )
3535 monkeypatch .setattr (mpu , "get_context_parallel_world_size" , lambda : 1 , raising = False )
3636 monkeypatch .setattr (mpu , "get_context_parallel_rank" , lambda : 0 , raising = False )
37+ monkeypatch .setattr (mpu , "get_expert_model_parallel_world_size" , lambda : 1 , raising = False )
3738 return mpu
3839
3940
@@ -93,7 +94,7 @@ def test_replay_has_no_dispatcher_specific_patch():
9394
9495
9596@pytest .mark .parametrize ("route_dtype" , [torch .uint8 , torch .int16 , torch .int32 ])
96- def test_setup_replay_installs_indices_and_returns_model_mask (monkeypatch , parallel_state , route_dtype ):
97+ def test_setup_replay_installs_indices_in_model_order_and_returns_mask (monkeypatch , parallel_state , route_dtype ):
9798 router_replay_module = types .ModuleType ("megatron.core.transformer.moe.router_replay" )
9899
99100 class RouterReplay :
@@ -131,19 +132,14 @@ def record_routed_layer_count(metadata, layout, padding_value):
131132
132133 monkeypatch .setattr (replay_utils , "align_token_metadata" , record_routed_layer_count )
133134
134- routes = torch .tensor (
135- [
136- [
137- [[0 , 1 ], [0 , 1 ], [0 , 1 ]],
138- [[10 , 11 ], [1 , 2 ], [20 , 21 ]],
139- [[12 , 13 ], [3 , 4 ], [22 , 23 ]],
140- [[14 , 15 ], [5 , 6 ], [24 , 25 ]],
141- ]
142- ],
143- dtype = route_dtype ,
135+ monkeypatch .setattr (parallel_state , "get_expert_model_parallel_world_size" , lambda : 8 )
136+
137+ routes = torch .arange (240 , dtype = torch .int32 ).reshape (2 , 5 , 3 , 8 ).to (route_dtype )
138+ attention_mask = torch .ones ((2 , 5 ), dtype = torch .long )
139+ router_padding_mask = torch .tensor (
140+ [[False , True , False , True , False ], [True , False , True , False , True ]],
141+ dtype = torch .bool ,
144142 )
145- attention_mask = torch .tensor ([[0 , 1 , 1 , 1 ]])
146- router_padding_mask = torch .tensor ([[1 , 0 , 0 , 1 ]], dtype = torch .bool )
147143 metadata_layout = build_token_metadata_layout (
148144 attention_mask ,
149145 routes .device ,
@@ -156,16 +152,45 @@ def record_routed_layer_count(metadata, layout, padding_value):
156152 router_padding_mask ,
157153 attention_mask ,
158154 model = object (),
159- model_config = SimpleNamespace (fp8 = None ),
155+ model_config = SimpleNamespace (fp8 = None , num_moe_experts = 384 ),
160156 metadata_layout = metadata_layout ,
161157 )
162158
163- assert RouterReplay .replay_data [0 ].tolist () == [[1 , 2 ], [3 , 4 ], [5 , 6 ]]
159+ installed = RouterReplay .replay_data [0 ]
160+ flat_padding_mask = router_padding_mask .transpose (0 , 1 ).flatten ()
161+ expected_captured = torch .tensor (
162+ [
163+ list (range (8 , 16 )),
164+ list (range (152 , 160 )),
165+ list (range (56 , 64 )),
166+ list (range (200 , 208 )),
167+ list (range (104 , 112 )),
168+ ],
169+ dtype = torch .int32 ,
170+ )
171+ assert torch .equal (installed [~ flat_padding_mask ], expected_captured )
172+ padding_routes = installed [flat_padding_mask ]
173+ assignment_ordinals = torch .arange (40 ).reshape (5 , 8 )
174+ expected_padding_routes = (assignment_ordinals % 8 ) * 48 + assignment_ordinals // 8
175+ assert torch .equal (padding_routes , expected_padding_routes )
176+ assert padding_routes [0 ].tolist () == [0 , 48 , 96 , 144 , 192 , 240 , 288 , 336 ]
177+ assert torch .all ((padding_routes >= 0 ) & (padding_routes < 384 ))
178+ assert torch .all (padding_routes .sort (dim = 1 ).values .diff (dim = 1 ) > 0 )
179+ for num_padding_rows in range (1 , 6 ):
180+ expert_loads = torch .bincount (padding_routes [:num_padding_rows ].flatten (), minlength = 384 )
181+ assert expert_loads .max () - expert_loads .min () <= 1
182+ assert torch .equal (
183+ expert_loads .reshape (8 , 48 ).sum (dim = 1 ),
184+ torch .full ((8 ,), num_padding_rows , dtype = torch .long ),
185+ )
164186 assert RouterReplay .replay_data [0 ].dtype == torch .int32
165187 assert RouterReplay .action == RouterReplayAction .REPLAY_FORWARD
166- assert model_kwargs ["padding_mask" ]. tolist () == [[ False , False , True ]]
188+ assert torch . equal ( model_kwargs ["padding_mask" ], router_padding_mask )
167189 assert routed_layer_counts == [1 ]
168190
191+ packed_routes = torch .arange (10 , dtype = torch .uint8 ).reshape (1 , 5 , 1 , 2 )
192+ assert torch .equal (replay_utils ._split_replay_indices (packed_routes )[0 ], packed_routes [0 , :, 0 ].to (torch .int32 ))
193+
169194
170195@pytest .mark .parametrize ("packed" , [False , True ])
171196@pytest .mark .parametrize ("tp_size" , [1 , 2 ])
@@ -219,7 +244,7 @@ def run(routes):
219244 router_padding_mask ,
220245 attention_mask ,
221246 model = object (),
222- model_config = SimpleNamespace (fp8 = None , sequence_parallel = False ),
247+ model_config = SimpleNamespace (fp8 = None , sequence_parallel = False , num_moe_experts = 4096 ),
223248 metadata_layout = layout ,
224249 remove_microbatch_padding = packed ,
225250 )
0 commit comments