Problem
get_num_experts_per_layer (megatron/model/transformer.py) raises an
IndexError for dense models (num_experts=[1]) whenever pipeline
parallelism is enabled (--pipeline-model-parallel-size > 1).
The function expands the single-element num_experts list using the
local per-stage layer count:
num_experts = num_experts * (num_layers // expert_interval)
but then indexes it using the global layer number, which includes the
pipeline stage offset:
layer_num = i + 1 + offset
n_e = num_experts[(layer_num-1) // expert_interval] if ...
For any pipeline stage past the first (offset > 0), the global index
exceeds the length of the locally-sized list, causing an out-of-bounds
access.
Reproduction
Any dense GPT run with PP > 1, e.g.:
--num-layers 32 --pipeline-model-parallel-size 2
--tensor-model-parallel-size 2
Stage 1 (offset=16) computes (30-1)//2 = 14 as an index into a
list of length 16//2 = 8 → IndexError.
TP-only and DP-only configurations are unaffected because offset is
always 0 there, which is why this only surfaces once PP is used.
Fix
Short-circuit the dense case before the MoE indexing logic. A dense
model has exactly one expert per layer regardless of stage offset:
In ./megatron/model/transformer.py adding these lines in function def get_num_experts_per_layer(num_experts: list, num_layers: int, expert_interval: int, offset: int = 0) -> list: solves the issue
if len(num_experts) == 1 and num_experts[0] == 1:
return [1] * num_layers
This leaves the genuine MoE path (num_experts > 1, or an explicit
per-layer list) completely untouched.
Notes
The deeper issue is that the expansion is sized by the local layer
count while indexing uses global layer numbers; a more complete fix
would reconcile the two for the MoE-with-PP case as well. This issue
addresses only the dense-model regression, which is the common path and
currently breaks all pipeline-parallel dense training.
Problem
get_num_experts_per_layer(megatron/model/transformer.py) raises anIndexError for dense models (
num_experts=[1]) whenever pipelineparallelism is enabled (
--pipeline-model-parallel-size > 1).The function expands the single-element
num_expertslist using thelocal per-stage layer count:
but then indexes it using the global layer number, which includes the
pipeline stage offset:
For any pipeline stage past the first (
offset > 0), the global indexexceeds the length of the locally-sized list, causing an out-of-bounds
access.
Reproduction
Any dense GPT run with PP > 1, e.g.:
--num-layers 32 --pipeline-model-parallel-size 2
--tensor-model-parallel-size 2
Stage 1 (offset=16) computes
(30-1)//2 = 14as an index into alist of length
16//2 = 8→ IndexError.TP-only and DP-only configurations are unaffected because
offsetisalways 0 there, which is why this only surfaces once PP is used.
Fix
Short-circuit the dense case before the MoE indexing logic. A dense
model has exactly one expert per layer regardless of stage offset:
In ./megatron/model/transformer.py adding these lines in function
def get_num_experts_per_layer(num_experts: list, num_layers: int, expert_interval: int, offset: int = 0) -> list:solves the issueThis leaves the genuine MoE path (
num_experts > 1, or an explicitper-layer list) completely untouched.
Notes
The deeper issue is that the expansion is sized by the local layer
count while indexing uses global layer numbers; a more complete fix
would reconcile the two for the MoE-with-PP case as well. This issue
addresses only the dense-model regression, which is the common path and
currently breaks all pipeline-parallel dense training.