MoE: remove the replicated-activation repeat in RoutedMoE.permute - #4913
MoE: remove the replicated-activation repeat in RoutedMoE.permute#4913systalyze-ai wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces '_gather_replicated_activations' along with a custom VJP implementation to optimize the gathering of sorted rows without materializing repeated inputs in the MoE layer, and adds corresponding unit tests. Feedback is provided to optimize the backward pass of the custom VJP by replacing the inefficient 'jnp.argsort' with a scatter-based permutation inversion to improve TPU performance.
| sort_indices = residuals | ||
| unsorted_grads = grads[jnp.argsort(sort_indices), ...] |
There was a problem hiding this comment.
Using jnp.argsort to invert a permutation on TPU is highly inefficient because it compiles to an
Since sort_indices is guaranteed to be a permutation of 0..N-1, we can invert it in jnp.empty_like(sort_indices).at[sort_indices].set(jnp.arange(sort_indices.shape[0])). This compiles to a highly optimized scatter/transpose-like operation on TPU, significantly speeding up the backward pass.
Note: The same optimization can be applied to _sort_activations_custom_bwd and unpermute in a separate PR to further improve performance.
| sort_indices = residuals | |
| unsorted_grads = grads[jnp.argsort(sort_indices), ...] | |
| sort_indices = residuals | |
| inverse_indices = jnp.empty_like(sort_indices).at[sort_indices].set(jnp.arange(sort_indices.shape[0])) | |
| unsorted_grads = grads[inverse_indices, ...] |
Gather directly from the original activations with divided indices instead of materializing top_k copies before the sorted gather. Forward, VJP, and JVP outputs are unchanged. Co-authored-by: Sudarsanan <[email protected]> Co-authored-by: Armin <[email protected]> Co-authored-by: utlz <[email protected]>
fccd4f4 to
123b8ef
Compare
Description
Changes the non-ragged
RoutedMoE.permutepath to gather directly from the original activations instead of materializingtop_kcopies before the sorted gather. This removes an activation buffer that is 6x the dispatch input for DeepSeek-V4-284B.Performance
Step time changed by ~1% on v6e-128 with DeepSeek-V4-Flash 284B LoRA fine-tuning at seq 16384; the benefit of the change is the removed activation buffer. Setup:
ici_expert_parallelism=16,ici_tensor_parallelism=8,ici_fsdp_parallelism=1,max_target_length=16384,per_device_batch_size=0.125(global batch 16),LIBTPU_INIT_ARGS=--xla_tpu_scoped_vmem_limit_kib=98304, dynamic-splash attention path enabled.Tests
JAX_PLATFORMS=cpu pytest -q tests/unit/moe_test.py -k GatherReplicatedActivationsTest: 2 passed.Checklist
Before submitting this PR, please make sure (put X in square brackets):
gemini-reviewlabel.