@@ -1640,6 +1640,87 @@ def gmm_up(x, w0, w1, w0_bias, w1_bias, gmm_fn, weight_gather):
16401640 layer_w1 = adc .checkpoint_name (layer_w1 , "moe_mlpwi_1" )
16411641 return self .apply_ffn_activation (layer_w0 , layer_w1 )
16421642
1643+ def get_gmm_for_local_experts (x , routing , route_metadata ):
1644+ """Return a partial GMM function with preconfigured routing params."""
1645+ num_ep = self .get_expert_parallelism_size ()
1646+ num_experts_per_shard = self .config .num_experts // num_ep
1647+ use_truncated_buffer = self .config .use_ring_of_experts and x .shape [0 ] < routing .sorted_selected_experts .shape [0 ]
1648+ if use_truncated_buffer :
1649+ local_group_sizes = routing .local_group_sizes
1650+ return functools .partial (
1651+ gmm ,
1652+ group_sizes = local_group_sizes ,
1653+ expert_assignments = routing .selected_experts ,
1654+ group_offset = 0 ,
1655+ )
1656+ else :
1657+ if self .config .use_ragged_sort and self .config .use_ring_of_experts :
1658+ experts_start = route_metadata .expert_shard_id * num_experts_per_shard
1659+ else :
1660+ experts_start = 0
1661+ return functools .partial (
1662+ gmm ,
1663+ group_sizes = routing .group_sizes ,
1664+ expert_assignments = routing .selected_experts ,
1665+ group_offset = experts_start ,
1666+ )
1667+
1668+ def unsort_output_with_ra2a (intermediate_output , routing , route_metadata , output_shape , is_batch_sharded_by_expert ):
1669+ """Unsort tokens and return them to original shards using ragged all-to-all."""
1670+ if is_batch_sharded_by_expert :
1671+ # locally unpermute back to the original order
1672+ if self .config .use_ragged_sort :
1673+ # Mirror the ragged-prefix gather used in `local_permute`. The
1674+ # un-permute can use the same valid-prefix length because the
1675+ # routed token count is identical for forward and backward.
1676+ valid_end = jnp .sum (routing .group_sizes ).astype (jnp .int32 )
1677+ local_output = a2a_ragged_unsort (
1678+ intermediate_output ,
1679+ jnp .argsort (route_metadata .local_sorted_indices ), # pylint: disable=undefined-variable
1680+ valid_end ,
1681+ )
1682+ else :
1683+ local_output = _sort_activations (
1684+ intermediate_output ,
1685+ jnp .argsort (route_metadata .local_sorted_indices ),
1686+ self .config .use_custom_sort_vjp ,
1687+ )
1688+
1689+ input_offsets , send_sizes , output_offsets , recv_sizes = RoutedMoE .get_all_to_all_params (
1690+ jnp .transpose (route_metadata .all_shards_group_sizes ),
1691+ route_metadata .expert_shard_id ,
1692+ self .get_expert_parallelism_size (),
1693+ )
1694+ intermediate_output = jax .lax .ragged_all_to_all (
1695+ local_output ,
1696+ output_shape ,
1697+ input_offsets ,
1698+ send_sizes ,
1699+ output_offsets ,
1700+ recv_sizes ,
1701+ axis_name = self ._expert_parallelism_name ,
1702+ )
1703+ else :
1704+ # If batch is replicated across EP shards then each shard should send
1705+ # 0..local_shard_size data to the other shards and receive the
1706+ # local_shard data from all of the other shards using ragged_all_to_all.
1707+ input_offsets , send_sizes , output_offsets , recv_sizes = RoutedMoE .get_all_to_all_params (
1708+ route_metadata .reshaped_group_sizes ,
1709+ route_metadata .expert_shard_id ,
1710+ self .get_expert_parallelism_size (),
1711+ is_batch_sharded = False ,
1712+ )
1713+ intermediate_output = jax .lax .ragged_all_to_all (
1714+ intermediate_output ,
1715+ output_shape ,
1716+ input_offsets ,
1717+ send_sizes ,
1718+ output_offsets ,
1719+ recv_sizes ,
1720+ axis_name = self ._expert_parallelism_name ,
1721+ )
1722+ return intermediate_output
1723+
16431724 @functools .partial (
16441725 jax .shard_map ,
16451726 mesh = self .mesh ,
@@ -1663,36 +1744,14 @@ def gmm_up(x, w0, w1, w0_bias, w1_bias, gmm_fn, weight_gather):
16631744 ),
16641745 check_vma = self .config .check_vma ,
16651746 )
1666- def wrapper (x , logits , pre_bias_logits , w0 , w1 , wo , w0_bias , w1_bias , wo_bias , sharded_input_ids , rngs ):
1747+ def sparse_matmul_route_and_compute (x , logits , pre_bias_logits , w0 , w1 , wo , w0_bias , w1_bias , wo_bias , sharded_input_ids , rngs ):
16671748 batch_size , sequence_length , _ = x .shape
16681749 x , routing , route_metadata = route (x , logits , pre_bias_logits , rngs , input_ids = sharded_input_ids )
16691750
16701751 if self .config .mlp_bias :
16711752 w0_bias , w1_bias , wo_bias = self .transform_bias (routing .selected_experts , w0_bias , w1_bias , wo_bias )
16721753
1673- num_ep = self .get_expert_parallelism_size ()
1674- num_experts_per_shard = self .config .num_experts // num_ep
1675-
1676- use_truncated_buffer = self .config .use_ring_of_experts and x .shape [0 ] < routing .sorted_selected_experts .shape [0 ]
1677- if use_truncated_buffer :
1678- local_group_sizes = routing .local_group_sizes
1679- gmm_fn = functools .partial (
1680- gmm ,
1681- group_sizes = local_group_sizes ,
1682- expert_assignments = routing .selected_experts ,
1683- group_offset = 0 ,
1684- )
1685- else :
1686- if self .config .use_ragged_sort and self .config .use_ring_of_experts :
1687- experts_start = route_metadata .expert_shard_id * num_experts_per_shard
1688- else :
1689- experts_start = 0
1690- gmm_fn = functools .partial (
1691- gmm ,
1692- group_sizes = routing .group_sizes ,
1693- expert_assignments = routing .selected_experts ,
1694- group_offset = experts_start ,
1695- )
1754+ gmm_fn = get_gmm_for_local_experts (x , routing , route_metadata )
16961755 intermediate_layer = gmm_up (x , w0 , w1 , w0_bias , w1_bias , gmm_fn , weight_gather )
16971756
16981757 wo_gather_axes , wo_tile_size = get_wo_gmm_params ()
@@ -1741,58 +1800,13 @@ def wrapper(x, logits, pre_bias_logits, w0, w1, wo, w0_bias, w1_bias, wo_bias, s
17411800 dtype = intermediate_output .dtype ,
17421801 )
17431802
1744- if is_batch_sharded_by_expert :
1745- # locally unpermute back to the original order
1746- if self .config .use_ragged_sort :
1747- # Mirror the ragged-prefix gather used in `local_permute`. The
1748- # un-permute can use the same valid-prefix length because the
1749- # routed token count is identical for forward and backward.
1750- valid_end = jnp .sum (routing .group_sizes ).astype (jnp .int32 )
1751- local_output = a2a_ragged_unsort (
1752- intermediate_output ,
1753- jnp .argsort (route_metadata .local_sorted_indices ), # pylint: disable=undefined-variable
1754- valid_end ,
1755- )
1756- else :
1757- local_output = _sort_activations (
1758- intermediate_output ,
1759- jnp .argsort (route_metadata .local_sorted_indices ),
1760- self .config .use_custom_sort_vjp ,
1761- )
1762-
1763- input_offsets , send_sizes , output_offsets , recv_sizes = RoutedMoE .get_all_to_all_params (
1764- jnp .transpose (route_metadata .all_shards_group_sizes ),
1765- route_metadata .expert_shard_id ,
1766- self .get_expert_parallelism_size (),
1767- )
1768- intermediate_output = jax .lax .ragged_all_to_all (
1769- local_output ,
1770- output_shape ,
1771- input_offsets ,
1772- send_sizes ,
1773- output_offsets ,
1774- recv_sizes ,
1775- axis_name = self ._expert_parallelism_name ,
1776- )
1777- else :
1778- # If batch is replicated across EP shards then each shard should send
1779- # 0..local_shard_size data to the other shards and receive the
1780- # local_shard data from all of the other shards using ragged_all_to_all.
1781- input_offsets , send_sizes , output_offsets , recv_sizes = RoutedMoE .get_all_to_all_params (
1782- route_metadata .reshaped_group_sizes ,
1783- route_metadata .expert_shard_id ,
1784- self .get_expert_parallelism_size (),
1785- is_batch_sharded = False ,
1786- )
1787- intermediate_output = jax .lax .ragged_all_to_all (
1788- intermediate_output ,
1789- output_shape ,
1790- input_offsets ,
1791- send_sizes ,
1792- output_offsets ,
1793- recv_sizes ,
1794- axis_name = self ._expert_parallelism_name ,
1795- )
1803+ intermediate_output = unsort_output_with_ra2a (
1804+ intermediate_output ,
1805+ routing ,
1806+ route_metadata ,
1807+ output_shape ,
1808+ is_batch_sharded_by_expert ,
1809+ )
17961810
17971811 output = self .unpermute (
17981812 intermediate_output ,
@@ -1851,7 +1865,7 @@ def wrapper(x, logits, pre_bias_logits, w0, w1, wo, w0_bias, w1_bias, wo_bias, s
18511865 if wo_bias is not None :
18521866 wo_bias = self ._maybe_shard_with_pspec (wo_bias , wo_bias_pspec )
18531867
1854- return wrapper (
1868+ return sparse_matmul_route_and_compute (
18551869 inputs ,
18561870 gate_logits ,
18571871 pre_bias_logits ,
0 commit comments