Skip to content

Commit 48ac2bf

Browse files
Merge pull request #4170 from AI-Hypercomputer:refactor
PiperOrigin-RevId: 936313321
2 parents dd9c267 + e8127d9 commit 48ac2bf

1 file changed

Lines changed: 111 additions & 98 deletions

File tree

src/maxtext/layers/moe.py

Lines changed: 111 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,84 @@ def gmm_up(x, w0, w1, w0_bias, w1_bias, gmm_fn, weight_gather):
16601660
layer_w1 = adc.checkpoint_name(layer_w1, "moe_mlpwi_1")
16611661
return self.apply_ffn_activation(layer_w0, layer_w1)
16621662

1663+
def get_gmm_for_local_experts(x, routing, route_metadata):
1664+
"""Return a partial GMM function with preconfigured routing params."""
1665+
num_ep = self.get_expert_parallelism_size()
1666+
num_experts_per_shard = self.config.num_experts // num_ep
1667+
if self.config.use_ring_of_experts and x.shape[0] < routing.sorted_selected_experts.shape[0]:
1668+
local_group_sizes = routing.local_group_sizes
1669+
return functools.partial(
1670+
gmm,
1671+
group_sizes=local_group_sizes,
1672+
expert_assignments=routing.selected_experts,
1673+
group_offset=0,
1674+
)
1675+
if self.config.use_ragged_sort and self.config.use_ring_of_experts:
1676+
experts_start = route_metadata.expert_shard_id * num_experts_per_shard
1677+
else:
1678+
experts_start = 0
1679+
return functools.partial(
1680+
gmm,
1681+
group_sizes=routing.group_sizes,
1682+
expert_assignments=routing.selected_experts,
1683+
group_offset=experts_start,
1684+
)
1685+
1686+
def unsort_output_and_ra2a(intermediate_output, routing, route_metadata, output_shape, is_batch_sharded_by_expert):
1687+
"""Unsort tokens and return them to original shards using ragged all-to-all."""
1688+
if is_batch_sharded_by_expert:
1689+
# locally unpermute back to the original order
1690+
if self.config.use_ragged_sort:
1691+
# Mirror the ragged-prefix gather used in `local_permute`. The
1692+
# un-permute can use the same valid-prefix length because the
1693+
# routed token count is identical for forward and backward.
1694+
valid_end = jnp.sum(routing.group_sizes).astype(jnp.int32)
1695+
local_output = a2a_ragged_unsort(
1696+
intermediate_output,
1697+
jnp.argsort(route_metadata.local_sorted_indices), # pylint: disable=undefined-variable
1698+
valid_end,
1699+
)
1700+
else:
1701+
local_output = _sort_activations(
1702+
intermediate_output,
1703+
jnp.argsort(route_metadata.local_sorted_indices),
1704+
self.config.use_custom_sort_vjp,
1705+
)
1706+
1707+
input_offsets, send_sizes, output_offsets, recv_sizes = RoutedMoE.get_all_to_all_params(
1708+
jnp.transpose(route_metadata.all_shards_group_sizes),
1709+
route_metadata.expert_shard_id,
1710+
self.get_expert_parallelism_size(),
1711+
)
1712+
return jax.lax.ragged_all_to_all(
1713+
local_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+
1722+
# If batch is replicated across EP shards then each shard should send
1723+
# 0..local_shard_size data to the other shards and receive the
1724+
# local_shard data from all of the other shards using ragged_all_to_all.
1725+
input_offsets, send_sizes, output_offsets, recv_sizes = RoutedMoE.get_all_to_all_params(
1726+
route_metadata.reshaped_group_sizes,
1727+
route_metadata.expert_shard_id,
1728+
self.get_expert_parallelism_size(),
1729+
is_batch_sharded=False,
1730+
)
1731+
return jax.lax.ragged_all_to_all(
1732+
intermediate_output,
1733+
output_shape,
1734+
input_offsets,
1735+
send_sizes,
1736+
output_offsets,
1737+
recv_sizes,
1738+
axis_name=self._expert_parallelism_name,
1739+
)
1740+
16631741
@functools.partial(
16641742
jax.shard_map,
16651743
mesh=self.mesh,
@@ -1683,36 +1761,16 @@ def gmm_up(x, w0, w1, w0_bias, w1_bias, gmm_fn, weight_gather):
16831761
),
16841762
check_vma=self.config.check_vma,
16851763
)
1686-
def wrapper(x, logits, pre_bias_logits, w0, w1, wo, w0_bias, w1_bias, wo_bias, sharded_input_ids, rngs):
1764+
def sparse_matmul_route_and_compute(
1765+
x, logits, pre_bias_logits, w0, w1, wo, w0_bias, w1_bias, wo_bias, sharded_input_ids, rngs
1766+
):
16871767
batch_size, sequence_length, _ = x.shape
16881768
x, routing, route_metadata = route(x, logits, pre_bias_logits, rngs, input_ids=sharded_input_ids)
16891769

