Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
94a2786
init
IlyasMoutawwakil Apr 23, 2026
8fc43d7
Merge branch 'main' into deepgemm
IlyasMoutawwakil Apr 23, 2026
357a035
style
IlyasMoutawwakil Apr 23, 2026
741b5eb
full support
IlyasMoutawwakil Apr 23, 2026
9fc3662
support EP better using offsets !
IlyasMoutawwakil Apr 24, 2026
84552ae
comments
IlyasMoutawwakil Apr 24, 2026
1d9f319
get rid of neutralize_ep_sentinels
IlyasMoutawwakil Apr 24, 2026
9b86043
remove deepgemm stuff
IlyasMoutawwakil Apr 24, 2026
8a3f88b
Merge branch 'main' into deepgemm
IlyasMoutawwakil Apr 24, 2026
996d67d
fix
IlyasMoutawwakil Apr 24, 2026
d033a83
prefix
IlyasMoutawwakil Apr 24, 2026
e15cfe6
move
IlyasMoutawwakil Apr 24, 2026
10b6d90
fix
IlyasMoutawwakil Apr 24, 2026
d4a6b30
remove comment
IlyasMoutawwakil Apr 24, 2026
1d6054f
fix unintilized outputs leaking
IlyasMoutawwakil Apr 24, 2026
137393c
revert unnecessary changes
IlyasMoutawwakil Apr 24, 2026
774f901
more unnecessary changes
IlyasMoutawwakil Apr 24, 2026
81230fe
revert downcast
IlyasMoutawwakil Apr 24, 2026
9f2ff08
keep it simple
IlyasMoutawwakil Apr 24, 2026
c55b7b7
guard deepgemm cuda version
IlyasMoutawwakil Apr 24, 2026
20858db
fix style
IlyasMoutawwakil Apr 24, 2026
bfea94f
update
IlyasMoutawwakil Apr 24, 2026
eada47e
add deepgemm testing
IlyasMoutawwakil Apr 24, 2026
89d2f0b
moe sentinel support
IlyasMoutawwakil Apr 26, 2026
ef72b0e
Merge branch 'main' into deepgemm
IlyasMoutawwakil Apr 26, 2026
60db1ca
fix
IlyasMoutawwakil Apr 26, 2026
e732af1
Merge branch 'main' into deepgemm
IlyasMoutawwakil Apr 27, 2026
68b7b0f
compilable sonicmoe
IlyasMoutawwakil Apr 27, 2026
faaa7aa
mega moe kernel support attempt
IlyasMoutawwakil Apr 29, 2026
b502cd6
use package for now
IlyasMoutawwakil Apr 29, 2026
cc753ca
Merge branch 'deepgemm' into deepgemm-isolation
IlyasMoutawwakil Apr 29, 2026
1c17452
skip ep router and experts pre/post processing
IlyasMoutawwakil Apr 29, 2026
5a8ceae
simpler
IlyasMoutawwakil Apr 29, 2026
a05aa39
fix
IlyasMoutawwakil Apr 29, 2026
854f4fb
Merge branch 'main' into deepgemm-isolation
IlyasMoutawwakil Apr 29, 2026
053c9df
fix
IlyasMoutawwakil Apr 29, 2026
80a6fe5
fix
IlyasMoutawwakil May 1, 2026
ad8226c
dtensor support
IlyasMoutawwakil May 1, 2026
a663f4d
more dtensor
IlyasMoutawwakil May 1, 2026
74c3f2e
simpler
IlyasMoutawwakil May 1, 2026
d3cae33
remove comment
IlyasMoutawwakil May 1, 2026
c1bfa0f
Merge branch 'deepgemm' into deepgemm-isolation
IlyasMoutawwakil May 2, 2026
6c43611
Merge branch 'main' into deepgemm-isolation
IlyasMoutawwakil May 4, 2026
0528e0e
revert
IlyasMoutawwakil May 4, 2026
2bfd029
bc order
IlyasMoutawwakil May 4, 2026
368db00
revert extra indent
IlyasMoutawwakil May 4, 2026
28fbb84
revert unnecessary change
IlyasMoutawwakil May 4, 2026
6ef27ab
update
IlyasMoutawwakil May 4, 2026
e436b77
less defensive
IlyasMoutawwakil May 4, 2026
8e8f0ee
allow all kernels
IlyasMoutawwakil May 5, 2026
c494e35
alow all kernels
IlyasMoutawwakil May 5, 2026
03b0442
hub only
IlyasMoutawwakil May 5, 2026
527d8b4
Merge branch 'main' into deepgemm-isolation
IlyasMoutawwakil May 5, 2026
2e51b3c
fix
IlyasMoutawwakil May 5, 2026
82c5fb5
fix
IlyasMoutawwakil May 5, 2026
99fdf71
test
IlyasMoutawwakil May 5, 2026
21398a8
test
IlyasMoutawwakil May 5, 2026
f21db7c
sync
IlyasMoutawwakil May 6, 2026
1fe3768
check nvcc
IlyasMoutawwakil May 6, 2026
bbfda35
probe
IlyasMoutawwakil May 6, 2026
68a373c
fix
IlyasMoutawwakil May 6, 2026
825f6d4
test psum
IlyasMoutawwakil May 6, 2026
028a39f
test
IlyasMoutawwakil May 6, 2026
ee173a5
test
IlyasMoutawwakil May 6, 2026
900e984
probe
IlyasMoutawwakil May 6, 2026
09a711f
fix
IlyasMoutawwakil May 6, 2026
a0d4940
test
IlyasMoutawwakil May 6, 2026
653b7b3
nan issue
IlyasMoutawwakil May 6, 2026
ed8af6b
repro
IlyasMoutawwakil May 6, 2026
fb8d338
repro
IlyasMoutawwakil May 6, 2026
562eb51
fix
IlyasMoutawwakil May 6, 2026
481e5e6
simplifications
IlyasMoutawwakil May 6, 2026
d3dbd32
fix
IlyasMoutawwakil May 6, 2026
9f168ff
fix
IlyasMoutawwakil May 6, 2026
7274c22
fix
IlyasMoutawwakil May 6, 2026
a800b8c
fix
IlyasMoutawwakil May 6, 2026
804c988
fix
IlyasMoutawwakil May 6, 2026
7f36562
fix
IlyasMoutawwakil May 6, 2026
6df9f47
fix
IlyasMoutawwakil May 6, 2026
c3432c9
empty
IlyasMoutawwakil May 6, 2026
77f09fe
simplify
IlyasMoutawwakil May 6, 2026
7dfbedd
test deepseek
IlyasMoutawwakil May 6, 2026
689cc29
dsv4 only
IlyasMoutawwakil May 6, 2026
8de089c
download dsv4
IlyasMoutawwakil May 6, 2026
cb4d6f9
fix test
IlyasMoutawwakil May 6, 2026
389eee8
Merge branch 'main' into deepgemm-isolation
IlyasMoutawwakil May 6, 2026
8f29ed6
push
IlyasMoutawwakil May 6, 2026
946e200
test
IlyasMoutawwakil May 6, 2026
6619647
fix
IlyasMoutawwakil May 6, 2026
913339a
fix ep plan
IlyasMoutawwakil May 6, 2026
7cfc2b2
fix attempt
IlyasMoutawwakil May 6, 2026
4c12f6e
debug
IlyasMoutawwakil May 6, 2026
92e6337
attempt
IlyasMoutawwakil May 6, 2026
a9997f5
debug
IlyasMoutawwakil May 6, 2026
197a8f6
fixes in modeling
IlyasMoutawwakil May 11, 2026
30d0780
more modeling changes
IlyasMoutawwakil May 11, 2026
3b1c470
more modeling changes
IlyasMoutawwakil May 11, 2026
51a9425
initial megamoe works but wrong output, deepgemm fully functional
IlyasMoutawwakil May 11, 2026
a4130db
mega moe works !
IlyasMoutawwakil May 11, 2026
b140f7c
simplification
IlyasMoutawwakil May 11, 2026
9ff656b
comments
IlyasMoutawwakil May 11, 2026
b5b741e
Merge branch 'main' into deepgemm-isolation
IlyasMoutawwakil May 12, 2026
1231258
fix merge
IlyasMoutawwakil May 12, 2026
a8cc32a
fix rank divergence
IlyasMoutawwakil May 12, 2026
c6486cb
use _keep_in_fp32_modules
IlyasMoutawwakil May 12, 2026
bd68b6f
simplify quantizer
IlyasMoutawwakil May 12, 2026
8630f9d
introduce indexerscorer
IlyasMoutawwakil May 12, 2026
f3b933f
remove testing file
IlyasMoutawwakil May 12, 2026
029a4c9
style
IlyasMoutawwakil May 12, 2026
85b5768
weight rename for scorer
IlyasMoutawwakil May 12, 2026
7f19516
style
IlyasMoutawwakil May 12, 2026
e395e4c
address review comments
IlyasMoutawwakil May 12, 2026
1b94261
style
IlyasMoutawwakil May 12, 2026
af51a6e
align with laguna
IlyasMoutawwakil May 12, 2026
ca934bf
Merge branch 'main' into deepgemm-isolation
IlyasMoutawwakil May 12, 2026
f18ab28
stale comments and styling
IlyasMoutawwakil May 12, 2026
26f3ba7
use grouped finegrained fp8 for grouped linear
IlyasMoutawwakil May 19, 2026
4039ed6
Merge branch 'main' into deepgemm-isolation
IlyasMoutawwakil May 19, 2026
9f2c97b
comments and docs
IlyasMoutawwakil May 19, 2026
8dc75bd
Revert "[DeepSeek V4] Fix MoE converter substring-matching FP8 scale …
ArthurZucker May 28, 2026
57081cc
Merge remote-tracking branch 'origin/main' into deepgemm-isolation
IlyasMoutawwakil May 28, 2026
78fcee6
fix quantizer and use upstream deepgemm
IlyasMoutawwakil May 28, 2026
2e4203f
remove force al kernels
IlyasMoutawwakil May 28, 2026
5f9e5cd
[deepseek_v4] fix FP8 save-side substring match + fp32 gate through s…
ArthurZucker May 28, 2026
afd1b70
always floats scal inv with triton
IlyasMoutawwakil May 28, 2026
619b5e9
minimal changes i quantizer
IlyasMoutawwakil May 28, 2026
3e76df5
force stable abi build for now
IlyasMoutawwakil May 28, 2026
f0e2859
support transposed
IlyasMoutawwakil May 28, 2026
d0c4a6d
fix yarn
IlyasMoutawwakil May 29, 2026
c1adcd7
unnecessary change
IlyasMoutawwakil May 29, 2026
143835f
add flash base test and fix the incorrect and crash issue during enab…
sywangyi May 29, 2026
b47b30f
merge
IlyasMoutawwakil May 29, 2026
8bd9619
better errors across deepgemm
IlyasMoutawwakil May 29, 2026
751c8b5
more better errors for deepgemm
IlyasMoutawwakil May 29, 2026
70c7c3b
ep tests
IlyasMoutawwakil May 29, 2026
464512e
Apply suggestions from code review
ArthurZucker May 29, 2026
d6fd64d
scope supports_round_trip to quantization ops only
ArthurZucker May 29, 2026
6e17509
Apply suggestions from code review
ArthurZucker May 29, 2026
3259618
Update src/transformers/core_model_loading.py
ArthurZucker May 29, 2026
2c06aef
style: ruff format
ArthurZucker May 29, 2026
7dfe6bd
custom ep/tp plan for megamoe
IlyasMoutawwakil Jun 1, 2026
1889163
process megamoe after weight loading
IlyasMoutawwakil Jun 1, 2026
46dc289
fix megamoe process
IlyasMoutawwakil Jun 1, 2026
e9ccaa0
up
ArthurZucker Jun 1, 2026
7d74684
the actual fix???
ArthurZucker Jun 1, 2026
87d2ee9
up
ArthurZucker Jun 1, 2026
7be266b
nit comment for futur
ArthurZucker Jun 1, 2026
5e102f1
style: drop unused exception variable in Fp8Dequantize._dequantize_one
ArthurZucker Jun 1, 2026
8631e6f
up
ArthurZucker Jun 1, 2026
b05bda4
style: apply make fix-repo docstring formatting
ArthurZucker Jun 1, 2026
7481aa6
Merge pr-46265 into deepgemm-isolation, drop redundant scale-merge wo…
IlyasMoutawwakil Jun 1, 2026
f769847
simplify after merge
IlyasMoutawwakil Jun 1, 2026
2b8bba0
review comments
IlyasMoutawwakil Jun 1, 2026
beac5f2
Merge branch 'main' into deepgemm-isolation
IlyasMoutawwakil Jun 1, 2026
f72bc20
revert unncessary
IlyasMoutawwakil Jun 2, 2026
b5f2d45
avoid name contraction
IlyasMoutawwakil Jun 2, 2026
014707d
fixes
IlyasMoutawwakil Jun 2, 2026
2a77aa7
dynamic tp/ep plan swap
IlyasMoutawwakil Jun 2, 2026
6922e3a
fix deepgemm single error and device assertion docs
IlyasMoutawwakil Jun 2, 2026
7471109
properly support bias in grouped linear
IlyasMoutawwakil Jun 2, 2026
b63ce4f
simplify
IlyasMoutawwakil Jun 2, 2026
c12e892
fix dist error handling and min cuda compatbility
IlyasMoutawwakil Jun 2, 2026
1ec0147
fix least cuda compat
IlyasMoutawwakil Jun 2, 2026
4fd793d
get alignment from deepgemm and cache it
IlyasMoutawwakil Jun 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/transformers/conversion_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@ def _build_checkpoint_conversion_mapping():
source_patterns=r"^layers\.(\d+)\.self_attn\.indexer\.",
target_patterns=r"layers.\1.self_attn.compressor.indexer.",
),
WeightRenaming(
source_patterns=r"^layers\.(\d+)\.self_attn\.compressor\.indexer\.weights_proj\.",
target_patterns=r"layers.\1.self_attn.compressor.indexer.scorer.weights_proj.",
),
WeightRenaming(
source_patterns=r"^layers\.(\d+)\.self_attn\.compressor\.norm\.",
target_patterns=r"layers.\1.self_attn.compressor.kv_norm.",
Expand Down
748 changes: 748 additions & 0 deletions src/transformers/integrations/deepgemm.py

Large diffs are not rendered by default.

774 changes: 374 additions & 400 deletions src/transformers/integrations/finegrained_fp8.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/transformers/integrations/hub_kernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ def register_kernel_mapping_transformers(*args, **kwargs):
"mamba-ssm": {"repo_id": "kernels-community/mamba-ssm", "version": 1},
"falcon_mamba-ssm": {"repo_id": "kernels-community/mamba-ssm", "version": 1},
"finegrained-fp8": {"repo_id": "kernels-community/finegrained-fp8", "version": 1},
"deep-gemm": {"repo_id": "kernels-community/deep-gemm", "version": 1},
"deep-gemm": {"repo_id": "kernels-community/deep-gemm", "version": 2},
"sonic-moe": {"repo_id": "kernels-community/sonic-moe", "revision": "ep-support"},
}

