Skip to content

FSDP2 training hangs during backward pass with MoE models when some experts are not activated #41881

Description

@LucienXian

System Info

Environment

  • transformers: 4.53.2
  • torch: 2.7.1+cu128
  • Model: Qwen3-30B-A3B

Who can help?

@seven-mile @ArthurZucker

Information

  • The official example scripts
  • My own modified scripts

Tasks

  • An officially supported task in the examples folder (such as GLUE/SQuAD, ...)
  • My own task or dataset (give details below)

Reproduction

Minimal Reproduction Code:

import torch
import torch.distributed as dist
from torch.utils.data import Dataset, DataLoader
from torch.utils.data.distributed import DistributedSampler
from transformers import AutoModelForCausalLM, AutoTokenizer, DataCollatorForLanguageModeling

def train():
    # Initialize distributed training
    dist.init_process_group(backend='nccl')
    rank = dist.get_rank()
    torch.cuda.set_device(rank)
    
    # Load MoE model (Qwen3 MoE specifically)
    model = AutoModelForCausalLM.from_pretrained(
        "Qwen/Qwen3-30B-A3B",  # Note: This should be a MoE model path
        trust_remote_code=True
    ).cuda()
    
    tokenizer = AutoTokenizer.from_pretrained(
        "Qwen/Qwen3-30B-A3B",  # Same as model path
        trust_remote_code=True
    )
    if tokenizer.pad_token is None:
        tokenizer.pad_token = tokenizer.eos_token
    
    # Apply FSDP2 - THIS CAUSES THE HANG WITH MOE MODELS
    use_fsdp2 = True
    if use_fsdp2:
        from transformers.fsdp import fully_shard, MixedPrecisionPolicy
        mp_policy = MixedPrecisionPolicy(
            param_dtype=torch.bfloat16, 
            reduce_dtype=torch.float32, 
            cast_forward_inputs=True
        )
        for layer in model.model.layers:
            fully_shard(layer, mp_policy=mp_policy)
        fully_shard(model, mp_policy=mp_policy)
    
    # which can lead to some experts not being activated on certain ranks
    train_dataset = getDataset()
    sampler = DistributedSampler(train_dataset, shuffle=False)
    # WORKAROUND: This configuration prevents the hang (forces same samples per DP rank)
    # sampler = DistributedSampler(train_dataset, rank=0, num_replicas=1, shuffle=False)
    
    train_dataloader = DataLoader(
        train_dataset,
        batch_size=1024,
        num_workers=1,
        drop_last=True,
        pin_memory=True,
        collate_fn=data_collator,
        sampler=sampler,
    )
    
    # Training setup
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)
    
    # Training loop that hangs during backward
    model.train()
    for step, batch in enumerate(train_dataloader):
        batch = {k: v.cuda(non_blocking=True) for k, v in batch.items()}
        
        outputs = model(**batch)
        loss = outputs.loss / 2  # Gradient accumulation steps
        loss.backward()  # HANGS HERE with FSDP2 when some experts aren't activated
        
        if step % 2 == 1:  # Gradient accumulation
            torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
            optimizer.step()
            optimizer.zero_grad()
        
        if rank == 0:
            print(f"Step {step} completed successfully")

if __name__ == "__main__":
    train()

Expected behavior

training will not get stuck

Description

We've encountered a critical issue when training Qwen3 MoE models with FSDP2 in transformers 4.53.2. The training process hangs during the backward pass under specific conditions.

Key observations:

  1. Training hangs during backward pass when using FSDP2 with MoE models
Image
  1. The issue does not occur when:

Suspected cause

We suspect PR #38133 introduced a change that causes FSDP2 to hang when some experts in MoE layers are not activated during forward pass. When certain experts receive no tokens (zero activation), FSDP2's gradient synchronization mechanism appears to deadlock during backward pass.

Questions for Maintainers cc @seven-mile @ArthurZucker

  1. Is this a known FSDP2 + MoE limitation?
  2. Should FSDP2 handle unused experts gracefully? (Or is this a bug?)
    Would a PR to modify expert masking or adjust FSDP2 sync logic help?

Offer to Help

I’m happy to test fixes or collaborate on a PR with guidance!
Let me know how I can assist!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions