Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

~8 min readUW · 2023

QLoRA,
explained.

In early 2023, fine-tuning a 65B model meant renting a cluster: over 780 GB of GPU memory, out of reach for almost everyone. Then one paper stacked three memory tricks — a smarter 4-bit number format, quantizing the quantization itself, and paging optimizer spikes to CPU — under ordinary LoRA adapters. Suddenly the same job fit on one 48 GB card, with no measurable quality loss. Open-source fine-tuning dates from this paper.

The delta

What changes against LoRA: the frozen base gets much smaller too

LoRA removes the optimiser state and leaves one cost untouched: the frozen base model still has to sit in accelerator memory, at sixteen bits per parameter, for the forward and backward passes to happen at all. For a large model that is the whole budget, so "cheap fine-tuning" still meant renting a cluster.

The change is to quantise the frozen base to four bits and backpropagate straight through it into the adapters. The reason this is sound rather than reckless is worth stating precisely, because it is the conceptual core: the quantised weights are never updated. A quantised weight that you train would accumulate rounding error step after step; a quantised weight that is frozen is just a fixed distortion of the original function, and the adapters — which are trained in full precision — can learn to compensate for it. Gradients pass through the quantised weights to reach the adapters without ever being applied to them.

Three pieces make the four bits survivable, and each targets a specific leak. The data type is chosen so that its quantisation levels match the distribution weights actually have — approximately normal and centred on zero — rather than being spaced uniformly, which would waste most of sixteen available levels on ranges few weights occupy. The per-block scaling constants are themselves quantised a second time, because at four bits the metadata is no longer negligible against the data. And optimiser state is paged to host memory so a transient spike fails slowly instead of fatally. Stated in units: a 65B-parameter fine-tune on a single GPU.

01

Why fine-tuning was out of reach

Training memory isn't just weights. Full fine-tuning with AdamW holds the 16-bit weights, 16-bit gradients, and two 32-bit optimizer states — roughly 16 bytes per parameter before activations. For a 65B model that's north of a terabyte; even LoRA, which shrinks gradients and optimizer state to almost nothing, still needs the frozen base model resident in 16-bit: 130 GB for 65B. The adapters were cheap; the statue they wrapped around was not.

The obvious move — store the frozen base in 4-bit — had an obvious objection: everyone "knew" 4-bit was for inference, and training through quantized weights would degrade everything. QLoRA's contribution is showing that with the right data type and plumbing, the objection is wrong.

02

The stack: 4-bit statue, 16-bit clay

QLoRA freezes the base model in 4-bit NF4 and trains 16-bit LoRA adapters on top. During each forward/backward pass, the touched 4-bit weights are dequantized to 16-bit on the fly, used, and discarded — gradients flow through the frozen quantized weights but are only applied to the adapters.

One training step through a quantized base
NF4 base
frozen, 0.5 B/param
→
Dequantize on the fly
16-bit compute
→
LoRA adapters
16-bit, trainable
↺
Gradients hit
adapters only
The key idea

Precision matters where learning happens, not where knowledge sits. The frozen base is a lookup — compress it hard. The adapters are the part being sculpted — keep them in full precision. Any quantization error in the base is systematic, and the adapters learn around it.

03

NF4: a number format shaped like weights

Sixteen levels is all 4 bits buy you. Spend them evenly across the range (like INT4 does) and you waste levels where weights are rare. Neural weights are approximately normally distributed — bunched near zero, thin tails — so QLoRA's NormalFloat-4 places its 16 levels at the quantiles of a normal distribution: each level owns an equal share of the actual weights.

It's the information-theoretic answer to "where do I put 16 points to describe a bell curve?" — dense levels where weights crowd, sparse levels in the tails. In ablations, NF4 beat standard FP4 consistently — the difference between 4-bit-that-degrades and 4-bit-that-doesn't.

04

Double quantization: compress the compressor

Block-wise quantization stores a scale constant per block of weights — and at QLoRA's small block size (64, chosen for accuracy), those 32-bit constants add up: ~0.5 bits per parameter of pure overhead, gigabytes at 65B scale. QLoRA's cheeky fix: quantize the quantization constants too — the per-block scales get their own 8-bit quantization with a second-level constant.

