Skip to content

Commit a64409b

Browse files
Merge pull request #4518 from AI-Hypercomputer:fix/routed-moe-test
PiperOrigin-RevId: 950968672
2 parents 40a45d2 + b390dc6 commit a64409b

1 file changed

Lines changed: 48 additions & 16 deletions

File tree

tests/unit/moe_test.py

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,31 @@
2929
from maxtext.layers import nnx_wrappers
3030
from maxtext.layers.initializers import NdInitializer, nd_dense_init, variable_to_logically_partitioned
3131
from maxtext.layers.quantizations import Fp8Quantization
32-
from maxtext.utils import maxtext_utils
32+
from maxtext.utils import max_logging, maxtext_utils
3333
from maxtext.utils.sharding import remove_expert_from_partition_spec
3434
from tests.utils.test_helpers import get_test_config_path
3535
import pytest
3636

3737

38+
def assert_moe_close(actual, expected, dtype):
39+
"""Asserts that the actual and expected MoE outputs are close."""
40+
assert np.isfinite(actual).all(), "Actual output contains NaNs or Infs!"
41+
if dtype == jnp.bfloat16:
42+
rtol, atol = 2e-2, 1e-2
43+
else:
44+
rtol, atol = 1e-5, 1e-6
45+
46+
max_diff = float(np.max(np.abs(actual - expected)))
47+
rms_expected = float(np.sqrt(np.mean(np.square(expected))))
48+
max_logging.debug(
49+
f"\n[assert_moe_close] dtype={dtype}, max_diff={max_diff:.6f}, max_diff/RMS={max_diff/rms_expected:.6f}"
50+
)
51+
52+
np.testing.assert_allclose(
53+
np.array(actual, dtype=np.float32), np.array(expected, dtype=np.float32), rtol=rtol, atol=atol, equal_nan=False
54+
)
55+
56+
3857
class TokenDroppingTest(unittest.TestCase):
3958

4059
def setUp(self):
@@ -156,7 +175,7 @@ def test_generate_masks(self):
156175
actual_dispatch_mask, actual_combine_mask = self.model.generate_masks(top_k_indices, softmax_probs)
157176

158177
self.assertTrue((expected_dispatch_mask == actual_dispatch_mask).all())
159-
self.assertTrue(jax.numpy.allclose(expected_combine_mask, actual_combine_mask, rtol=1e-02, atol=1e-02))
178+
assert_moe_close(actual_combine_mask, expected_combine_mask, self.cfg.dtype)
160179

161180

162181
class MlpBlockTest(unittest.TestCase):
@@ -280,7 +299,7 @@ def test_deepseek_bias_updates(self):
280299
expected_updates = jnp.array([-0.01, 0.0, 0.01, 0.0])
281300
actual_updates = moe.calculate_load_balance_updates(top_k_indices, num_experts, rate)
282301

283-
self.assertTrue(jax.numpy.allclose(expected_updates, actual_updates, rtol=1e-05, atol=1e-05, equal_nan=False))
302+
assert_moe_close(actual_updates, expected_updates, jnp.float32)
284303

285304

286305
class MoeLoopBlock(nnx.Module):
@@ -394,7 +413,7 @@ def get_expected_output(self, rng, hidden_states, cfg, mesh):
394413
num_experts_per_tok=cfg.num_experts_per_tok,
395414
kernel_init=nd_dense_init(1.0, "fan_in", "truncated_normal"),
396415
kernel_axes=("embed", "mlp"),
397-
dtype=cfg.dtype,
416+
dtype=jnp.float32,
398417
weight_dtype=cfg.weight_dtype,
399418
)
400419
variables = model.init(
@@ -404,8 +423,8 @@ def get_expected_output(self, rng, hidden_states, cfg, mesh):
404423
),
405424
)
406425

407-
output = jax.jit(model.apply)(variables, hidden_states) # pylint: disable=not-callable
408-
return variables, output
426+
output = jax.jit(model.apply)(variables, hidden_states.astype(jnp.float32)) # pylint: disable=not-callable
427+
return variables, output.astype(cfg.dtype)
409428

