Skip to content

[fsdp] fix: shard LoRA modules separately to prevent dtype mismatch errors with FSDP2 - #4275

Open
xxnpark wants to merge 1 commit into
verl-project:mainfrom
xxnpark:fix/lora-fsdp2
Open

xxnpark wants to merge 1 commit into
verl-project:mainfrom
xxnpark:fix/lora-fsdp2

Conversation

@xxnpark

@xxnpark xxnpark commented Nov 24, 2025

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes #3470

Currently, when the base model is loaded in a dtype other than fp32, its parameters end up in a different dtype than the LoRA adapters (since we do not set autocast_adapter_dtype=False and the adapter parameters are cast to fp32 by default). With FSDP1, the wrapping policies for base model modules and LoRA modules are handled separately, so this mismatch does not cause issues. For FSDP2, however, there is no equivalent handling, and base model parameters and LoRA parameters can end up under the same FSDP wrapper, leading to dtype mismatch errors. This PR fixes this issue.

Checklist Before Starting

  • Search for similar PRs. Paste at least one query link here: https://github.com/volcengine/verl/pulls?q=is%3Apr+is%3Aopen+FSDP2
  • Format the PR title as [{modules}] {type}: {description} (This will be checked by the CI)
    • {modules} include fsdp, megatron, sglang, vllm, rollout, trainer, ci, training_utils, recipe, hardware, deployment, ray, worker, single_controller, misc, perf, model, algo, env, tool, ckpt, doc, data
    • If this PR involves multiple modules, separate them with , like [megatron, fsdp, doc]
    • {type} is in feat, fix, refactor, chore, test
    • If this PR breaks any API (CLI arguments, config, function signature, etc.), add [BREAKING] to the beginning of the title.
    • Example: [BREAKING][fsdp, megatron] feat: dynamic batching

Test

Running python -m verl.trainer.main_ppo with actor_rollout_ref.actor.strategy=fsdp2 and actor_rollout_ref.actor.fsdp_config.model_dtype=bfloat16 in the current main branch gives the error:

AssertionError: FSDP expects uniform original parameter dtype but got {torch.float32, torch.bfloat16}

but it runs well in this branch.

API and Usage Example

No API changes.

Design & Code Changes

This change updates the FSDP2 wrapping logic to explicitly identify LoRA modules and shard them separately from the base model modules.

Checklist Before Submitting

Important

Please check all the following items before requesting a review, otherwise the reviewer might deprioritize this PR for review.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses a dtype mismatch error that occurs with FSDP2 when LoRA adapters are used with a base model loaded in a precision other than fp32. The core of the change is in verl/utils/fsdp_utils.py, where the apply_fsdp2 function is updated to differentiate between LoRA modules and base model transformer layers. By introducing an is_lora flag, the logic now separates trainable leaf modules (like LoRA adapters) and shards them independently before sharding the main transformer blocks. This prevents parameters with different data types from being grouped under the same FSDP wrapper, which was the source of the error. The changes are logical, well-targeted, and consistently applied across all call sites. The fix appears to be correct and should resolve the reported issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FSDP2 with LoRA training throws dtype mismatch error

1 participant