2929from maxtext .layers import nnx_wrappers
3030from maxtext .layers .initializers import NdInitializer , nd_dense_init , variable_to_logically_partitioned
3131from maxtext .layers .quantizations import Fp8Quantization
32- from maxtext .utils import maxtext_utils
32+ from maxtext .utils import max_logging , maxtext_utils
3333from maxtext .utils .sharding import remove_expert_from_partition_spec
3434from tests .utils .test_helpers import get_test_config_path
3535import 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+
3857class 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
162181class 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
286305class 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