410429
def get_moe_output(self, variables, hidden_states, cfg, mesh):
411430
"""retrieve expected output from MoE"""
@@ -462,6 +481,7 @@ def test_megablox(self):
462481
sparse_matmul=True,
463482
per_device_batch_size=1,
464483
max_target_length=128,
484+
float32_gate_logits=True,
465485
)
466486

467487
rng = jax.random.PRNGKey(1234)
@@ -477,7 +497,7 @@ def test_megablox(self):
477497
mesh = Mesh(devices_array, cfg.mesh_axes)
478498
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
479499
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
480-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
500+
assert_moe_close(actual_output, expected_output, cfg.dtype)
481501

482502
@pytest.mark.tpu_only
483503
def test_ragged_dot(self):
@@ -491,6 +511,7 @@ def test_ragged_dot(self):
491511
sparse_matmul=True,
492512
per_device_batch_size=1,
493513
max_target_length=128,
514+
float32_gate_logits=True,
494515
)
495516

496517
rng = jax.random.PRNGKey(1234)
@@ -506,7 +527,7 @@ def test_ragged_dot(self):
506527
mesh = Mesh(devices_array, cfg.mesh_axes)
507528
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
508529
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
509-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
530+
assert_moe_close(actual_output, expected_output, cfg.dtype)
510531

511532
@pytest.mark.tpu_only
512533
def test_dense(self):
@@ -520,6 +541,7 @@ def test_dense(self):
520541
sparse_matmul=False,
521542
per_device_batch_size=1,
522543
max_target_length=128,
544+
float32_gate_logits=True,
523545
)
524546

525547
rng = jax.random.PRNGKey(2345)
@@ -535,7 +557,7 @@ def test_dense(self):
535557
mesh = Mesh(devices_array, cfg.mesh_axes)
536558
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
537559
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
538-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
560+
assert_moe_close(actual_output, expected_output, cfg.dtype)
539561

540562
@pytest.mark.tpu_only
541563
def test_moe_emb_chunking_random_routing(self):
@@ -556,6 +578,7 @@ def test_moe_emb_chunking_random_routing(self):
556578
mlp_bias=True,
557579
per_device_batch_size=1,
558580
max_target_length=128,
581+
float32_gate_logits=True,
559582
)
560583

561584
cfg_non_chunked = pyconfig.initialize(
@@ -575,6 +598,7 @@ def test_moe_emb_chunking_random_routing(self):
575598
mlp_bias=True,
576599
per_device_batch_size=1,
577600
max_target_length=128,
601+
float32_gate_logits=True,
578602
)
579603

580604
rng = jax.random.PRNGKey(1234)
@@ -639,6 +663,7 @@ def test_moe_emb_chunking_gmm_v2(self):
639663
mlp_bias=True,
640664
per_device_batch_size=1,
641665
max_target_length=128,
666+
float32_gate_logits=True,
642667
)
643668

644669
rng = jax.random.PRNGKey(1234)
@@ -654,7 +679,7 @@ def test_moe_emb_chunking_gmm_v2(self):
654679
mesh = Mesh(devices_array, cfg.mesh_axes)
655680
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
656681
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
657-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
682+
assert_moe_close(actual_output, expected_output, cfg.dtype)
658683

659684
@pytest.mark.tpu_only
660685
def test_megablox_expert_parallelism(self):
@@ -669,6 +694,7 @@ def test_megablox_expert_parallelism(self):
669694
per_device_batch_size=4, # TODO(b/450900273): sharding error if pdbs=1
670695
ici_expert_parallelism=4,
671696
max_target_length=128,
697+
float32_gate_logits=True,
672698
)
673699

674700
rng = jax.random.PRNGKey(2345)
@@ -685,7 +711,7 @@ def test_megablox_expert_parallelism(self):
685711
with nn_partitioning.axis_rules(cfg.logical_axis_rules):
686712
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
687713
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
688-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
714+
assert_moe_close(actual_output, expected_output, cfg.dtype)
689715

690716
@pytest.mark.tpu_only
691717
def test_ring_of_expert_and_tensor_parallelism(self):
@@ -702,6 +728,7 @@ def test_ring_of_expert_and_tensor_parallelism(self):
702728
use_ring_of_experts=True,
703729
ici_tensor_parallelism=2,
704730
max_target_length=128,
731+
float32_gate_logits=True,
705732
)
706733

