@@ -1640,6 +1640,85 @@ 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+ if self .config .use_ragged_sort and self .config .use_ring_of_experts :
1657+ experts_start = route_metadata .expert_shard_id * num_experts_per_shard
1658+ else :
1659+ experts_start = 0
1660+ return functools .partial (
1661+ gmm ,
1662+ group_sizes = routing .group_sizes ,
1663+ expert_assignments = routing .selected_experts ,
1664+ group_offset = experts_start ,
1665+ )
1666+
1667+ def unsort_output_with_ra2a (intermediate_output , routing , route_metadata , output_shape , is_batch_sharded_by_expert ):
1668+ """Unsort tokens and return them to original shards using ragged all-to-all."""
1669+ if is_batch_sharded_by_expert :
1670+ # locally unpermute back to the original order
1671+ if self .config .use_ragged_sort :
1672+ # Mirror the ragged-prefix gather used in `local_permute`. The
1673+ # un-permute can use the same valid-prefix length because the
1674+ # routed token count is identical for forward and backward.
1675+ valid_end = jnp .sum (routing .group_sizes ).astype (jnp .int32 )
1676+ local_output = a2a_ragged_unsort (
1677+ intermediate_output ,
1678+ jnp .argsort (route_metadata .local_sorted_indices ), # pylint: disable=undefined-variable
1679+ valid_end ,
1680+ )
1681+ else :
1682+ local_output = _sort_activations (
1683+ intermediate_output ,
1684+ jnp .argsort (route_metadata .local_sorted_indices ),
1685+ self .config .use_custom_sort_vjp ,
1686+ )
1687+
1688+ input_offsets , send_sizes , output_offsets , recv_sizes = RoutedMoE .get_all_to_all_params (
1689+ jnp .transpose (route_metadata .all_shards_group_sizes ),
1690+ route_metadata .expert_shard_id ,
1691+ self .get_expert_parallelism_size (),
1692+ )
1693+ return jax .lax .ragged_all_to_all (
1694+ local_output ,
1695+ output_shape ,
1696+ input_offsets ,
1697+ send_sizes ,
1698+ output_offsets ,
1699+ recv_sizes ,
1700+ axis_name = self ._expert_parallelism_name ,
1701+ )
1702+
1703+ # If batch is replicated across EP shards then each shard should send
1704+ # 0..local_shard_size data to the other shards and receive the
1705+ # local_shard data from all of the other shards using ragged_all_to_all.
1706+ input_offsets , send_sizes , output_offsets , recv_sizes = RoutedMoE .get_all_to_all_params (
1707+ route_metadata .reshaped_group_sizes ,
1708+ route_metadata .expert_shard_id ,
1709+ self .get_expert_parallelism_size (),
1710+ is_batch_sharded = False ,
1711+ )
1712+ return jax .lax .ragged_all_to_all (
1713+ intermediate_output ,
1714+ output_shape ,
1715+ input_offsets ,
1716+ send_sizes ,
1717+ output_offsets ,
1718+ recv_sizes ,
1719+ axis_name = self ._expert_parallelism_name ,
1720+ )
1721+
16431722 @functools .partial (
16441723 jax .shard_map ,
16451724 mesh = self .mesh ,
@@ -1663,36 +1742,16 @@ def gmm_up(x, w0, w1, w0_bias, w1_bias, gmm_fn, weight_gather):
16631742 ),
16641743 check_vma = self .config .check_vma ,
16651744 )
1666- def wrapper (x , logits , pre_bias_logits , w0 , w1 , wo , w0_bias , w1_bias , wo_bias , sharded_input_ids , rngs ):
1745+ def sparse_matmul_route_and_compute (
1746+ x , logits , pre_bias_logits , w0 , w1 , wo , w0_bias , w1_bias , wo_bias , sharded_input_ids , rngs
1747+ ):
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 ()
@@ -1727,83 +1786,38 @@ def wrapper(x, logits, pre_bias_logits, w0, w1, wo, w0_bias, w1_bias, wo_bias, s
17271786 output , (- 1 , sequence_length , self .moe_expert_input_dim // self .get_tensor_parallelism_size ())
17281787 )
17291788 output = jax .lax .psum_scatter (output , self ._expert_parallelism_name , scatter_dimension = 0 , tiled = True )
1789+ return output , routing .lb_loss , routing .bias_updates
1790+
1791+ if self .get_expert_parallelism_size () > 1 :
1792+ original_inputs_first_dim = batch_size * sequence_length * self .config .num_experts_per_tok
1793+ if routing .sorted_selected_experts .shape [0 ] != original_inputs_first_dim :
1794+ raise ValueError ("original_inputs_first_dim does not match the original tensor" " shape!" )
1795+ output_shape = jax .lax .empty (
1796+ (
1797+ original_inputs_first_dim ,
1798+ self .moe_expert_input_dim // self .get_tensor_parallelism_size (),
1799+ ),
1800+ dtype = intermediate_output .dtype ,
1801+ )
17301802
1731- else :
1732- if self .get_expert_parallelism_size () > 1 :
1733- original_inputs_first_dim = batch_size * sequence_length * self .config .num_experts_per_tok
1734- if routing .sorted_selected_experts .shape [0 ] != original_inputs_first_dim :
1735- raise ValueError ("original_inputs_first_dim does not match the original tensor" " shape!" )
1736- output_shape = jax .lax .empty (
1737- (
1738- original_inputs_first_dim ,
1739- self .moe_expert_input_dim // self .get_tensor_parallelism_size (),
1740- ),
1741- dtype = intermediate_output .dtype ,
1742- )
1743-
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- )
1796-
1797- output = self .unpermute (
1803+ intermediate_output = unsort_output_with_ra2a (
17981804 intermediate_output ,
1799- routing .sorted_selected_experts ,
1800- routing .weights ,
1801- batch_size = batch_size ,
1802- sequence_length = sequence_length ,
1803- use_custom_sort_vjp = self .config .use_custom_sort_vjp ,
1804- group_sizes = routing .group_sizes ,
1805+ routing ,
1806+ route_metadata ,
1807+ output_shape ,
1808+ is_batch_sharded_by_expert ,
18051809 )
18061810
1811+ output = self .unpermute (
1812+ intermediate_output ,
1813+ routing .sorted_selected_experts ,
1814+ routing .weights ,
1815+ batch_size = batch_size ,
1816+ sequence_length = sequence_length ,
1817+ use_custom_sort_vjp = self .config .use_custom_sort_vjp ,
1818+ group_sizes = routing .group_sizes ,
1819+ )
1820+
18071821 return output , routing .lb_loss , routing .bias_updates
18081822
18091823 if self .config .moe_fsdp_use_two_stage_all_gather :
@@ -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