Scaling DoRA: High-Rank Adaptation via Factored Norms and Fused Kernels
Abstract
Weight-Decomposed Low-Rank Adaptation (DoRA) extends LoRA by decoupling weight magnitude from direction, but its forward pass requires the row-wise norm of W + sBA, a computation that every major framework we surveyed implements by materializing the dense [d_out, d_in] product BA. At d_in = 8192 and rank r = 384, a single module's norm requires about 512 MB of transient working memory in bf16, making high-rank DoRA costly and often infeasible on common single-GPU setups once hundreds of adapted modules and checkpointing are involved. We present two systems contributions. A factored norm decomposes the squared norm into base, cross, and Gram terms computable through O(d_out r + r^2) intermediates, eliminating the dense product. Fused Triton kernels collapse the four-kernel DoRA composition into a single pass, reducing memory traffic by about 4x and using a numerically stable form that avoids catastrophic cancellation in the near-unity rescaling regime where magnitude scales concentrate in practice. Across six 8-32B vision-language models (VLMs) on three NVIDIA GPUs (RTX 6000 PRO, H200, B200) at r = 384 in bf16, the fused implementation is 1.5-2.0x faster than Hugging Face PEFT's DoRA implementation for inference and 1.5-1.9x faster for gradient computation (optimizer step excluded), with up to 7 GB lower peak VRAM. Microbenchmarks on six GPUs spanning four architecture generations (L40S, A100, RTX 6000 PRO, H200, B200, B300) confirm 1.5-2.7x compose-kernel speedup. Final-logit cosine similarity exceeds 0.9999 across all model/GPU pairs, and multi-seed training curves match within 7.1 x 10^-4 mean per-step loss delta over 2000 steps.
Figures & tables
| PEFT | Factored (ours) | |
| Rank-dependent persistent | ||
| Chunk buffer (transient) | Included above | per chunk † |
| Per-module temps | 3–4 dense | + |
| Identity matrix | Every forward call | Never created |
| Concrete : , , fp32 | ||
| Theory: dense (B@A) | 256 MB | N/A |
| Tier | Path | When | Tradeoff |
|---|---|---|---|
| 1 | Fused Backward | Training + CUDA + Triton + auto-gate/force-on | Fastest above crossover; saves inner for bwd |
| 2 | Fused Forward | Inference + CUDA + Triton | Speed without bwd memory |
| 3 | Eager Fallback | CPU / no Triton / force-off / sub-crossover | Universal compatibility |
| GPU | Arch | Memory | BW (TB/s) | Scope |
|---|---|---|---|---|
| L40S | SM89 Ada | 48 GB GDDR6 | 0.86 | Micro |
| A100-SXM4 | SM80 Ampere | 80 GB HBM2e | 2.04 | Micro |
| RTX 6000 PRO | SM120 Blackwell | 96 GB GDDR7 | 1.60 | Micro+Model |
| H200 | SM90 Hopper | 141 GB HBM3e | 4.80 | Micro+Model |
| B200 | SM100 Blackwell | 192 GB HBM3e | 7.70 | Micro+Model |
| B300 | SM103 Blackwell | 268 GB HBM3e | 7.70 | Micro |
| Speedup vs. PEFT DoRA | Speedup vs. Eager | |||||
|---|---|---|---|---|---|---|
| Model | RTX | H200 | B200 | RTX | H200 | B200 |
| Qwen2.5-VL-32B | OOM | 1.73× | 1.74× | OOM | 1.20× | 1.22× |
| Qwen3-VL-32B | OOM | 1.66× | 1.67× | OOM | 1.18× | 1.21× |
| Qwen3.5-27B | 1.51× | 1.57× | 1.57× | 1.22× | 1.21× | 1.23× |
| Gemma3-27B | 1.53× | 1.61× | 1.56× | 1.20× | 1.19× | 1.21× |
| Mistral-Sm-24B | 1.66× | 1.87× | 1.87× | 1.22× | 1.21× | 1.23× |
| Fused (s) | Eager (s) | PEFT (s) | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Model | RTX | H200 | B200 | RTX | H200 | B200 | RTX | H200 | B200 |
| Qwen2.5-VL-32B | OOM | 30.9 | 23.3 | OOM | 37.1 | 28.5 | OOM | 53.6 | 40.4 |
| Qwen3-VL-32B | OOM | 33.4 | 25.4 | OOM | 39.5 | 30.6 | OOM | 55.4 | 42.3 |
| Qwen3.5-27B | 39.5 | 25.4 | 19.4 | 48.1 | 30.6 | 23.9 | 59.5 | 39.8 | 30.5 |
| Gemma3-27B | 41.6 | 27.5 | 21.4 | 50.0 | 32.7 | 25.8 | 63.6 | 44.1 | 33.4 |
| Mistral-Sm-24B | 32.5 | 20.9 | 15.9 | 39.7 | 25.2 | 19.6 | 53.9 | 39.1 | 29.8 |
| vs. PEFT DoRA | vs. Eager | ||||
|---|---|---|---|---|---|
| Model | Rank | Grad. | Infer. | Grad. | Infer. |
| Qwen3.5-27B | 384 | 1.57× | 1.65× | 1.21× | 1.16× |
| 512 | 1.61× | 1.68× | 1.18× | 1.14× | |
| 768 | 1.53× | 1.59× | 1.15× | 1.11× | |
| Qwen3-VL-32B | 384 | 1.66× | 1.78× | 1.18× | 1.14× |
| 512 | 1.70× | 1.82× | 1.16× | 1.12× | |
| Shape | Rank | PEFT | Factored | Meas. × | Theory × |
|---|---|---|---|---|---|
| 64 | 192 MB | 65 MB | 3.0× | 63× | |
| 384 | 192 MB | 71 MB | 2.7× | 9.8× | |
| 512 | 192 MB | 73 MB | 2.6× | 7.1× | |
| 384 | 768 MB | 245 MB | 3.1× | 20.4× | |
| 512 | 768 MB | 241 MB | 3.2× | 15.1× | |
| 768 | 768 MB | 236 MB | 3.2× | 9.8× |
| Model | Method | RTX | H200 | B200 |
|---|---|---|---|---|
| Qwen2.5-VL-32B | Eager | OOM | 99.2 | 99.2 |
| Fused | OOM | 98.4 | 98.4 | |
| Dense (B@A) | OOM | 100.6 | 100.6 | |
| PEFT | OOM | 103.5 | 103.5 | |
| Mistral-Sm-24B | Eager | 71.6 | 71.7 | 71.6 |
| Fused | 70.6 | 70.7 | 70.6 |
| Compose fwd | Backward | E2E | Norm mem | |
| L40S bf16 | 1.47× | 1.06× | 1.05× | 0.8× |
| A100 bf16 | 1.73× | 1.16× | 1.07× | 0.8× |
| RTX 6000 PRO bf16 | 1.92× | 1.22× | 1.08× | 0.8× |
| H200 bf16 | 2.00× | 1.08× | 1.06× | 0.8× |
| B200 bf16 | 2.70× | 1.23× | 1.08× | 0.8× |
| B300 bf16 | 2.62× | 1.22× | 1.08× | 0.8× |
| Seed | Steps | Mean | Max | Eval | Wall (fused/eager) |
| 1 | 2000 | 330/362 min | |||
| 2 | 2000 | 330/359 min | |||
| 3 | 2000 | 330/359 min | |||
| Grand mean | — | 330/360 min | |||
| Scenario | Config | Rationale |
|---|---|---|
| Training, CUDA, above crossover | Tier 1 (fused bwd) | Full speedup; 0.1–1.0 GB less VRAM than eager |
| Training, memory-constrained | Tier 1 + frozen mag | inner skipped; lower peak VRAM |
| Inference, CUDA | Tier 2 (fused fwd) | Compose speedup, no backward memory |
| CPU / no Triton | Tier 3 (eager) | Automatic fallback |
| , any single GPU | Factored norm | PEFT path 46–87% slower |
| , | Either norm | Factored overhead minimal |
Appendix figures & tables7 assets
Supplementary material from the paper’s appendix.
Appendix
| Feature | Status | Scope | Notes |
|---|---|---|---|
| Mixed-precision bf16 | ✓ | Bench+Conv | All model benchmarks and convergence runs |
| Mixed-precision fp16 | ✓ | CI | Operator tests only; no model-level fp16 runs |
| Gradient checkpointing | ✓ | Bench+Conv | All model benchmarks use gradient checkpointing |
| ZeRO-2 | ✓ | Conv | All convergence runs use ZeRO-2 |
| ZeRO-3 | ✓ | CI | Parameter gathering tested; no model-level runs |
| FSDP1 | ✓ | CI | summon_full_params path tested |
| Model | Method | RTX 6000 PRO | H200 | B200 |
|---|---|---|---|---|
| Qwen2.5-VL-32B | Eager | OOM | 99.2 | 99.2 |
| Fused | OOM | 98.4 | 98.4 | |
| Dense (B@A) | OOM | 100.6 | 100.6 | |
| PEFT | OOM | 103.5 | 103.5 | |
| Qwen3-VL-32B | Eager | OOM | 99.2 | 99.1 |
| Fused | OOM | 98.4 | 98.4 |
| Compose fwd | Backward | E2E | Norm mem | |
|---|---|---|---|---|
| L40S fp32 | 1.53× | 1.21× | 1.04× | 3.2× |
| A100 fp32 | 1.64× | 1.20× | 1.02× | 3.2× |
| RTX 6000 PRO fp32 | 1.97× | 1.27× | 1.06× | 3.2× |
| H200 fp32 | 1.84× | 1.13× | 1.03× | 3.2× |
| B200 fp32 | 2.35× | 1.26× | 1.03× | 3.2× |
| B300 fp32 | 2.23× | 1.21× | 1.03× | 3.2× |
| Framework | Version | File Path | Pattern |
|---|---|---|---|
| HF PEFT | 20a9829 | peft/tuners/lora/dora.py | torch.eye |
| torchtune | v0.5.0 | modules/peft/dora.py | Same algorithm |
| Unsloth | 2026.3.7 | Disables custom kernels | Falls back to PEFT |
| SWIFT (ms-swift) | a807cb9 | Defers to PEFT/Unsloth | No custom code |
| LLaMA-Factory | v0.9.3 | Delegates to PEFT | No custom code |
| Axolotl | v0.6.0 | Delegates to PEFT | No custom code |
Low-Rank Adaptation
Low-rank adaptation (LoRA) fine-tunes pretrained models with compact weight updates, reducing trainable parameters and deployment costs.
See all 542 papers