Expand Down Expand Up @@ -376,7 +376,7 @@ def lazy_load_kernel(kernel_name: str, mapping: dict[str, ModuleType | None] = _
repo_id = _HUB_KERNEL_MAPPING[kernel_name]["repo_id"]
revision = _HUB_KERNEL_MAPPING[kernel_name].get("revision", None)
version = _HUB_KERNEL_MAPPING[kernel_name].get("version", None)
kernel = get_kernel(repo_id, revision=revision, version=version)
kernel = get_kernel(repo_id, revision=revision, version=version, allow_all_kernels=ALLOW_ALL_KERNELS)
mapping[kernel_name] = kernel
except FileNotFoundError as e:
mapping[kernel_name] = None
Expand Down
5 changes: 4 additions & 1 deletion src/transformers/integrations/moe.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
is_torch_less_or_equal,
is_torchdynamo_compiling,
)
from .deepgemm import deepgemm_bf16_experts_forward
from .sonicmoe import sonicmoe_experts_forward


Expand Down Expand Up @@ -133,7 +134,8 @@ def batched_mm_experts_forward(
# Clamp EP sentinels so `gate_up_proj[expert_ids]` stays in-bounds. Routing weights are already
# zero at sentinel slots (RouterParallel masks them at dispatch), so the weighted mul drops
# those contributions — we pay the wasted GEMM compute because batched_mm has no offset to skip.
expert_ids.clamp_(0, self.num_experts - 1)
# Out-of-place to avoid mutating the caller's routing tensor (a contiguous `reshape(-1)` aliases it).
expert_ids = expert_ids.clamp(0, self.num_experts - 1)

# Select gate_up or just up projection weights and biases
if self.has_gate:
Expand Down Expand Up @@ -483,6 +485,7 @@ class ExpertsInterface(GeneralInterface):
"""Interface for registering custom experts forward functions."""

_global_mapping = {
"deepgemm": deepgemm_bf16_experts_forward,
"batched_mm": batched_mm_experts_forward,
"grouped_mm": grouped_mm_experts_forward,
"sonicmoe": sonicmoe_experts_forward,
Expand Down
17 changes: 5 additions & 12 deletions src/transformers/integrations/sonicmoe.py
Comment thread
IlyasMoutawwakil marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

from ..utils import logging
from .hub_kernels import lazy_load_kernel
from .tensor_parallel import to_local


logger = logging.get_logger(__name__)
Expand Down Expand Up @@ -169,18 +170,10 @@ def sonicmoe_experts_forward(
# already zero (RouterParallel masks them at dispatch), so the per-token reduction
# contributes nothing for sentinel slots.

# FSDP2 / EP wraps weights as DTensors but the kernel takes raw CUTLASS / CuteDSL pointers,
# so unwrap to local shards before reshaping. `to_local()` is autograd-aware — backward
# will rewrap the gradient as a DTensor matching each parameter's placements.
w1 = self.gate_up_proj
w2 = self.down_proj
b1 = self.gate_up_proj_bias if self.has_bias else None
b2 = self.down_proj_bias if self.has_bias else None
if isinstance(w1, torch.distributed.tensor.DTensor):
w1 = w1.to_local()
w2 = w2.to_local()
b1 = b1.to_local() if b1 is not None else None
b2 = b2.to_local() if b2 is not None else None
w1 = to_local(self.gate_up_proj)
w2 = to_local(self.down_proj)
b1 = to_local(self.gate_up_proj_bias) if self.has_bias else None
b2 = to_local(self.down_proj_bias) if self.has_bias else None

# Map activation function
act_name = getattr(self.config, "hidden_act", "silu").lower()
Expand Down
82 changes: 80 additions & 2 deletions src/transformers/integrations/tensor_parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@
logger = logging.get_logger(__name__)


def to_local(t):
"""Unwrap a `DTensor` to its local shard if needed; pass through otherwise.
Custom kernels (CUTLASS, CuteDSL, Triton) take raw tensor pointers and don't
understand `DTensor`, so weights wrapped by FSDP2 / EP need this unwrap before
they can be fed to the kernel. ``to_local()`` is autograd-aware on the train
path: backward rewraps the gradient as a DTensor matching each parameter's
placements.
"""
if hasattr(torch.distributed, "tensor") and hasattr(torch.distributed.tensor, "DTensor"):
if isinstance(t, torch.distributed.tensor.DTensor):
return t.to_local()
return t


def initialize_tensor_parallelism(
tp_plan: str | dict[str, str] | None, tp_size: int | None = None, device_mesh=None, device_map=None
):
Expand Down Expand Up @@ -773,6 +788,25 @@ def _backward_hook(mod, grad_input, grad_output, mesh=device_mesh):
module.register_full_backward_hook(_backward_hook)


class AllReduceParallel(TensorParallelLayer):
"""All-reduce a module's forward output across the TP mesh. Use as a declarative
sync point at the boundary of a multi-arg module whose compute ends in a partial
sum (e.g. the lightning indexer's score sum before its top-k).
"""

def _prepare_input_fn(self, mod, inputs, device_mesh):
return inputs

def _prepare_output_fn(self, mod, outputs, device_mesh):
return all_reduce_forward(outputs, device_mesh)

def shard_tensor(self, param, tensor_idx=None, device=None, dtype=None):
return param[...].to(device=device, dtype=dtype)

def prepare_module_tp(self, module, device_mesh, **kwargs):
distribute_module(module, device_mesh, output_fn=self._prepare_output_fn)


class MlaKvAProjParallel(TensorParallelLayer):
"""
For MLA attention used in DeepSeek-V2 style models (deepseek_v2, longcat_flash, glm_moe_dsa, glm4_moe_lite):
Expand Down Expand Up @@ -1095,7 +1129,7 @@ def __init__(self, **kwargs):
super().__init__(**kwargs)

def _prepare_input_fn(self, mod, inputs, device_mesh):
return inputs[0] if inputs else inputs
return inputs

def _prepare_output_fn(self, mod, outputs, device_mesh):
"""
Expand Down Expand Up @@ -1173,6 +1207,19 @@ def shard_tensor(
return param[...].to(device=device, dtype=dtype)


class RouterParallelMegaMoe(RouterParallel):
"""Router TP plan used with DeepGEMM Mega MoE.
Mega MoE handles EP dispatch inside the kernel and wants raw global expert ids
with unmasked routing weights, so the router doesn't pre-shard per EP rank like
`RouterParallel._prepare_output_fn` does. The quantizer's `update_tp_plan` swaps
`"ep_router"` → `"megamoe_router"` when `experts_implementation == "deepgemm_megamoe"`.
"""

def _prepare_output_fn(self, mod, outputs, device_mesh):
return outputs


class MoeTensorParalellExperts(TensorParallelLayer):
"""
Note: For tensor parallel, the MoEExpertsParallel TP layer handles gradient sync:
Expand All @@ -1198,7 +1245,7 @@ def _prepare_input_fn(self, mod, inputs, device_mesh):
# and partial_expert_output is different on each GPU before all-reduce
top_k_weights = all_reduce_backward(top_k_weights, device_mesh)

return (hidden_states, top_k_index, top_k_weights)
return hidden_states, top_k_index, top_k_weights

def _prepare_output_fn(self, mod, outputs, device_mesh):
# all_reduce_forward to sum partial expert outputs across GPUs
Expand All @@ -1212,6 +1259,32 @@ def shard_tensor(
return param[...].to(device=device, dtype=dtype)


class MoeTensorParalellMegaMoeExperts(TensorParallelLayer):
"""TP layer for DeepGEMM Mega MoE experts.
Mega MoE is inference-only (the kernel has no backward) and handles EP dispatch +
combine + per-rank token sharding internally — so we skip the gradient-sync hooks
that the regular `MoeTensorParalellExperts` would apply, and we forward the EP
`process_group` into the module so the symm-buffer rendezvous can run on first
forward. The quantizer's `update_tp_plan` swaps the experts plan key from
`"moe_tp_experts"` to `"megamoe_experts"` when
`from_pretrained(..., experts_implementation="deepgemm_megamoe")`.
"""

def _prepare_input_fn(self, mod, inputs, device_mesh):
hidden_states, top_k_index, top_k_weights = inputs[0], inputs[1], inputs[2]
return hidden_states, top_k_index, top_k_weights, device_mesh.get_group()

def _prepare_output_fn(self, mod, outputs, device_mesh):
# Kernel returned the fully-combined gathered output; no further reduction.
return outputs

def shard_tensor(
self, param: torch.Tensor, tensor_idx: int | None = None, device=None, dtype=None
) -> torch.Tensor:
return param[...].to(device=device, dtype=dtype)


class MoeIdentityExpertParallel(TensorParallelLayer):
"""
TP class for zero/identity experts in MoE layers.
Expand Down Expand Up @@ -1250,10 +1323,13 @@ class ParallelInterface(GeneralInterface):
"sequence_parallel": SequenceParallel(),
"grouped_gemm": GroupedGemmParallel(),
"ep_router": RouterParallel(),
"megamoe_router": RouterParallelMegaMoe(),
"moe_tp_experts": MoeTensorParalellExperts(),
"megamoe_experts": MoeTensorParalellMegaMoeExperts(),
"moe_identity_expert": MoeIdentityExpertParallel(),
"replicated_with_grad_allreduce": ReplicatedWithGradAllReduce(),
"mla_kv_a_proj": MlaKvAProjParallel(),
"all_reduce": AllReduceParallel(),
}
if is_torch_available() and _torch_distributed_available
else {}
Expand All @@ -1274,6 +1350,7 @@ class ParallelInterface(GeneralInterface):
"sequence_parallel": None,
"replicated_with_grad_allreduce": None,
"mla_kv_a_proj": None,
"all_reduce": None,
}

# Bias sharding: colwise shards bias, rowwise doesn't (bias is replicated and all-reduced)
Expand All @@ -1289,6 +1366,7 @@ class ParallelInterface(GeneralInterface):
"sequence_parallel": None,
"replicated_with_grad_allreduce": None,
"mla_kv_a_proj": None,
"all_reduce": None,
}

@classmethod
Expand Down
12 changes: 12 additions & 0 deletions src/transformers/modeling_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2212,6 +2212,18 @@ def set_experts_implementation(self, experts_implementation: str | dict):
else experts_implementation.get("", self.config._experts_implementation)
)