It saves ~0.37 bits/param — about 3 GB on a 65B model. Not glamorous, but it's the difference between fitting on the card and not. Systems papers are won in the decimals.

Watch the decimals add up. A 32-bit scale per 64-weight block is pure overhead on top of the 4 NF4 bits:

That 0.373-bit gap, multiplied across 65 billion parameters, is the 3 GB — and 3 GB is exactly the margin between "fits on a 48 GB card" and "doesn't." Put the whole frozen base on the scale next to a normal fine-tune:

The adapters and their optimizer state are ~1% of this and ride in the headroom — the frozen base was the whole memory problem.

05

Paged optimizers: surviving the spikes

Even with everything above, training memory spikes — a long sequence's activation checkpointing can momentarily demand gigabytes, and one spike OOMs an otherwise-fitting run. QLoRA uses paged optimizers: optimizer states live in unified memory that the NVIDIA driver pages between GPU and CPU on demand, like OS virtual memory. Spikes swap out; training hiccups instead of dying.

Together the three tricks turn "fits on average" into "fits, period" — the practical difference between a paper result and a tool people actually run overnight on one machine.

07

Why it still matters

QLoRA is why "fine-tune it on your own data" became a weekend project instead of an infrastructure program. Shipped into bitsandbytes and Hugging Face PEFT within weeks, it became — and remains — the default recipe behind most open-model fine-tunes you've ever downloaded. The NF4-frozen-base pattern also normalized a bigger idea: quantization isn't just a deployment trick, it's a training-time tool.

Conceptually it completed LoRA's argument. LoRA said: the update is low-rank, so shrink the training. QLoRA added: the base is redundant, so shrink the storage. Between them, the two papers cut fine-tuning's cost by orders of magnitude in each dimension — and the open-source model ecosystem is the compound interest.

Read next

The foundation: LoRA. The production context: the Fine-Tuning Handbook and the fine-tuning pipeline design. Check your own memory math with the GPU VRAM calculator.

How it works

How QLoRA stores, computes and trains, step by step

QLoRA stores the frozen base model in 4 bits, computes in 16 bits and trains LoRA adapters in 16 bits. Each piece below is specified exactly in the paper, and together they deliver the headline: fine-tuning a 65B model in under 48 GB of GPU memory, where regular 16-bit fine-tuning needs more than 780 GB.

pretrained weights, roughly normal NF4: levels at normal quantiles exact 0 evenly spaced levels, no exact zero −1 0 +1 weight ÷ block absmax
NF4 places its 16 levels at normal quantiles, so each level covers a similar share of the weights; evenly spaced levels spend resolution on the sparse tails.
  1. Build the NF4 code book. The 16 values come from quantiles of a standard normal distribution: each value averages two neighboring quantiles, and the set is normalized into [−1, 1]. To represent zero exactly, the negative and positive halves are estimated separately, 2^k−1 quantiles for the negative side and 2^k−1 + 1 for the positive side, and one of the two duplicate zeros is dropped. The result is 7 negative values, an exact 0 and 8 positive values.
  2. Quantize block by block. Each weight tensor is cut into blocks of 64. A block's absolute maximum rescales it into [−1, 1], and each weight is stored as the 4-bit index of the nearest NF4 value. Small blocks stop one outlier from crushing the resolution of many weights.
  3. Double-quantize the block constants. The per-block scales, one 32-bit float per 64 weights, are themselves quantized to 8-bit floats in blocks of 256 after subtracting their mean, with one 32-bit constant per block of scales. Overhead falls from 0.5 to about 0.127 bits per parameter.
  4. Dequantize on the fly and compute in BF16. In every forward and backward pass, the weights a layer needs are expanded from NF4 to BFloat16, used and discarded. Storage stays near 4.1 bits per parameter while the arithmetic is 16-bit.
  5. Put LoRA adapters on every linear layer. The adapters are BF16 and are the only trainable parameters. Computing their gradients requires backpropagating through the dequantized base weights, but no update is ever applied to those weights. Adapters on the query and value projections alone, the original LoRA default, did not match 16-bit fine-tuning on large models; adapters on all linear layers of each Transformer block did, and once they were everywhere the rank barely mattered. The chatbot runs used r = 64 and α = 16.
  6. Page the optimizer. Adam's states live in NVIDIA unified memory, which the driver moves to CPU RAM when the GPU runs short, so a long sequence's memory spike slows a step instead of ending the run.
  7. Train and evaluate at scale. LLaMA models from 7B to 65B were fine-tuned on eight instruction datasets: OASST1, HH-RLHF, Alpaca, Self-Instruct, Unnatural Instructions, FLAN v2, Chip2 and Longform. More than 1,000 models were trained in all, and the best chatbots, called Guanaco, were trained on OASST1.

