Skip to content

Commit a9311cc

Browse files
authored
shard glm (#698)
* shard glm * angelos' fix * nit
1 parent 9fe5f43 commit a9311cc

2 files changed

Lines changed: 67 additions & 6 deletions

File tree

mlx_lm/models/deepseek_v3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ def shard(self, group: Optional[mx.distributed.Group] = None):
465465
# Shard the MoE. Shard in place since the MoE should be responsible
466466
# for aggregating the results.
467467
else:
468-
layer.mlp.sharding_group = group = group
468+
layer.mlp.sharding_group = group
469469
shard_inplace(
470470
layer.mlp.shared_experts.gate_proj, "all-to-sharded", group=group
471471
)

mlx_lm/models/glm4_moe.py

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import mlx.core as mx
99
import mlx.nn as nn
10+
from mlx.nn.layers.distributed import shard_inplace, shard_linear, sum_gradients
1011

1112
from .base import BaseModelArgs, create_attention_mask, scaled_dot_product_attention
1213
from .pipeline import PipelineMixin
@@ -205,13 +206,21 @@ def __init__(self, config: ModelArgs):
205206
config=config, intermediate_size=intermediate_size
206207
)
207208

209+
self.sharding_group = None
210+
208211
def __call__(self, x):
212+
if self.sharding_group is not None:
213+
x = sum_gradients(self.sharding_group)(x)
214+
209215
inds, scores = self.gate(x)
210216
y = self.switch_mlp(x, inds)
211217
y = (y * scores[..., None]).sum(axis=-2).astype(y.dtype)
212218
if self.config.n_shared_experts is not None:
213219
y = y + self.shared_experts(x)
214220

221+
if self.sharding_group is not None:
222+
y = mx.distributed.all_sum(y, group=self.sharding_group)
223+
215224
return y
216225

217226

@@ -252,10 +261,6 @@ def __init__(self, config: ModelArgs):
252261
self.layers = [
253262
DecoderLayer(config, idx) for idx in range(config.num_hidden_layers)
254263
]
255-
self.start_idx = 0
256-
self.end_idx = len(self.layers)
257-
self.num_layers = self.end_idx
258-
259264
self.norm = nn.RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
260265

261266
def __call__(
@@ -286,7 +291,8 @@ def __call__(
286291
cache[-1].keys = mx.depends(cache[-1].keys, h)
287292

288293
# Broadcast h while keeping it in the graph
289-
h = mx.distributed.all_gather(h)[: h.shape[0]]
294+
if pipeline_size > 1:
295+
h = mx.distributed.all_gather(h)[: h.shape[0]]
290296

291297
return self.norm(h)
292298

@@ -329,6 +335,61 @@ def sanitize(self, weights):
329335
if not k.startswith(f"model.layers.{mpt_layer}")
330336
}
331337

338+
def shard(self, group: Optional[mx.distributed.Group] = None):
339+
group = group or mx.distributed.init()
340+
N = group.size()
341+
for layer in self.model.layers:
342+
# Shard the self attention
343+
layer.self_attn.q_proj = shard_linear(
344+
layer.self_attn.q_proj, "all-to-sharded", group=group
345+
)
346+
layer.self_attn.k_proj = shard_linear(
347+
layer.self_attn.k_proj, "all-to-sharded", group=group
348+
)
349+
layer.self_attn.v_proj = shard_linear(
350+
layer.self_attn.v_proj, "all-to-sharded", group=group
351+
)
352+
layer.self_attn.o_proj = shard_linear(
353+
layer.self_attn.o_proj, "sharded-to-all", group=group
354+
)
355+
layer.self_attn.n_heads //= N
356+
layer.self_attn.n_kv_heads //= N
357+
358+
# Shard the MLP
359+
if isinstance(layer.mlp, MLP):
360+
layer.mlp.gate_proj = shard_linear(
361+
layer.mlp.gate_proj, "all-to-sharded", group=group
362+
)
363+
layer.mlp.down_proj = shard_linear(
364+
layer.mlp.down_proj, "sharded-to-all", group=group
365+
)
366+
layer.mlp.up_proj = shard_linear(
367+
layer.mlp.up_proj, "all-to-sharded", group=group
368+
)
369+
370+
# Shard the MoE. Shard in place since the MoE should be responsible
371+
# for aggregating the results.
372+
else:
373+
layer.mlp.sharding_group = group
374+
shard_inplace(
375+
layer.mlp.shared_experts.gate_proj, "all-to-sharded", group=group
376+
)
377+
shard_inplace(
378+
layer.mlp.shared_experts.down_proj, "sharded-to-all", group=group
379+
)
380+
shard_inplace(
381+
layer.mlp.shared_experts.up_proj, "all-to-sharded", group=group
382+
)
383+
shard_inplace(
384+
layer.mlp.switch_mlp.gate_proj, "all-to-sharded", group=group
385+
)
386+
shard_inplace(
387+
layer.mlp.switch_mlp.down_proj, "sharded-to-all", group=group
388+
)
389+
shard_inplace(
390+
layer.mlp.switch_mlp.up_proj, "all-to-sharded", group=group
391+
)
392+
332393
@property
333394
def layers(self):
334395
return self.model.pipeline_layers

0 commit comments

Comments
 (0)