# MegaMoE is locked at load time: its TP plan is baked into `base_model_tp_plan`
# by `update_tp_plan` (and isn't re-evaluated) and `setup_megamoe_weights`
# mutates the expert weights into UTCCP layout on first forward. Either side of
# a switch would silently produce garbage, so reject it with a clear pointer.
current = self.config._experts_implementation
if "deepgemm_megamoe" in (current, requested_implementation) and current != requested_implementation:
raise RuntimeError(
f"Cannot switch experts implementation from {current!r} to {requested_implementation!r} "
"at runtime: `deepgemm_megamoe` is a load-time choice. Reload via "
"`from_pretrained(..., experts_implementation=...)` to switch."
)

if requested_implementation != self.config._experts_implementation:
requested_implementation = self._check_and_adjust_experts_implementation(requested_implementation)
# Apply the change (on the internal attr, to avoid setting it recursively)
Expand Down
42 changes: 26 additions & 16 deletions src/transformers/models/deepseek_v4/configuration_deepseek_v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,20 +112,28 @@ class DeepseekV4Config(PreTrainedConfig):
"norm": (["hidden_states"], ["hidden_states"]),
}
base_model_ep_plan = {
# EP-only by default, same shape as gpt-oss: route on the gate, run the
# routed experts as a grouped-GEMM kernel sharded along the expert axis,
# and wrap the experts module with `moe_tp_experts` so its output gets
# all-reduced across ranks. Attention stays replicated (V4 is shared-KV
# MQA + a CSA / HCA compressor branch — both broadcast a single KV head
# across all attention heads via `repeat_kv`, so colwise-sharding
# `q_b_proj` would leave KV replicated and `repeat_kv` would no longer
# match the rank-local query head count). The shared MLP also stays
# replicated — it's small and not worth TP-ing. There's deliberately
# no `base_model_tp_plan` for V4: we don't ship a pure-TP plan, only EP.
# V4 ships EP only (no `base_model_tp_plan` — the runtime picks one plan or
# the other, never both, and V4 is MoE so EP is the only sensible config).
# MoE parallelism: route on the gate, run the routed experts as a grouped-GEMM
# kernel sharded along the expert axis, and wrap the experts module with
# `moe_tp_experts` so its output gets all-reduced across ranks. Same shape as
# gpt-oss. Main attention stays replicated: V4 is shared-KV MQA + a CSA / HCA
# compressor branch — both broadcast a single KV head across all attention
# heads via `repeat_kv`, so colwise-sharding `q_b_proj` would leave KV
# replicated and `repeat_kv` would no longer match the rank-local query head
# count. The shared MLP also stays replicated — it's small and not worth
# sharding. The Lightning Indexer is the one carve-out: its keys are
# replicated (own compressor at index_head_dim fed by replicated
# hidden_states), so head-sharding is well-formed; `q_b_proj` and the
# `scorer.weights_proj` go colwise, and the `scorer` output is all-reduced
# so every rank sees the same `index_scores` and picks the same top-k.
"layers.*.mlp.gate": "ep_router",
"layers.*.mlp.experts.gate_up_proj": "grouped_gemm",
"layers.*.mlp.experts.down_proj": "grouped_gemm",
"layers.*.mlp.experts": "moe_tp_experts",
"layers.*.self_attn.compressor.indexer.q_b_proj": "colwise",
"layers.*.self_attn.compressor.indexer.scorer.weights_proj": "colwise",
"layers.*.self_attn.compressor.indexer.scorer": "all_reduce",
}

