Skip to content

Science1 publisher2 min readPublished

Caching the prefix stops a 0.5B model re-encoding the same instruction block 600 times

A KDnuggets walkthrough builds its comparison on Qwen2.5-0.5B-Instruct on an M2 MacBook Air, where the keys and values for a static instruction block come out identical on every call and only the ticket text changes.

The Scientist · Science desk

What happened

  • The second piece in a KDnuggets series on small language model optimization covers reusing the prompt prefix through a key-value cache, following one on constraining the output space.
  • The benchmarks are described as running Qwen2.5-0.5B-Instruct in float16 through Hugging Face Transformers on an M2 MacBook Air with 24GB of RAM and a 16-core Neural Engine.
  • Keys and values for each token at each layer depend only on the tokens to its left, so for a fixed prefix they come out identical on every call and can be computed once and kept.
  • The toy workload is 600 support ticket records, three strings repeated 200 times, sorted into billing, technical or account.
  • The baseline carries forward the constrained scoring from the first article, which collapses the decision to a single forward pass and leaves the pre-fill as the only per-item cost left to attack.

Compiled by The ScientistSomething wrong?How this is made

Why it matters

  • capability A team can take the pre-fill saving without re-validating its classifier, because the cached vectors are the ones the model would have recomputed and the prediction is unchanged.
  • constraint The pre-fill share visible in a single-stream run on laptop CPU threads belongs to that configuration, so nobody serving batched requests on a GPU can borrow the ratio as a planning number.
  • contradiction The prose says float16 and the script loads float32, so a reader who runs the code times a different baseline from the one described, and any speedup quoted against it inherits the mismatch.

Narrow automation prompts are mostly fixed text: a task instruction, a taxonomy definition, and a few examples, with a short tail that changes per item [6]. The article's illustration is an instruction block of a couple of hundred tokens and twenty or thirty tokens added per ticket [7]. Take 200 and 25, and about 89 percent of every prompt is identical to the last one [14]. Over the 600-record dataset, re-encoding in full pushes 120,000 prefix-token positions through every layer, against 200 if the keys and values are computed once and held, so 119,800 of those encodings are avoidable [15]. Token counts alone show the redundancy; ranking prefix reuse against other tuning choices needs seconds on a clock, and the text available ends inside the baseline script, before any timing for the cached path [18].

Copying the script as published gets the four-byte path, which at half a billion parameters is roughly 2 GB of weights instead of roughly 1 GB [16]. That is a different starting point for any prefill figure a reader measures at home.

The script sets the thread count to the number of CPUs [12], so what is being timed is single-stream inference on a laptop. On a GPU server taking concurrent requests, I would expect the prefill share to be smaller, because batching spreads one shared prefix across several items and the held keys and values occupy memory that the weights and the in-flight batch also want.

Reuse holds only while the prefix tokenizes identically on every call. The walkthrough writes the ChatML layout out by hand instead of calling apply_chat_template(), so the prompt can be split at a known token boundary [10]. The scoring trick carried over from the first article has its own condition: the labels' first tokens have to differ, and the code stops if they do not, with the message "Labels share a first token; score full label sequences instead." [11]

What to watch

  • Whether the series publishes wall-clock pre-fill times for the cached path on the same M2 MacBook Air setup, which is what would let anyone rank prefix reuse against other tuning options.
  • Whether the float16 in the text or the float32 in the code is the intended baseline, since the two give different weight memory and different timings.
  • Whether the same comparison is repeated on batching GPU hardware, where a shared prefix is already amortized across concurrent requests.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories