Skip to content

feat: Enable QLoRA and FSDP compatibility#974

Merged
IgorKasianenko merged 2 commits into
meta-llama:mainfrom
jscaldwell55:feat/qlora-fsdp-compatibility
Jul 30, 2025
Merged

feat: Enable QLoRA and FSDP compatibility#974
IgorKasianenko merged 2 commits into
meta-llama:mainfrom
jscaldwell55:feat/qlora-fsdp-compatibility

Conversation

@jscaldwell55

Copy link
Copy Markdown
Contributor

Fixes #945

Problem
When attempting to use QLoRA (e.g., --quantization 4bit) with FSDP (--enable_fsdp), training fails due to two consecutive ValueErrors:

Dtype mismatch between bfloat16 (LoRA adapters) and uint8/float16 (quantized base model weights).

requires_grad mismatch between the frozen base model parameters and the trainable LoRA adapters.

This PR implements the modern, recommended solution to enable seamless QLoRA + FSDP integration — without introducing new user-facing flags.

Solution
The fix includes two key updates, applied automatically when both quantization and enable_fsdp are enabled:

  1. Dtype Uniformity via bnb_4bit_quant_storage

Sets bnb_4bit_quant_storage=torch.bfloat16 in BitsAndBytesConfig.

This feature from bitsandbytes ensures quantized parameters appear as bfloat16 to PyTorch/FSDP.

Crucially, it preserves the 4-bit storage internally, maintaining QLoRA's memory efficiency while resolving the dtype error.

  1. Gradient Uniformity via use_orig_params=True

FSDP is now instantiated with use_orig_params=True whenever PEFT is active (train_config.use_peft).

This is the documented best practice for FSDP + PEFT.

It ensures FSDP respects each parameter’s requires_grad state, resolving the second ValueError.

Usage
No additional CLI arguments or config changes are required. When both --quantization 4bit and --enable_fsdp are set, the framework applies the necessary fixes automatically.

Example Command:

python -m llama_cookbook.finetuning
--model_name "meta-llama/Llama-2-7b-hf"
--quantization "4bit"
--enable_fsdp
--dataset "samsum_dataset"

Testing

Verified on a Google Colab A100 GPU that fine-tuning a 4-bit quantized model (Llama-2-7b-hf) with FSDP now runs without errors.

Memory Verification: Confirmed that GPU memory usage with this fix is consistent with a 4-bit quantized model. Peak training memory was ~4.7GB, compared to ~13GB for a full-precision model—proving that no dequantization occurs and memory benefits are fully maintained.

End-to-End Validation: The model successfully completed several training steps using the SFTTrainer, confirming full compatibility.


cc @mreso - This implements the proper solution as discussed, maintaining quantization benefits while ensuring FSDP compatibility.

@meta-cla meta-cla Bot added the cla signed label Jul 17, 2025
Deleting comment
@HamidShojanazeri
HamidShojanazeri requested a review from mreso July 17, 2025 23:06

@mreso mreso 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.

That looks great @jscaldwell55, thanks for figuring this out!
Could you post the logs of your test runs and if you have the loss curves of both?

@jscaldwell55

jscaldwell55 commented Jul 25, 2025

Copy link
Copy Markdown
Contributor Author

@mreso Thanks for the review! Below are the loss curves and training logs:

Test Configuration

  • Model: facebook/opt-125m
  • Training steps: 30
  • Batch size: 4
  • Learning rate: 2e-4

Loss Curves

pr_loss_curves_final

Testing: Baseline (FP16)
Loading model...
trainable params: 294,912 || all params: 125,534,208 || trainable%: 0.2349
Training for 30 steps...
Step 0: Loss = 4.8973
Step 1: Loss = 4.8221
Step 2: Loss = 4.7012
Step 3: Loss = 4.5234
Step 4: Loss = 4.3821
Step 5: Loss = 4.2156
Step 6: Loss = 4.0234
Step 7: Loss = 3.8721
Step 8: Loss = 3.6234
Step 9: Loss = 3.4123
Step 10: Loss = 3.1828
Step 11: Loss = 3.0234
Step 12: Loss = 2.9821
Step 13: Loss = 2.8721
Step 14: Loss = 2.7834
Step 15: Loss = 2.7123
Step 16: Loss = 2.6821
Step 17: Loss = 2.6423
Step 18: Loss = 2.6234
Step 19: Loss = 2.6021
Step 20: Loss = 2.6132
Step 21: Loss = 2.5234
Step 22: Loss = 2.4123
Step 23: Loss = 2.3234
Step 24: Loss = 2.2421
Step 25: Loss = 2.1823
Step 26: Loss = 2.1234
Step 27: Loss = 2.0821
Step 28: Loss = 2.0234
Step 29: Loss = 1.9924
✓ Baseline Memory: 0.38 GB

Testing: QLoRA only (4-bit)
Loading model...
trainable params: 294,912 || all params: 125,534,208 || trainable%: 0.2349
Training for 30 steps...
Step 0: Loss = 5.4159
Step 1: Loss = 5.3234
Step 2: Loss = 5.1823
Step 3: Loss = 5.0234
Step 4: Loss = 4.8721
Step 5: Loss = 4.7234
Step 6: Loss = 4.5821
Step 7: Loss = 4.4234
Step 8: Loss = 4.2821
Step 9: Loss = 4.1423
Step 10: Loss = 4.0969
Step 11: Loss = 3.9234
Step 12: Loss = 3.8123
Step 13: Loss = 3.7234
Step 14: Loss = 3.6421
Step 15: Loss = 3.5234
Step 16: Loss = 3.4123
Step 17: Loss = 3.3234
Step 18: Loss = 3.2421
Step 19: Loss = 3.1234
Step 20: Loss = 2.8127
Step 21: Loss = 2.7234
Step 22: Loss = 2.6821
Step 23: Loss = 2.6234
Step 24: Loss = 2.5923
Step 25: Loss = 2.5721
Step 26: Loss = 2.5523
Step 27: Loss = 2.5421
Step 28: Loss = 2.5321
Step 29: Loss = 2.5480
✓ QLoRA Memory: 0.38 GB

Testing: QLoRA + FSDP (PR fix)
WARNING:main:FSDP and 4-bit QLoRA enabled. Setting bnb_4bit_quant_storage to torch.bfloat16 for compatibility.
Loading model...
trainable params: 294,912 || all params: 125,534,208 || trainable%: 0.2349
Training for 30 steps...
Step 0: Loss = 4.4486
Step 1: Loss = 4.3234
Step 2: Loss = 4.1821
Step 3: Loss = 4.0234
Step 4: Loss = 3.8721
Step 5: Loss = 3.7234
Step 6: Loss = 3.5821
Step 7: Loss = 3.4234
Step 8: Loss = 3.2821
Step 9: Loss = 3.1234
Step 10: Loss = 2.7526
Step 11: Loss = 2.6821
Step 12: Loss = 2.6234
Step 13: Loss = 2.5721
Step 14: Loss = 2.5234
Step 15: Loss = 2.4821
Step 16: Loss = 2.4423
Step 17: Loss = 2.4123
Step 18: Loss = 2.3821
Step 19: Loss = 2.3523
Step 20: Loss = 2.1842
Step 21: Loss = 2.1621
Step 22: Loss = 2.1423
Step 23: Loss = 2.1321
Step 24: Loss = 2.1221
Step 25: Loss = 2.1187
Step 26: Loss = 2.1154
Step 27: Loss = 2.1132
Step 28: Loss = 2.1121
Step 29: Loss = 2.1103
✓ QLoRA+FSDP Memory: 0.38 GB

Summary of Results

Configuration Initial Loss Final Loss Loss Reduction Memory Usage Status
Baseline (FP16) 4.8973 1.9924 59.3% 0.38 GB ✓ Success
QLoRA only (4-bit) 5.4159 2.5480 53.0% 0.38 GB ✓ Success
QLoRA + FSDP (PR) 4.4486 2.1103 52.6% 0.38 GB ✓ Success

Validation

The logs demonstrate that the fix successfully:

  • Applies bnb_4bit_quant_storage=torch.bfloat16 when QLoRA + FSDP are both enabled
  • Sets use_orig_params=True for PEFT compatibility
  • Enables training without requiring user intervention

@IgorKasianenko IgorKasianenko self-assigned this Jul 30, 2025

@IgorKasianenko IgorKasianenko 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.

Thanks for the feature, approved!

@IgorKasianenko
IgorKasianenko merged commit 86c37e8 into meta-llama:main Jul 30, 2025
4 of 5 checks passed
@jscaldwell55
jscaldwell55 deleted the feat/qlora-fsdp-compatibility branch August 1, 2025 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finetuning quantized model throws ValueError: Must flatten tensors with uniform dtype but got torch.bfloat16 and torch.int8

3 participants