Contents Working with Large Language Models Course home

Chapter 23Efficiency: Smaller, Cheaper, Faster

The other axis

Most of this book has followed capability. Larger models, longer contexts, better scores.

There is a second axis, and outside research it is usually the binding one. A model that cannot run within your budget, memory or latency is not available to you at any quality.

This chapter is about that axis. It divides cleanly into three questions.

How do I adapt a model without paying for full fine-tuning? How do I make the model smaller? How do I make it answer faster?

Adapting without paying for it

Full fine-tuning updates every weight, and the memory cost is worse than the parameter count suggests.

For a 77 billion parameter model in half precision:

what must be held memory
weights, fp16 14 GB
gradients, fp16 14 GB
Adam states, fp32 master and two moments 56 GB
total, before activations 84 GB

That is several high-end accelerators to fine-tune a model that fits on one for inference. And the result is a whole new 1414 GB of weights per task.

LoRA

Low-rank adaptation rests on one observation. The change a fine-tune makes to a weight matrix has low intrinsic rank, even though the matrix does not.

So do not learn the change directly. Factor it:

W=W+BA,Bd×r,Ar×k,rmin(d,k).(23.1)\begin{equation} W' \;=\; W \;+\; BA, \qquad B \in \mathbb{R}^{d \times r}, \quad A \in \mathbb{R}^{r \times k}, \quad r \ll \min(d, k). \label{eq:lora} \quad\text{(23.1)} \end{equation}

Freeze WW entirely. Train only AA and BB.

The arithmetic is the argument. A full matrix has dkdk parameters. The adapter has r(d+k)r(d + k).

rank rr full matrix adapter share
1 16,777,216 8,192 0.05%
4 16,777,216 32,768 0.20%
8 16,777,216 65,536 0.39%
16 16,777,216 131,072 0.78%
64 16,777,216 524,288 3.13%

Those figures are for d=k=4096d = k = 4096, a typical attention projection.

At r=8r = 8 you train four tenths of one per cent of the weights. The optimiser state shrinks in the same proportion, which is where most of the 8484 GB went.

Three practical consequences follow, and the third is the one people underrate.

You can fine-tune a large model on one accelerator.

An adapter is megabytes rather than gigabytes, so you can keep hundreds of them.

And because Equation (23.1) is an addition to a frozen WW, adapters can be swapped at serving time without reloading the base model. One model in memory, many behaviours.

QLoRA combines the idea with a quantised base model, and puts fine-tuning a 6565 billion parameter model within reach of a single accelerator.

Making the model smaller

Quantisation

Weights are usually trained in 1616 bits. They rarely need 1616 bits to be used.

precision bytes per parameter a 7B model
fp32 4 28.0 GB
fp16 2 14.0 GB
int8 1 7.0 GB
int4 0.5 3.5 GB

The int4 row is the interesting one. A model that needed a data-centre card at fp16 now fits on a consumer GPU.

Quality loss at int8 is usually indistinguishable in practice.

At int4 the loss is measurable but often acceptable. It is almost always a better trade than moving to a genuinely smaller model.

Distillation and pruning

Distillation trains a small student to match a large teacher’s output distribution. The teacher’s full distribution carries more information than a hard label does, because it says which wrong answers were nearly right.

Pruning removes weights or whole structures that contribute little. Unstructured pruning gives better compression ratios; structured pruning gives speedups on real hardware, because it removes shapes rather than scattered entries.

The general finding across all three techniques is the same. Models are substantially over-parameterised for inference, and most of that slack can be recovered without retraining from scratch.

Making inference faster

Where the time actually goes

Generation has two phases with completely different cost profiles, and conflating them causes most confusion about latency.

Prefill processes the whole prompt in parallel. It is compute-bound, and it is fast per token.

Decoding produces one token at a time, each depending on the last. It is memory-bound, because every step reads the entire weight matrix to produce one token.

So the second phase dominates wall-clock time on any answer of reasonable length, and it is the one worth optimising.

The KV cache, and its cost

Each decoding step recomputes attention over the whole prefix. Caching the keys and values avoids that, and it is the single most important inference optimisation there is.

It also becomes the memory problem. For D=4096D = 4096 and L=32L = 32 layers, in fp16:

context length KV cache
2,048 1.07 GB
32,768 17.18 GB

At long context the cache can exceed the weights.

That is why grouped-query attention exists, sharing key and value projections across heads. It is one of the few architecture changes since the original transformer driven purely by serving cost.

Batching, and the quadratic wall

Throughput comes from batching. Because decoding is memory-bound, processing many sequences at once costs little more than one.

So serving systems batch aggressively, and schedule continuously rather than waiting for a batch to fill.

Underneath all of it sits the O(n2)O(n^2) of Chapter 16. Quadrupling the context multiplies the attention cost sixteen-fold, and every long-context technique is an attempt to pay less than that.

FlashAttention does not change the complexity. It changes the memory traffic, computing attention in tiles that fit in fast on-chip memory. That is a large practical speedup for no change in the result.

Living with a deployed model

Two effects that only appear after shipping, and neither is a modelling problem.

Drift. The world changes and the training data does not. A model’s accuracy on live traffic decays even though the model has not changed. The response is monitoring, not retraining on a schedule.

Feedback loops. A deployed model influences the data it will later be trained on. A recommender changes what people read; a text model changes what people write. That loop is now measurable in web corpora.

The engineering discipline here is the empirical method of Chapter 14, applied to a system rather than an experiment. State the metric, hold out the evaluation, log the failures, and look at them.

Further reading.

introduce LoRA and its rank ablations are worth reading for the intuition about intrinsic dimension. combine it with quantisation. explain why memory traffic rather than arithmetic is the bottleneck.

Count the adapter. For d=k=4096d = k = 4096, compute the LoRA parameter count at r=4,8,32r = 4, 8, 32 and express each as a share of the full matrix. Then repeat for d=k=768d = k = 768. Why is the share so much larger on the smaller matrix, and what does that imply about where LoRA pays best?

The memory budget. Work out the full fine-tuning memory for a 1313 billion parameter model in fp16 with Adam, then the same figure with LoRA at r=8r = 8 applied to attention projections only. State every assumption you made.

Choose a precision. A 77B model must run on a card with 88 GB of memory, leaving 22 GB for activations and the KV cache. Which precision can you use? Now the context must be 8,1928{,}192 tokens. Recompute and say what has to give.

Prefill against decode. Explain why the first phase is compute-bound and the second memory-bound. Then predict which phase dominates for a 2,0002{,}000 token prompt with a 2020 token answer, and for a 5050 token prompt with a 2,0002{,}000 token answer.

Size the cache. For D=5120D = 5120, L=40L = 40 and fp16, compute the KV cache at 4,0964{,}096 and 65,53665{,}536 tokens. At which length does it exceed the weights of a 1313B model? Name one architectural change that reduces it.

Pick the technique. For each constraint, choose one method from this chapter and justify it: (a) one accelerator, must serve forty customer- specific behaviours; (b) model must run on a phone; (c) latency is fine but throughput is a tenth of what is needed; (d) context must grow from 4k to 64k.