16901770
if self.config.mlp_bias:
16911771
w0_bias, w1_bias, wo_bias = self.transform_bias(routing.selected_experts, w0_bias, w1_bias, wo_bias)
16921772

1693-
num_ep = self.get_expert_parallelism_size()
1694-
num_experts_per_shard = self.config.num_experts // num_ep
1695-
1696-
use_truncated_buffer = self.config.use_ring_of_experts and x.shape[0] < routing.sorted_selected_experts.shape[0]
1697-
if use_truncated_buffer:
1698-
local_group_sizes = routing.local_group_sizes
1699-
gmm_fn = functools.partial(
1700-
gmm,
1701-
group_sizes=local_group_sizes,
1702-
expert_assignments=routing.selected_experts,
1703-
group_offset=0,
1704-
)
1705-
else:
1706-
if self.config.use_ragged_sort and self.config.use_ring_of_experts:
1707-
experts_start = route_metadata.expert_shard_id * num_experts_per_shard
1708-
else:
1709-
experts_start = 0
1710-
gmm_fn = functools.partial(
1711-
gmm,
1712-
group_sizes=routing.group_sizes,
1713-
expert_assignments=routing.selected_experts,
1714-
group_offset=experts_start,
1715-
)
1773+
gmm_fn = get_gmm_for_local_experts(x, routing, route_metadata)
17161774
intermediate_layer = gmm_up(x, w0, w1, w0_bias, w1_bias, gmm_fn, weight_gather)
17171775