vocab_size: int = 129280
Expand Down Expand Up @@ -283,12 +291,14 @@ def __post_init__(self, **kwargs):
)
self.qk_rope_head_dim = int(self.head_dim * self.partial_rotary_factor)

# yarn is applied ONLY to layers with a
# compressor (CSA/HCA); pure sliding-window layers use plain RoPE with
# `theta=rope_theta` (10000) and no scaling. Compress layers use
# `theta=compress_rope_theta` (160000) with yarn factor=16, and the reference
# does NOT multiply cos/sin by the yarn mscale — force `attention_factor=1.0`
# so transformers' `_compute_yarn_parameters` doesn't apply `0.1·log(16)+1`.
# yarn is applied ONLY to layers with a compressor (CSA/HCA); pure
# sliding-window layers use plain RoPE with `theta=rope_theta` (10000) and no
# scaling. Compress layers use `theta=compress_rope_theta` (160000) with yarn
# factor=16. For a YaRN compress layer we force `attention_factor=1.0`: the V4
# reference does NOT multiply cos/sin by YaRN's computed mscale, and leaving the
# key unset lets `_compute_yarn_parameters` derive `0.1·log(factor)+1 ≈ 1.277`.
# We only inject the key when `rope_type="yarn"` — the default-rope validator
# rejects it (and `compute_default_rope_parameters` hardcodes 1.0 anyway).
rp = self.rope_parameters or {}
if isinstance(rp.get("main"), dict) and isinstance(rp.get("compress"), dict):
# Already nested — drop any leftover top-level keys.
Expand Down
Loading
Loading