707734
rng = jax.random.PRNGKey(2345)
@@ -718,7 +745,7 @@ def test_ring_of_expert_and_tensor_parallelism(self):
718745
with nn_partitioning.axis_rules(cfg.logical_axis_rules):
719746
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
720747
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
721-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
748+
assert_moe_close(actual_output, expected_output, cfg.dtype)
722749

723750
def _run_ragged_sort_loss_and_grad(
724751
self,
@@ -754,6 +781,7 @@ def _build_cfg(use_ragged_sort: bool):
754781
ici_expert_parallelism=2,
755782
use_ring_of_experts=use_ring_of_experts,
756783
max_target_length=128,
784+
float32_gate_logits=True,
757785
use_ragged_sort=use_ragged_sort,
758786
ragged_buffer_factor=effective_buffer_factor,
759787
ragged_gather_fallback=ragged_gather_fallback,
@@ -890,6 +918,7 @@ def test_moe_fsdp_two_stage_parallelism_tpu_only(self):
890918
ici_fsdp_transpose_parallelism=2,
891919
moe_fsdp_use_two_stage_all_gather=True,
892920
max_target_length=128,
921+
float32_gate_logits=True,
893922
)
894923

895924
rng = jax.random.PRNGKey(2345)
@@ -906,7 +935,7 @@ def test_moe_fsdp_two_stage_parallelism_tpu_only(self):
906935
with nn_partitioning.axis_rules(cfg.logical_axis_rules):
907936
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
908937
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
909-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
938+
assert_moe_close(actual_output, expected_output, cfg.dtype)
910939

911940
@pytest.mark.tpu_only
912941
def test_megablox_context_parallelism(self):
@@ -921,6 +950,7 @@ def test_megablox_context_parallelism(self):
921950
per_device_batch_size=1,
922951
ici_context_parallelism=4,
923952
max_target_length=128,
953+
float32_gate_logits=True,
924954
)
925955

926956
rng = jax.random.PRNGKey(2345)
@@ -937,7 +967,7 @@ def test_megablox_context_parallelism(self):
937967
with nn_partitioning.axis_rules(cfg.logical_axis_rules):
938968
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
939969
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
940-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
970+
assert_moe_close(actual_output, expected_output, cfg.dtype)
941971

942972
@pytest.mark.tpu_only
943973
def test_megablox_expert_context_parallelism(self):
@@ -954,6 +984,7 @@ def test_megablox_expert_context_parallelism(self):
954984
ici_expert_parallelism=2,
955985
packing=False,
956986
max_target_length=128,
987+
float32_gate_logits=True,
957988
)
958989

959990
rng = jax.random.PRNGKey(2345)
@@ -970,7 +1001,7 @@ def test_megablox_expert_context_parallelism(self):
9701001
with nn_partitioning.axis_rules(cfg.logical_axis_rules):
9711002
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
9721003
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
973-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
1004+
assert_moe_close(actual_output, expected_output, cfg.dtype)
9741005

9751006
@pytest.mark.tpu_only
9761007
def test_megablox_expert_tensor_parallelism(self):
@@ -986,6 +1017,7 @@ def test_megablox_expert_tensor_parallelism(self):
9861017
ici_tensor_parallelism=2,
9871018
ici_expert_parallelism=2,
9881019
max_target_length=128,
1020+
float32_gate_logits=True,
9891021
)
9901022

9911023
rng = jax.random.PRNGKey(2345)
@@ -1002,7 +1034,7 @@ def test_megablox_expert_tensor_parallelism(self):
10021034
with nn_partitioning.axis_rules(cfg.logical_axis_rules):
10031035
variables, expected_output = self.get_expected_output(rng_model, hidden_states, cfg, mesh)
10041036
actual_output, _, _ = self.get_moe_output(variables, hidden_states, cfg, mesh)
1005-
self.assertTrue(jax.numpy.allclose(expected_output, actual_output, rtol=1e-02, atol=1e-02, equal_nan=False))
1037+
assert_moe_close(actual_output, expected_output, cfg.dtype)
10061038

10071039
def test_random_routing(self):
10081040
bs, seq_len, num_experts, num_experts_per_tok = 12, 1024, 8, 2

0 commit comments

Comments
 (0)