Skip to content

Commit cd7d9a5

Browse files
Evanev7Awni Hannun
andauthored
Add minimax tensor sharding (ml-explore#760)
* add minimax sharding * fix --------- Co-authored-by: Awni Hannun <awni@apple.com>
1 parent 2524663 commit cd7d9a5

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

mlx_lm/models/minimax.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import mlx.core as mx
77
import mlx.nn as nn
8+
from mlx.nn.layers.distributed import shard_inplace, shard_linear, sum_gradients
89

910
from .base import BaseModelArgs, create_attention_mask, scaled_dot_product_attention
1011
from .switch_layers import SwitchGLU
@@ -118,8 +119,12 @@ def __init__(self, args: ModelArgs):
118119
args.hidden_size, args.intermediate_size, args.num_local_experts
119120
)
120121
self.e_score_correction_bias = mx.zeros((args.num_local_experts,))
122+
self.sharding_group = None
121123

122124
def __call__(self, x: mx.array) -> mx.array:
125+
if self.sharding_group is not None:
126+
x = sum_gradients(self.sharding_group)(x)
127+
123128
gates = self.gate(x.astype(mx.float32))
124129

125130
scores = mx.sigmoid(gates)
@@ -135,6 +140,10 @@ def __call__(self, x: mx.array) -> mx.array:
135140

136141
y = self.switch_mlp(x, inds)
137142
y = (y * scores[..., None]).sum(axis=-2)
143+
144+
if self.sharding_group is not None:
145+
y = mx.distributed.all_sum(y, group=self.sharding_group)
146+
138147
return y
139148

140149

@@ -267,6 +276,53 @@ def dequant(weight, scale_inv):
267276

268277
return weights
269278

279+
def shard(self, group: Optional[mx.distributed.Group] = None):
280+
group = group or mx.distributed.init()
281+
N = group.size()
282+
rank = group.rank()
283+
for layer in self.model.layers:
284+
# Shard the self attention
285+
layer.self_attn.q_proj = shard_linear(
286+
layer.self_attn.q_proj, "all-to-sharded", group=group
287+
)
288+
layer.self_attn.k_proj = shard_linear(
289+
layer.self_attn.k_proj, "all-to-sharded", group=group
290+
)
291+
layer.self_attn.v_proj = shard_linear(
292+
layer.self_attn.v_proj, "all-to-sharded", group=group
293+
)
294+
layer.self_attn.o_proj = shard_linear(
295+
layer.self_attn.o_proj, "sharded-to-all", group=group
296+
)
297+
if layer.self_attn.use_qk_norm:
298+
layer.self_attn.q_norm.weight = layer.self_attn.q_norm.weight.split(
299+
N, axis=-1
300+
)[rank]
301+
layer.self_attn.k_norm.weight = layer.self_attn.k_norm.weight.split(
302+
N, axis=-1
303+
)[rank]
304+
305+
layer.self_attn.num_attention_heads //= N
306+
layer.self_attn.num_key_value_heads //= N
307+
308+
# Shard the MLP
309+
shard_inplace(
310+
layer.block_sparse_moe.switch_mlp.gate_proj,
311+
"all-to-sharded",
312+
group=group,
313+
)
314+
shard_inplace(
315+
layer.block_sparse_moe.switch_mlp.down_proj,
316+
"sharded-to-all",
317+
group=group,
318+
)
319+
shard_inplace(
320+
layer.block_sparse_moe.switch_mlp.up_proj,
321+
"all-to-sharded",
322+
group=group,
323+
)
324+
layer.block_sparse_moe.sharding_group = group
325+
270326
@property
271327
def layers(self):
272328
return self.model.layers

0 commit comments

Comments
 (0)