The same arithmetic scales down. The 33B model trains on a single 24 GB consumer GPU in under 12 hours, and the deployed Guanaco 7B, still in 4 bits, needs about 5 GB of memory.

The math

The QLoRA forward pass and the NF4 levels

Y^BF16 = X^BF16 · doubleDequant(c1^FP32, c2^k-bit, W^NF4) + X^BF16 · L1^BF16 · L2^BF16
doubleDequant(c1, c2, W) = dequant( dequant(c1, c2), W^4bit ) = W^BF16
qi = ½ · [ QX( i / (2^k + 1) ) + QX( (i + 1) / (2^k + 1) ) ]
  • W^NF4 — the frozen base weights, stored as 4-bit indices into the NF4 code book.
  • c2 — the per-block absmax scales, one per 64 weights, stored as 8-bit floats; c1 — one 32-bit constant per 256 of those scales.
  • L1, L2 — the LoRA factors, the only trained tensors (the LoRA scale is left out here, as in the paper's own equation).
  • QX — the quantile function of the standard normal distribution; k = 4 bits.

At the extremes of block size: one weight per block would make quantization almost lossless but spend 32 bits of scale on every 4-bit weight, while one block per tensor would let a single large weight set the scale for millions of others and push most of them onto the levels nearest zero. Blocks of 64 are the compromise, and double quantization is what makes a block that small affordable.

The evidence

What QLoRA measured, and what it found

The paper first checked that 4-bit training loses nothing, by replicating 16-bit full fine-tuning and 16-bit LoRA on RoBERTa-large (GLUE) and T5 (Super-NaturalInstructions), then fine-tuned LLaMA 7B to 65B and measured MMLU and chatbot quality. Chatbots were judged on the 80-prompt Vicuna benchmark and on OASST1 prompts, by GPT-4 and by human raters, including an Elo tournament between systems.

MeasurementResult
Perplexity on Pile Common Crawl, by data typeInt4 34.34; FP4 31.07 and 29.48 (two variants); NF4 + DQ 27.41
Mean 5-shot MMLU after fine-tuningBF16 53.0; FP4 52.2; NF4 + DQ 53.1
Guanaco vs ChatGPT, Vicuna benchmark, GPT-4 judge65B 99.3%; 33B 97.8%; 13B 90.4%; 7B 87.0%
Elo with GPT-4 as judgeGPT-4 1348; Guanaco 65B 1022; Guanaco 33B 992; Vicuna 13B 974; ChatGPT 966
Hardware65B on one 48 GB GPU in about 24 hours; 33B on one 24 GB consumer GPU in under 12 hours

NF4 is what makes 4 bits safe: FP4 trailed the 16-bit baseline by about a point on MMLU, while NF4 with double quantization matched it. The data findings were less expected. A 9k-example OASST1 set beat a 450k-example FLAN v2 subset on chatbot quality, so suitability mattered more than size, and MMLU scores did not predict chatbot scores in either direction.

The ablations cut against defaults too. LoRA on only the query and value projections fell short of full fine-tuning on large models; adapters on all linear layers were required. And the evaluation instrument had biases the authors measured themselves: GPT-4 favored whichever system appeared first in its prompt, and it rated its own answers higher than human raters did, an Elo of 1348 from GPT-4 against 1176 from humans.

Since then

What the authors admit, and what happened next

The trade is acknowledged: dequantising weights on the fly makes each step slower than the same fine-tune in sixteen bits. This buys feasibility, not speed — the right comparison is against not being able to run at all.

The part that was contested is the evaluation rather than the method. The headline quality claims rested substantially on judgements by another language model and on preference benchmarks that were, at the time, new and not well understood. Later work documented systematic biases in model-as-judge evaluation — toward longer answers, toward a position in the comparison, toward outputs resembling the judge's own style. The technique's value did not depend on those numbers and has survived them, but "matches sixteen-bit fine-tuning" was measured with an instrument that was itself under review.

How it held up: four-bit base plus full-precision adapters is simply how local fine-tuning is done, and the distribution-matched data type and double quantisation were absorbed into the quantisation toolchain generally. The wider significance is who it moved: before this rung, adapting a large model required an organisation; after it, a person with one GPU. Most of what the open-weight ecosystem on the next ladder produced downstream of each release depended on this being possible.

SOLVE IT YOURSELF

Reproduce the 65B-on-one-GPU claim

QLoRA's headline is a memory-accounting result, so account for it. This computes, from first principles, why a 65B model that needs over a terabyte of state to fine-tune normally collapses to ~33 GB — small enough for a single 48 GB card. Watch NF4's 4 bits, the block-scale overhead, and double quantization's clever ~0.37-bit saving combine into the exact numbers the paper reports. Change the model size or block size and the whole budget recomputes.

YOUR TASK

Write the body of bits_per_param. Everything else in the file is already written; this is the function the paper is about. Press ▶ Run to check it against the 5 assertions below — they start red.

WHAT IT HAS TO SATISFY — 5 ASSERTIONS
  1. Full 16-bit fine-tuning a 65B model needs ~1 TB of state
  2. NF4 stores 4 bits per weight
  3. Double quantization saves ~0.37 bits per parameter
  4. That saving is ~3 GB on a 65B model
  5. QLoRA fits a 48GB card where full fine-tuning cannot
CPython · WebAssembly
Questions

Questions people ask about QLoRA

How is NF4 different from INT4 and FP4?

All three have 16 levels, because 4 bits allow only 16 values; they differ in where the levels sit. INT4 spaces them evenly across the range. FP4 uses a tiny exponent and mantissa, so levels are denser near zero but follow a fixed floating-point pattern. NF4, introduced in QLoRA, places its 16 levels at quantiles of a normal distribution scaled to the range from minus one to one, because pretrained weights are roughly normally distributed, so each level covers a similar share of the weights. It is built asymmetrically, with 7 negative values, an exact zero and 8 positive values. In the paper's tests NF4 gave lower perplexity than both and matched 16-bit fine-tuning on MMLU, where FP4 lost about a point.

Why does QLoRA put LoRA adapters on all linear layers?

Because that was what it took to match 16-bit fine-tuning. The original LoRA paper adapted only the attention query and value projections, which worked for GPT-3 on its tasks. When the QLoRA authors used that default on large LLaMA models with instruction data, the 4-bit models fell short of full 16-bit fine-tuning. Adding adapters to every linear layer in each Transformer block, including the attention output and the MLP projections, closed the gap. They also found that once adapters were everywhere, the rank mattered little, so the number of adapted matrices was the hyperparameter that counted. The Guanaco chatbots used rank 64 and alpha 16 on all linear layers.

How much GPU memory does QLoRA need?

The paper's headline is a 65B-parameter model fine-tuned in under 48 GB of GPU memory, down from more than 780 GB for regular 16-bit fine-tuning, on a single professional GPU in about a day. The 33B model trains on a 24 GB consumer GPU in under 12 hours. The frozen base costs about 4.127 bits per parameter with NF4 and double quantization, so a 7B base takes roughly 3.6 GB before activations, adapters and optimizer state, and the deployed Guanaco 7B needs about 5 GB. Activation memory grows with sequence length and batch size, which is why paged optimizers exist: they let occasional spikes spill into CPU memory instead of crashing the run.

Is QLoRA slower than ordinary LoRA?

Yes, per step. Every forward and backward pass has to dequantize the base weights it touches from 4-bit NF4 back to BFloat16 before multiplying, and that work is not free, so QLoRA trades speed for memory. The fair comparison is usually not 16-bit LoRA on the same GPU, because the 16-bit run often does not fit at all. Against a setup that needs several GPUs just to hold a 16-bit base, QLoRA on one GPU may be slower per step but far cheaper and simpler to run. If the 16-bit model fits comfortably in memory, plain LoRA will train faster.

Why did a 9k-example dataset beat a 450k-example one in QLoRA?

Because the smaller dataset matched the task. The OASST1 set the authors used has about 9,000 examples drawn from assistant conversations that volunteers wrote and ranked, which is exactly the kind of interaction a chatbot benchmark tests. The FLAN v2 subset had 450,000 examples, but they are mostly academic NLP tasks recast as instructions. On the Vicuna chatbot benchmark, models trained on OASST1 came out ahead, while FLAN v2 models did better on MMLU. The paper concluded that a dataset's suitability for the target behavior matters more than its size, and that a benchmark such as MMLU does not tell you how good a chatbot is.

Does double quantization hurt accuracy?

Not measurably in the paper's results. Double quantization compresses the scaling constants rather than the weights: the 32-bit scale stored for every 64 weights is itself quantized to an 8-bit float, in blocks of 256 with one 32-bit constant each. That cuts the overhead from 0.5 to about 0.127 bits per parameter, roughly 3 GB on a 65B model. The weights are still quantized against nearly the same scales, so the reconstruction barely changes, and the paper's NF4-plus-double-quantization setup matched 16-bit fine-tuning on MMLU, 53.1 against 53.0. Whatever double quantization costs in accuracy is too small to show in those results.

Check yourself

4 questions to test what you just read

Work each one out before you open it — a number, a prediction or a reason, not a definition. Producing the answer is what makes it stick. Your progress is kept on this device.

A 7B model is stored in NF4 with double quantization at 4.127 bits per parameter. Roughly how many gigabytes does the frozen base take, and how does that compare with 16-bit?

Show answer

7 × 10⁹ × 4.127 / 8 ≈ 3.6 GB, against 7 × 10⁹ × 2 bytes = 14 GB in 16-bit: about a 3.9× reduction for the weights alone, before activations, adapters and optimizer state.

The NF4 code book has 7 negative levels, an exact zero and 8 positive levels. Why not 8 and 8, symmetric around zero?

Show answer

Sixteen symmetric quantiles would put levels just above and below 0 but none at exactly 0, so zero-valued elements such as padding would be stored with error. QLoRA estimates 8 negative-side and 9 positive-side quantiles, each set ending at 0, merges them and drops the duplicate zero: 7 + 1 + 8 = 16 levels, with an exact zero.

What would you predict happens to the 4-bit codes of a 64-weight block if one weight is ten times larger than all the others?

Show answer

The outlier sets the block's absmax, so every other weight is rescaled to within about ±0.1 of zero, where NF4 has only a few levels (about −0.09, 0 and +0.08). Most of the block's precision is lost. Small 64-weight blocks confine that damage to one block, which is why QLoRA accepts the extra scaling constants and then shrinks them with double quantization.

GPT-4 judged Guanaco 65B at 99.3% of ChatGPT, but it favored whichever answer came first. How would you check a number like that?

Show answer

Score every pair twice with the answers swapped and average, so the order bias cancels, then compare with human raters. The paper ran human evaluations alongside GPT-4 and found GPT-4 also inflated its own outputs (Elo 1348 from GPT-4, 1176 from humans), so model-judged percentages are best read as rankings, not precise ratios.

Where this sits

Teaching a base model to follow

A pre-trained model completes text; it does not take instructions. Nine papers on getting from one to the other, from RLHF to a loss with no reward model in it.

  1. 1InstructGPT2022
  2. 2Constitutional AI2022
  3. 3Self-Instruct2023
  4. 4LoRA2022
  5. 5QLoRA2023
  6. 6Direct Preference Optimization2023
  7. 7GRPO2024
  8. 8STaR2022
  9. 9Let's Verify Step by Step2023

All 110 papers, in 19 ladders →

QLoRA: Efficient Finetuning of Quantized LLMs · Dettmers, Pagnoni, Holtzman, Zettlemoyer · University of Washington · 2023 · read the original paper on arXiv → · Vibe Engines · 2026
Finished this one? 0 / 110 Paper Breakdowns done
NextDirect Preference Optimization Next on the “Teaching a base model to follow” ladder · rung 6 of 9

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More Paper Breakdowns