The parent note gave you the formulas. This page makes you use them until every corner is boring. We enumerate every kind of question these formulas can be asked — then work one example per corner. When you finish, no LoRA sizing/memory/scaling question can surprise you.
Everything here builds on LoRA and QLoRA (parent). If a term is new, check Matrix Rank and Low-Rank Approximation , Quantization of Neural Networks , Adam Optimizer memory cost , or Full Fine-Tuning vs PEFT .
Every LoRA/QLoRA numeric question falls into one of these cells . We will hit each one.
Cell
What varies
The question it answers
C1 Param count, square
d = k
How many trainable params for one square projection?
C2 Param count, rectangular
d = k
Does the formula still hold when shapes differ?
C3 Degenerate rank r = 1
smallest useful rank
What is the leanest LoRA possible?
C4 Limiting rank r = min ( d , k )
rank saturates
When does LoRA stop saving anything?
C5 Scaling factor α / r
change r , hold α
How does effective update strength move?
C6 Full-FT optimizer memory
Adam on all params
Why is full fine-tuning so heavy?
C7 QLoRA base storage
4-bit frozen weights
How small does the base get?
C8 Real-world sizing (word problem)
pick a GPU
Does a whole run fit in this card?
C9 Exam twist
mixed / trap
Apply LoRA to a subset of layers, count everything
Recall The three formulas everything below uses
Trainable params per matrix ::: r ( d + k )
Effective update scale ::: r α
Bytes/param at b bits ::: b /8
An attention output projection is d = k = 4096 . Apply rank-8 LoRA. How many trainable parameters?
Forecast: guess before reading — is it closer to 60 thousand or 6 million?
Identify the two thin matrices. B ∈ R 4096 × 8 and A ∈ R 8 × 4096 .
Why this step? LoRA never stores the full Δ W ; it only ever stores B and A (see Matrix Rank and Low-Rank Approximation ).
Add their sizes. r ( d + k ) = 8 ( 4096 + 4096 ) = 8 × 8192 = 65 , 536 .
Why this step? B has d ⋅ r entries, A has r ⋅ k entries; sum = r ( d + k ) .
Compare to full. Full Δ W = 409 6 2 = 16 , 777 , 216 .
Why this step? This is the number LoRA is avoiding .
Verify: ratio = 65536/16777216 = 0.0039 = 0.39% — a 256 × reduction. Matches the parent's headline "256×". ✓
A down-projection in an MLP block is d = 4096 , k = 11008 (a real Llama-style shape). Rank r = 16 . Trainable params?
Forecast: with two very different dimensions, does the smaller or the larger one dominate?
Plug into r ( d + k ) . 16 ( 4096 + 11008 ) = 16 × 15104 .
Why this step? The formula is symmetric in d and k — it does not care which is bigger, it just adds them.
Multiply. 16 × 15104 = 241 , 664 .
Why this step? Straight arithmetic.
Sanity vs full. Full = d ⋅ k = 4096 × 11008 = 45 , 088 , 768 .
Why this step? Confirms LoRA still crushes the count when shapes are lopsided.
Verify: ratio = 241664/45088768 = 0.00536 = 0.54% . Both dimensions contribute linearly, so the bigger one (k ) contributes more of the LoRA cost — but both stay cheap. ✓
Same d = k = 4096 layer, but r = 1 . This is a single outer product Δ W = b a ⊤ (one column times one row). Params?
Forecast: r = 1 is the smallest LoRA that does anything. How tiny is it?
Apply formula. r ( d + k ) = 1 ( 4096 + 4096 ) = 8192 .
Why this step? B becomes a single column vector (4096 × 1 ), A a single row vector (1 × 4096 ).
Interpret geometrically. Δ W can now only push the model along one rank-1 direction.
Why this step? A rank-1 matrix is exactly one outer product — the most restricted non-trivial update (see figure).
Verify: 8192 params vs full 16 , 777 , 216 = 0.049% . As r → smallest, savings → largest. This is the floor of LoRA cost. ✓
d = k = 4096 . What if someone sets r = 4096 — the maximum possible rank?
Forecast: at maximum rank, is LoRA still saving anything? Guess yes/no.
Compute LoRA params. r ( d + k ) = 4096 ( 4096 + 4096 ) = 4096 × 8192 = 33 , 554 , 432 .
Why this step? Push the formula to its limit to expose where it breaks even.
Compare to full. Full = 409 6 2 = 16 , 777 , 216 .
Why this step? We need the crossover.
Read the ratio. 33554432/16777216 = 2.0 — LoRA now costs twice as much as just training Δ W directly!
Why this step? Because B A stores two full-size matrices to represent what one matrix could hold. At full rank the factorization is pure overhead.
Verify: LoRA only saves when r ( d + k ) < d k , i.e. r < d + k d k . For d = k = 4096 : r < 2048 . At r = 4096 we blew past that, so cost doubled. ✓ (This is why the whole method insists r ≪ min ( d , k ) .)
A run uses α = 16 , r = 8 . A teammate raises rank to r = 32 for "more capacity" but leaves α = 16 . By what factor did the effective update strength change?
Forecast: stronger, weaker, or unchanged?
Old scale. α / r = 16/8 = 2 .
Why this step? α / r is the actual multiplier on B A x in the forward pass — the true "volume knob".
New scale. α / r = 16/32 = 0.5 .
Why this step? α was held fixed, r quadrupled.
Ratio. 0.5/2 = 0.25 .
Why this step? The update is now 4 1 as strong — the run will "feel weaker" despite more parameters.
Verify: the rule of thumb α ≈ 2 r would have set α = 64 at r = 32 , giving α / r = 2 again — restoring the original strength. So the fix is to bump α with r . ✓
A 7 B model, full fine-tuning with Adam in fp32. How much memory just for optimizer state + master weights + gradients?
Forecast: guess in GB before computing. (Hint: it is not the model's own 14 GB.)
Count Adam's copies. fp32 master weights (4 B) + gradient (4 B) + momentum m (4 B) + variance v (4 B) = 16 B/param.
Why this step? Adam keeps two moving averages plus a master copy; see Adam Optimizer memory cost .
Multiply. 7 × 1 0 9 × 16 = 1.12 × 1 0 11 bytes.
Why this step? Total per-param cost times parameter count.
Convert to GB. 1.12 × 1 0 11 /1 0 9 = 112 GB (using 1 0 9 bytes/GB).
Why this step? Human-readable — and clearly won't fit a consumer GPU.
Verify: the parent quoted "7 B × 12 B ≈ 84 GB" using 12 B/param (dropping the separate gradient copy). With the fuller 16 B accounting we get 112 GB. Either way it's tens of GB of pure optimizer overhead — the whole reason PEFT exists (Full Fine-Tuning vs PEFT ). ✓
Store the same 7 B base in NF4 (4-bit). How many GB?
Forecast: the fp16 base is 14 GB. Quarter it?
Bytes per param. 4 bits = 4/8 = 0.5 B.
Why this step? Storage = bits/8 (see Quantization of Neural Networks ).
Multiply. 7 × 1 0 9 × 0.5 = 3.5 × 1 0 9 B.
Why this step? Only the frozen base is quantized; adapters stay full precision but are tiny.
Convert. 3.5 × 1 0 9 /1 0 9 = 3.5 GB.
Why this step? This is what actually sits in GPU memory for the base.
Verify: fp16 base = 7 × 1 0 9 × 2 = 14 GB; ratio 3.5/14 = 0.25 — exactly 4 × smaller, as "4-bit vs 16-bit" demands. ✓
Worked example Cell C8 (word problem)
You have a single 24 GB GPU. You want to QLoRA-tune a 7 B model with rank-16 adapters on the Q and V projections of 32 layers, each projection d = k = 4096 . Add up base + adapters + adapter optimizer state. Does it fit?
Forecast: yes or no — and what dominates the budget?
Base (NF4). From C7: 3.5 GB.
Why this step? Frozen 4-bit base is the biggest single chunk.
Adapter params. Per matrix r ( d + k ) = 16 × 8192 = 131 , 072 . Matrices = 2 ( Q,V ) × 32 layers = 64 . Total = 131072 × 64 = 8 , 388 , 608 ≈ 8.39 M.
Why this step? Count all injected matrices, not just one (this is the exam trap — don't forget the layer multiplier).
Adapter memory (bf16 weights + Adam). Weights 2 B + gradient 2 B + m , v in fp32 4 + 4 B ≈ 12 B/param. 8.39 × 1 0 6 × 12 = 1.01 × 1 0 8 B ≈ 0.10 GB.
Why this step? Only adapters carry optimizer state — this is the whole saving.
Sum. 3.5 + 0.10 ≈ 3.6 GB (before activations).
Why this step? Compare to the 24 GB budget.
Verify: 3.6 GB ≪ 24 GB — fits with enormous headroom for activations. The base dominates , not the adapters. Contrast C6's 112 GB for full FT: QLoRA turns an impossible run into a comfortable one. ✓
Worked example Cell C9 (exam-style)
Twist: "A 13 B model has 40 layers. Rank-8 LoRA is applied to Q , K , V , O (four projections, each 5120 × 5120 ) in only the top 20 layers . Give trainable params and the fraction of the full model." Watch the traps: subset of layers, four projections, 13 B total.
Forecast: more or less than 1% of the model?
Per-matrix count. r ( d + k ) = 8 ( 5120 + 5120 ) = 8 × 10240 = 81 , 920 .
Why this step? Base unit before multiplying by how many matrices we touch.
How many matrices? 4 projections × 20 layers = 80 matrices.
Why this step? The trap: "top 20 of 40", not all 40 — halve the layer count.
Total trainable. 81920 × 80 = 6 , 553 , 600 ≈ 6.55 M.
Why this step? Sum over every touched matrix.
Fraction of full model. 6.5536 × 1 0 6 /13 × 1 0 9 = 5.04 × 1 0 − 4 .
Why this step? Express as a share so it's comparable across models.
Verify: 5.04 × 1 0 − 4 = 0.0504% ≈ 0.05% of the model is trainable — well under 1% , right in LoRA's usual < 1% band. If a student forgot the "top 20" and used 40 layers they'd get 13.1 M (0.10% ) — double the correct answer. Read the fine print! ✓
Mnemonic The two questions every LoRA problem is secretly asking
"How many little matrices, and how strong is each push?"
Count = r ( d + k ) × ( matrices ) . Strength = α / r . Everything else is bytes-per-param bookkeeping.
Recall Quick self-test
LoRA stops saving memory when r exceeds what value (for d = k )? ::: r = d + k d k = 2 d — beyond it, r ( d + k ) > d k .
In the C8 budget, which term dominates? ::: The 4-bit frozen base (3.5 GB), not the adapters (0.1 GB).
Raising r from 8 to 32 with fixed α changes update strength by what factor? ::: × 0.25 (quartered).