Search Tech Journey

Find topics, journeys and posts

back to blog
mladvanced 120m read

DL S068 · Pruning and Distillation — When Smaller Beats Quantized

Magnitude pruning, 2:4 structured sparsity that actually maps to GPUs, and knowledge distillation from teacher to student. When distillation beats quantization, and when it's a trap.

🧠SoftwareM11 · Efficient inference + serving· Session 068 of 130 120 min

🎯 Prune a Transformer to 50% sparsity, distill a 7B into a 1.3B, and know which of these actually wins in production.

Series: Deep Learning & LLMs From Scratch — 80 sessions · Session 68 / 80 · Module M11 · ~2 hours

The story

Quantization (S067) shrinks by making each weight cheaper. Pruning shrinks by making some weights zero. Distillation shrinks by training a smaller model to imitate a bigger one. All three are compression, all three have decades of history, and all three interact badly with LLMs in ways the CNN literature didn't prepare us for.

Here's the awkward truth: for LLMs, pruning is disappointing. The Lottery Ticket Hypothesis papers dazzled everyone in 2019 with 90% sparsity on ResNet. On GPT-scale models the same techniques get you 20% sparsity before quality collapses. Meanwhile distillation is phenomenal: Llama-3.2-1B (distilled from 8B/70B) is basically usable, DistilBERT retains 97% of BERT quality at 40% size, and Alpaca kicked off the entire "instruction-tuned tiny model" era.

So today: pruning honestly (with the caveats), the one form of pruning that does work on GPUs (2:4 sparsity on Ampere+), and distillation deeply — because distillation is where the real wins live.

Trimming the bonsai vs training a smaller apprentice
🌍 Real world
💻 Code world
You will be able to
  • Implement magnitude pruning and measure the accuracy/sparsity curve.
  • Explain why 2:4 structured sparsity is the only pruning modern GPUs accelerate, and how to enable it.
  • Distinguish response, feature, and relation distillation with one-line definitions each.
  • Write a distillation training loop with soft-label KL + hard-label CE loss and pick a temperature.
  • Decide between prune, quantize, distill, or MoE for a given deployment constraint.
  • Recognise when a distilled model is being 'held back' by its teacher and when it needs its own SFT.

Prerequisites

  • Session 067 — compression as an axis; we're adding two more axes.
  • Session 058 — you'll need to run SFT on the student.
  • Session 022 — L1/L2 penalties feed straight into pruning intuition.


1 · Magnitude pruning

The oldest, dumbest, still-competitive method: rank weights by absolute value, set the smallest k%k\% to zero, fine-tune the rest.

import torch, torch.nn as nn
 
def magnitude_prune(model: nn.Module, sparsity: float):
    """Global magnitude pruning across all Linear layers."""
    all_weights = torch.cat([
        p.detach().abs().flatten()
        for name, p in model.named_parameters()
        if "weight" in name and p.dim() == 2
    ])
    threshold = torch.quantile(all_weights, sparsity)
    masks = {}
    for name, p in model.named_parameters():
        if "weight" in name and p.dim() == 2:
            mask = p.detach().abs() >= threshold
            p.data.mul_(mask)
            masks[name] = mask
    return masks

Then during fine-tuning, re-apply masks after each optimizer step so pruned weights stay zero:

def apply_masks(model, masks):
    for name, p in model.named_parameters():
        if name in masks:
            p.data.mul_(masks[name])

This is called iterative magnitude pruning (IMP): prune 20%, fine-tune, prune another 20%, fine-tune. Better than one-shot.

Try itSweep sparsity from 0.1 to 0.9 on a small transformer and plot perplexity.

Load distilgpt2, evaluate perplexity on WikiText-2 test split. Then call magnitude_prune at sparsities [0.1, 0.3, 0.5, 0.7, 0.9] (fresh model each time) and record perplexity. Plot it. You'll see the classic "cliff": near-flat until ~40–50%, then a hockey-stick blow-up. That cliff location is what SparseGPT (and later Wanda) shifted to the right by ~10–15 points.

💡 Hint · Use a distilgpt2 or nanoGPT model and WikiText-2 for a 2-minute round trip.

The disappointing curve

On ResNet-50/ImageNet: 90% sparsity, <1% accuracy loss.
On Llama-2-7B/WikiText: 50% sparsity, ~10× perplexity increase. Even 20% hurts.

Why the gap? LLMs are trained closer to their capacity — every weight matters more. And unstructured sparsity doesn't speed up inference on a GPU (dense matmul kernels don't skip zeros; you're just wasting the same FLOPs).


2 · N:M structured sparsity — the pruning GPUs actually like

Ampere (A100) and newer support 2:4 sparsity: in every group of 4 consecutive weights along a specific axis, at most 2 are non-zero. NVIDIA's Sparse Tensor Cores literally skip the zeros and give you a 2× throughput uplift on the matmul.

def enforce_2_4(w: torch.Tensor) -> torch.Tensor:
    """w: (out, in). Keep top-2 magnitudes in every group of 4 along `in`."""
    out_f, in_f = w.shape
    assert in_f % 4 == 0
    w4 = w.view(out_f, in_f // 4, 4)
    _, topk_idx = w4.abs().topk(k=2, dim=-1)  # (out, in/4, 2)
    mask = torch.zeros_like(w4).scatter_(-1, topk_idx, 1.0).bool()
    return (w4 * mask).view(out_f, in_f)

Enable it at inference with torch.sparse.SparseSemiStructuredTensor or via TensorRT-LLM's --use_sparse_gemm. On Llama-2-7B with SparseGPT + 2:4, real papers report ~5% perplexity increase for ~1.8× decode speedup. Not free, but real.

Movement pruning (Sanh et al.) is a smarter variant: rank not by magnitude but by how much a weight moved during fine-tuning. Weights growing are important; weights drifting to zero can go. Better than magnitude on downstream tasks with small fine-tuning budgets.


3 · SparseGPT — the GPTQ of pruning

Frantar & Alistarh, 2023: same Hessian-compensation trick as GPTQ but for pruning masks. Given a target sparsity per layer, solve for the optimal mask + weight update jointly. One-shot (no fine-tuning), works at 50% for OPT-175B with <5% perplexity drop.

# pip install sparsegpt (Frantar's ref implementation)
from sparsegpt import SparseGPT
# hook each Linear layer, feed calibration data:
#   sparsegpt.fasterprune(sparsity=0.5, prunen=2, prunem=4)

prunen=2, prunem=4 gets you N:M sparsity in one shot without fine-tuning. This is what you'd actually run if you were serious about pruning today.


4 · Knowledge distillation — the wins are here

Hinton et al. (2015): a student model is trained not on the hard one-hot labels but on the soft probabilities from a teacher.

L=(1α)LCE(ytrue,ps)+αT2LKL(ptTpsT)\mathcal{L} = (1-\alpha) \cdot \mathcal{L}_{CE}(y_{\text{true}}, p_s) + \alpha \cdot T^2 \cdot \mathcal{L}_{KL}(p_t^T \,\|\, p_s^T)

Where pT=softmax(z/T)p^T = \text{softmax}(z/T) is the softened distribution at temperature TT. Typical T[2,5]T \in [2, 5], α[0.5,0.9]\alpha \in [0.5, 0.9].

Why it works: soft labels leak the teacher's uncertainty structure — "this looks 60% cat, 30% dog, 10% fox" is more informative than "cat". The student learns not just the answer but the manifold of related answers.

Response distillation (the basic recipe)

import torch
import torch.nn.functional as F
 
def distill_step(student, teacher, x, y_true, T=2.0, alpha=0.7):
    with torch.no_grad():
        z_t = teacher(x).logits           # (B, seq, V)
    z_s = student(x).logits
    # Hard-label loss
    ce = F.cross_entropy(z_s.view(-1, z_s.size(-1)), y_true.view(-1))
    # Soft-label KL
    log_p_s = F.log_softmax(z_s / T, dim=-1)
    p_t = F.softmax(z_t / T, dim=-1)
    kl = F.kl_div(log_p_s, p_t, reduction="batchmean") * (T * T)
    return (1 - alpha) * ce + alpha * kl

That's ~90% of what DistilBERT / TinyLlama / MiniLM did.

Feature distillation

Match hidden states, not just logits: hsWht2\|h_s^{\ell} - W \cdot h_t^{\ell'}\|^2 for layer pairs (,)(\ell, \ell'). Useful when the student is much shallower than the teacher — logits alone give too little signal.

Relation distillation (RKD, TinyBERT)

Match pairwise relationships between samples: d(hsi,hsj)d(hti,htj)\|d(h_s^i, h_s^j) - d(h_t^i, h_t^j)\|. Preserves the geometry of the teacher's representation space.

Modern LLM distillation

The dominant recipe now is even simpler: sample from the teacher, SFT the student. Alpaca (Stanford, 2023) took GPT-3.5 outputs on 52k prompts and fine-tuned Llama-7B. The student never sees teacher probabilities, just teacher completions. It works because the completions themselves carry the teacher's implicit reasoning.

Rule of thumb (2024/2025)

    5 · When does distillation beat quantization?

    SituationReach for
    Need 4× smaller, ≤1% quality loss, have GPU for trainingQuantization (AWQ)
    Need 10× smallerDistillation
    Have a great teacher but no calibration dataDistillation
    Need real latency wins on non-Ampere hardwareDistillation (smaller model) or quantization
    On-device (phone)Distill then quantize
    Task is very narrow (single-domain chatbot)Distill to 1B, will match teacher on that task

    The killer combo: distill 70B → 7B, then AWQ-4bit that 7B. Effective ~35× compression with maybe 3 points of MMLU loss. This is roughly what Meta did for on-device Llama-3.2-1B.


    6 · A distillation run in ~40 lines

    from transformers import AutoModelForCausalLM, AutoTokenizer
    import torch, torch.nn.functional as F
     
    teacher = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3-8B-Instruct", torch_dtype=torch.bfloat16, device_map="cuda:0").eval()
    student = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-3.2-1B", torch_dtype=torch.bfloat16, device_map="cuda:1")
    tok = AutoTokenizer.from_pretrained("meta-llama/Llama-3-8B-Instruct")
     
    opt = torch.optim.AdamW(student.parameters(), lr=2e-5)
     
    def loss_fn(z_s, z_t, y, T=2.0, alpha=0.7):
        ce = F.cross_entropy(z_s.view(-1, z_s.size(-1)), y.view(-1), ignore_index=-100)
        kl = F.kl_div(
            F.log_softmax(z_s / T, dim=-1),
            F.softmax(z_t / T, dim=-1),
            reduction="batchmean",
        ) * (T * T)
        return (1 - alpha) * ce + alpha * kl
     
    for batch in loader:
        input_ids = batch["input_ids"].cuda(0)
        labels = batch["labels"].cuda(1)
        with torch.no_grad():
            z_t = teacher(input_ids).logits.to("cuda:1")
        z_s = student(input_ids.to("cuda:1")).logits
        loss = loss_fn(z_s, z_t, labels)
        loss.backward()
        opt.step(); opt.zero_grad()

    Two things to notice:

    1. Teacher on GPU 0, student on GPU 1. You need both in memory — the teacher forward dwarfs the student's memory anyway.
    2. ignore_index=-100 — standard HF convention for masking prompt tokens from the loss. Only distill on the response tokens.

    7 · Pitfalls

    War story Vocab mismatch

    Student and teacher must share the tokenizer. Distilling Llama into Mistral fails silently — the logit indices don't align. Either use the same base family or add a projection layer (feature distillation).

    War story Temperature miscalibration

    Too low (T=1T=1): soft labels collapse to hard labels, no benefit over CE. Too high (T=10T=10): distribution flattens to uniform, no signal. Sweep T{2,3,5}T \in \{2, 3, 5\} on a validation set. Higher TT needs higher α\alpha.

    War story Distillation is not a replacement for pretraining

    Distilling a 1B student from an 8B teacher does not skip the need for a strong base model. Start from an already-pretrained 1B (TinyLlama or Llama-3.2-1B base), then distill. Distilling from random init needs teacher-scale data and compute.

    War story Depth pruning beats width pruning on modern LLMs

    Meta's Llama 3.2 report (2024) revealed how they made the 1B and 3B: they did layer-drop pruning (remove whole transformer layers) from the 8B, then healed with distillation. Layer 25 of a 32-layer model often contributes almost nothing; removing it costs ~0.5 MMLU. Sun et al.'s ShortGPT (2024) and Gromov et al. (2024) both show you can drop up to 25% of layers with negligible loss if you pick the right ones (Block Importance metric: change in hidden state cosine similarity across a layer).


    9 · The 2024–2025 distillation renaissance

    Distillation went from a niche technique to the default way small models get made. Every open-weights release under 3B in 2024–2025 was distilled from a bigger sibling. Let me lay out the taxonomy that emerged.

    9.1 White-box vs black-box distillation

    • White-box (classical): you have the teacher's logits per token. KL loss against them. This is the code above; requires access to teacher weights.
    • Black-box (a.k.a. "distillation from API"): you only have generated text from the teacher — no logits. Train the student on (prompt, teacher_response) pairs as SFT. Alpaca, Vicuna, WizardLM all did this from GPT-3.5/GPT-4. Legal grey area (violates most APIs' terms) but wildly effective.

    Black-box distillation seeded the entire open-source instruction-tuned model ecosystem in 2023. In 2024–2025 it's less common because Llama-3/Qwen2.5 have good enough instruction data of their own, but any time you see a "trained on synthetic data" tag on HuggingFace, that's black-box distillation.

    9.2 On-policy vs off-policy distillation

    Agarwal et al., "On-policy distillation" (Google 2024) argue: don't just distill on a fixed dataset. Instead, at each step, let the student generate a response, then use the teacher to score/relabel it. This closes the train-test distribution gap (student never sees its own outputs during training). Gemma-2 was distilled this way; Google claim ~2× sample efficiency.

    9.3 MiniLLM and reverse-KL

    Gu et al., MiniLLM (ICLR 2024) noticed that standard forward-KL (student matches teacher's distribution) forces the student to spread probability across all modes the teacher covers — including modes the small student can't do well. Switching to reverse-KL (teacher matches student's distribution) makes the student concentrate on modes it can fit. On smaller students (≤ 1B) this is a 3–5 point win on MT-Bench.

    9.4 Distilling reasoning: the DeepSeek-R1 story

    January 2025. DeepSeek releases DeepSeek-R1, a reasoning model trained with pure RL. Then they do something remarkable: they distill R1's reasoning traces into Qwen and Llama students of various sizes and release them.

    DeepSeek-R1-Distill-Qwen-7B scores 55.5% on AIME 2024 vs Qwen-2.5-7B's ~12%. The student inherits chain-of-thought reasoning from the teacher, essentially for free, at 7B scale. This kicked off the entire "reasoning distillation" wave of 2025 — within 4 months there were 30+ open reasoning models all trained this way.

    The lesson: distillation transfers not just knowledge but capabilities, if you can generate teacher outputs that exercise the capability. Alpaca did this for instruction following in 2023; R1 did it for reasoning in 2025.

    Further reading — the modern distillation stack:


    10 · Try it yourself

    1. Prune → measure. Take a small model (gpt2 or Qwen2.5-0.5B), magnitude-prune to 30%/50%/70% sparsity without fine-tuning, measure WikiText perplexity at each. Plot the curve. Then re-run with a short healing fine-tune. Notice how much fine-tuning recovers.
    2. 2:4 sparsify one Linear layer with torch.sparse.to_sparse_semi_structured and time the matmul on an A100 vs a dense reference. Confirm the ~1.8× speedup.
    3. Reasoning distillation lite. Generate 200 chain-of-thought traces from DeepSeek-R1-Distill-Qwen-7B on GSM8K problems. SFT a Qwen-0.5B student on those traces. Measure GSM8K accuracy delta vs the un-distilled baseline. Even 200 examples move the needle noticeably.

    8 · Mermaid: the compression landscape


    Recall

    1. Why is unstructured magnitude pruning a bad latency play on GPUs? Dense matmul kernels don't skip zeros. You save storage but the wall-clock forward pass is unchanged.

    2. What is 2:4 sparsity and why does it work? In every group of 4 consecutive weights, at most 2 are non-zero. NVIDIA Ampere Sparse Tensor Cores have a hardware pathway that skips those zeros, giving ~2× matmul throughput.

    3. Distillation loss formula? L=(1α)CE(ytrue,ps)+αT2KL(ptTpsT)\mathcal{L} = (1-\alpha) \cdot \text{CE}(y_{\text{true}}, p_s) + \alpha \cdot T^2 \cdot \text{KL}(p_t^T \,\|\, p_s^T), where pT=softmax(z/T)p^T = \text{softmax}(z/T).

    4. Why the T2T^2 factor in the KL term? Softening by TT shrinks gradient magnitudes by 1/T21/T^2. Multiplying the loss by T2T^2 keeps gradient scales comparable to the CE term regardless of temperature.

    5. Killer compression combo for on-device? Distill (10× smaller student) → then quantize the student to INT4/NF4. Total ~35× compression with modest quality loss.

    Stretch: run a distillation of a 3B student from an 8B teacher on Alpaca-style data, compare against SFT-only baseline. Report MMLU delta. Predict what happens at temperature 1 vs 3.

    In your own words: the reason pruning underperforms on LLMs vs CNNs is __________________________.

    Spaced review: S022 regularization, S058 SFT, S067 quantization.

    Next session (S069): speculative decoding — a tiny draft model proposes tokens the big model verifies in parallel. 2–3× decode speedup for zero quality loss.

    Bring back tomorrow:

    • The N:M sparsity idea (only pruning that maps to hardware).
    • The soft-label + hard-label distillation loss.
    • The distill-then-quantize combo.
    Common misconception
    ✗ What most people think

    "Pruning removes the weights that don't matter, so a 50%-sparse model should run about twice as fast. I'll zero out the smallest weights and get my speedup."

    ✓ What is actually true

    Zeroing a weight removes a multiply, but it does not remove a memory access, a matrix shape, or a kernel launch. Unstructured sparsity gives you a dense tensor full of zeros: same bytes moved, same GEMM dimensions, no speedup on hardware built for dense matmul. You get wall-clock benefit only from structured sparsity — whole heads, whole channels, whole layers — or from a hardware-supported pattern with a kernel that actually exploits it.

    Why the myth is so sticky

    The belief is sticky because it is true in the world where you first learned about sparsity: sparse linear algebra on CPUs, graph algorithms, and scientific computing, where a sparse format really does skip the zeros and really is faster. It is also true in the accounting sense — the FLOP count genuinely halves. What breaks it is that a modern accelerator is not FLOP-limited on this workload; it is bandwidth- and shape-limited, and an irregular index pattern is worse for both. So you can be perfectly right about the arithmetic and completely wrong about the clock, which is the most durable kind of wrong.

    Prove it to yourself

    Time it rather than counting it:

    import torch, time
    W = torch.randn(4096, 4096, device='cuda', dtype=torch.float16)
    x = torch.randn(4096, 4096, device='cuda', dtype=torch.float16)
    mask = (W.abs() > W.abs().flatten().kthvalue(W.numel()//2).values)
    Ws = W * mask                      # 50% zeros, same shape, same dtype
    
    def bench(A):
        for _ in range(5): A @ x
        torch.cuda.synchronize(); t = time.time()
        for _ in range(50): A @ x
        torch.cuda.synchronize(); return (time.time()-t)/50
    
    print('dense ', bench(W))
    print('sparse', bench(Ws), '<- same bytes, same shape')
    print('narrow', bench(W[:2048]), '<- structurally smaller')

    The middle line is the lesson. The third line is the fix.

    From first principles
    Start with the question

    Why does distilling from a teacher's full output distribution beat training the student on the teacher's top-1 answers, even when the top-1 answers are correct? The labels are identical.

    1. 1
      A hard label is one bit of information per token position: this token, not the others. A full distribution over the vocabulary carries information about every alternative and their relative plausibility.
      forced by · the gradient a sample provides is bounded by the information it encodes, so richer targets mean more signal per token
    2. 2
      Those relative plausibilities encode the teacher's learned similarity structure — which continuations are near-misses and which are nonsense — information that exists nowhere in the ground-truth data.
      forced by · the training corpus only ever asserts what was written, never what could plausibly have been written instead
    3. 3
      Training against a distribution rather than a point makes the loss landscape smoother: the target moves continuously as the student improves, instead of presenting a single spike the student must climb toward.
      forced by · a soft target has non-zero gradient over many logits at once, so the student gets corrective pressure on the whole output layer per step, not just on one entry
    4. 4
      The teacher's distribution is also self-consistent in a way the corpus is not — it never contains two contradictory labels for the same context, because it is a single function.
      forced by · label noise in real corpora sets a floor on achievable loss, and distilling from a function removes that floor
    5. 5
      But this only works where the student can actually be queried on the same inputs the teacher sees, which is why on-policy distillation — training on the student's own generations, scored by the teacher — outperforms distilling on a fixed corpus.
      forced by · the student's errors compound on its own trajectory, and a fixed corpus never visits the states where the student is worst
    ⇒ Therefore

    Therefore soft targets are not a regularisation trick — they transfer a function rather than a dataset, and functions carry strictly more information than the samples used to fit them.

    And note the prediction. First: the benefit of distillation over hard labels should be largest where the teacher is uncertain, because that is where the extra information lives — so it should help most on ambiguous or open-ended tokens and barely at all on deterministic ones like closing brackets. Measure per-token loss improvement bucketed by teacher entropy and expect exactly that gradient. Second: temperature should matter, and matter non-monotonically — too low and you have recovered hard labels, too high and you have flattened the distribution into noise. Third: distillation should be markedly more sample-efficient than training on the same corpus with ground-truth labels, so the student should reach a given loss in fewer tokens. If it does not, your teacher is not adding information and you should question whether it is better than the data.

    Mental modelCapacity you can remove vs capacity you must relocate

    A trained network holds its capability in two forms. Some of it is genuinely redundant — heads that duplicate each other, channels that barely fire, layers whose residual contribution is near zero. That capacity can simply be deleted. The rest is distributed: no single weight holds it, and cutting anywhere degrades it a little.

    Pruning is the tool for the first kind. Distillation is the tool for the second — it does not remove capacity, it re-fits a smaller function to the same input-output behaviour. Confusing the two is the source of nearly every disappointing compression result: people prune where they should have distilled, then are surprised that fine-tuning cannot bring it back.

    • Unstructured sparsity saves FLOPs on paper. Structured sparsity — heads, channels, layers — saves wall-clock. Only the second is a deployment result.
    • Every prune needs a recovery phase. A pruned-but-unfinetuned model is a measurement, not a model.
    • Distillation transfers a function; supervised training transfers a dataset. The function has more information in it, which is why the student can beat a same-size model trained from scratch.
    • The compression triangle is size, quality, and effort. Quantisation is cheap and preserves quality; pruning is cheap and costs quality; distillation preserves quality and costs a training pipeline. Pick which one you can afford to spend.
    • Compression is capability-selective. Aggregate metrics hide it. Always evaluate per-capability.
    🔔 Fires when you see

    Fire this the moment you see: a sparsity percentage quoted without a latency measurement · a pruned model that fine-tuning cannot recover (you cut distributed capacity, not redundant capacity) · a student that matches the teacher on benchmarks but not in production (your distillation corpus did not cover the production distribution) · "we'll just use a smaller model" with no distillation step · compression evaluated only on perplexity · someone stacking pruning and quantisation without measuring the interaction.

    The tradeoff

    You must halve serving cost for a model you already have. Prune it, distil a smaller one, or quantise?

    Structured pruning plus recovery fine-tuning
    + you gain reduces FLOPs and memory together and produces a plain dense model in the original format, so every runtime and kernel still works; the recovery phase is short relative to training and can reuse your existing fine-tuning pipeline
    − you pay quality loss is real and capability-selective — the removed heads were doing something, and it is rarely the thing your aggregate metric measures; each new target size needs its own prune-and-recover cycle, so it does not amortise across deployments
    pick when you need a modest size reduction, you already have a working fine-tuning setup and data, and you can evaluate on the specific capabilities you ship rather than on a generic benchmark
    Distil a smaller student
    + you gain the best quality-per-parameter of the three, because you are re-fitting rather than damaging; you choose the student architecture freely, so you can pick shapes that suit your hardware; and one good student amortises across every deployment of that size
    − you pay by far the most expensive option in engineering time and compute — a teacher inference pipeline, a large generation corpus, and a full training run — and the student inherits the teacher's blind spots and biases without inheriting the ability to notice them
    pick when you will serve this model at high volume for months, so a one-off training cost amortises, or you need a size that no released checkpoint offers
    Quantise and change nothing else
    + you gain hours rather than weeks, no training data, no retraining, and quality degradation that is usually far smaller than an equivalent size reduction by pruning; fully reversible if it disappoints
    − you pay saves bytes rather than FLOPs, so it helps memory-bound decode much more than compute-bound prefill; and it stacks awkwardly with pruning because both consume the same error budget
    pick when you are memory-bound rather than compute-bound, or you need a result this week — this is always the correct first attempt
    What a senior engineer actually does

    Try quantisation first, always, because it is the cheapest experiment and frequently the whole answer. If it is not enough, the deciding question is how long you will serve this model: pruning is the right answer for a one-off or short-lived deployment, distillation for anything you will run at volume for months, because only then does the training cost amortise against the inference bill.

    The failure that costs teams the most is stacking techniques without measuring in between. Prune, then quantise, then distil, and when quality drops you cannot attribute it. Change one thing, evaluate on the capabilities you actually ship, and record the result — the resulting table is worth more than any of the individual models, because it tells you where your error budget went.


    Quick recall · click to reveal
    ★ = stretch question

    Previous: ← DL S067 · Next: DL S069 →