17181776
wo_gather_axes, wo_tile_size = get_wo_gmm_params()
@@ -1747,83 +1805,38 @@ def wrapper(x, logits, pre_bias_logits, w0, w1, wo, w0_bias, w1_bias, wo_bias, s
17471805
output, (-1, sequence_length, self.moe_expert_input_dim // self.get_tensor_parallelism_size())
17481806
)
17491807
output = jax.lax.psum_scatter(output, self._expert_parallelism_name, scatter_dimension=0, tiled=True)
1808+
return output, routing.lb_loss, routing.bias_updates
1809+
1810+
if self.get_expert_parallelism_size() > 1:
1811+
original_inputs_first_dim = batch_size * sequence_length * self.config.num_experts_per_tok
1812+
if routing.sorted_selected_experts.shape[0] != original_inputs_first_dim:
1813+
raise ValueError("original_inputs_first_dim does not match the original tensor" " shape!")
1814+
output_shape = jax.lax.empty(
1815+
(
1816+
original_inputs_first_dim,
1817+
self.moe_expert_input_dim // self.get_tensor_parallelism_size(),
1818+
),
1819+
dtype=intermediate_output.dtype,
1820+
)
17501821

1751-
else:
1752-
if self.get_expert_parallelism_size() > 1:
1753-
original_inputs_first_dim = batch_size * sequence_length * self.config.num_experts_per_tok
1754-
if routing.sorted_selected_experts.shape[0] != original_inputs_first_dim:
1755-
raise ValueError("original_inputs_first_dim does not match the original tensor" " shape!")
1756-
output_shape = jax.lax.empty(
1757-
(
1758-
original_inputs_first_dim,
1759-
self.moe_expert_input_dim // self.get_tensor_parallelism_size(),
1760-
),
1761-
dtype=intermediate_output.dtype,
1762-
)
1763-
1764-
if is_batch_sharded_by_expert:
1765-
# locally unpermute back to the original order
1766-
if self.config.use_ragged_sort:
1767-
# Mirror the ragged-prefix gather used in `local_permute`. The
1768-
# un-permute can use the same valid-prefix length because the
1769-
# routed token count is identical for forward and backward.
1770-
valid_end = jnp.sum(routing.group_sizes).astype(jnp.int32)
1771-
local_output = a2a_ragged_unsort(
1772-
intermediate_output,
1773-
jnp.argsort(route_metadata.local_sorted_indices), # pylint: disable=undefined-variable
1774-
valid_end,
1775-
)
1776-
else:
1777-
local_output = _sort_activations(
1778-
intermediate_output,
1779-
jnp.argsort(route_metadata.local_sorted_indices),
1780-
self.config.use_custom_sort_vjp,
1781-
)
1782-
1783-
input_offsets, send_sizes, output_offsets, recv_sizes = RoutedMoE.get_all_to_all_params(
1784-
jnp.transpose(route_metadata.all_shards_group_sizes),
1785-
route_metadata.expert_shard_id,
1786-
self.get_expert_parallelism_size(),
1787-
)
1788-
intermediate_output = jax.lax.ragged_all_to_all(
1789-
local_output,
1790-
output_shape,
1791-
input_offsets,
1792-
send_sizes,
1793-
output_offsets,
1794-
recv_sizes,
1795-
axis_name=self._expert_parallelism_name,
1796-
)
1797-
else:
1798-
# If batch is replicated across EP shards then each shard should send
1799-
# 0..local_shard_size data to the other shards and receive the
1800-
# local_shard data from all of the other shards using ragged_all_to_all.
1801-
input_offsets, send_sizes, output_offsets, recv_sizes = RoutedMoE.get_all_to_all_params(
1802-
route_metadata.reshaped_group_sizes,
1803-
route_metadata.expert_shard_id,
1804-
self.get_expert_parallelism_size(),
1805-
is_batch_sharded=False,
1806-
)
1807-
intermediate_output = jax.lax.ragged_all_to_all(
1808-
intermediate_output,
1809-
output_shape,
1810-
input_offsets,
1811-
send_sizes,
1812-
output_offsets,
1813-
recv_sizes,
1814-
axis_name=self._expert_parallelism_name,
1815-
)
1816-
1817-
output = self.unpermute(
1822+
intermediate_output = unsort_output_and_ra2a(
18181823
intermediate_output,
1819-
routing.sorted_selected_experts,
1820-
routing.weights,
1821-
batch_size=batch_size,
1822-
sequence_length=sequence_length,
1823-
use_custom_sort_vjp=self.config.use_custom_sort_vjp,
1824-
group_sizes=routing.group_sizes,
1824+
routing,
1825+
route_metadata,
1826+
output_shape,
1827+
is_batch_sharded_by_expert,
18251828
)
18261829

1830+
output = self.unpermute(
1831+
intermediate_output,
1832+
routing.sorted_selected_experts,
1833+
routing.weights,
1834+
batch_size=batch_size,
1835+
sequence_length=sequence_length,
1836+
use_custom_sort_vjp=self.config.use_custom_sort_vjp,
1837+
group_sizes=routing.group_sizes,
1838+
)
1839+
18271840
return output, routing.lb_loss, routing.bias_updates
18281841

18291842
if self.config.moe_fsdp_use_two_stage_all_gather:
@@ -1871,7 +1884,7 @@ def wrapper(x, logits, pre_bias_logits, w0, w1, wo, w0_bias, w1_bias, wo_bias, s
18711884
if wo_bias is not None:
18721885
wo_bias = self._maybe_shard_with_pspec(wo_bias, wo_bias_pspec)
18731886

1874-
return wrapper(
1887+
return sparse_matmul_route_and_compute(
18751888
inputs,
18761889
gate_logits,
18771890
pre_bias_logits,

0 commit comments

Comments
 (0)