Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

KV Cache

In the previous two chapters, we explored how to control the generation of the model: sampling strategies and stopping criteria. Next, let us look at how to improve the performance of model inference.

Autoregressive generation in a GPT model has a performance bottleneck: every time a new token is generated, the attention of all tokens has to be recomputed. Suppose 100 tokens have been generated; to generate the 101st token we have to compute the attention of 101 tokens, and the time complexity of generating each token is O(n2)O(n^2).

KV cache

The core idea of the KV cache (key-value cache): cache the keys and values of the tokens that have already been generated. When generating a new token, compute only its query, and then do attention together with the cached keys and values.

How it works

In self-attention, the key and value of each token depend only on the token itself and the tokens before it, and have nothing to do with later tokens. Therefore:

  • the keys and values of generated tokens can be cached and need not be recomputed;

  • a new token only needs to compute its own query and do attention together with the cached keys and values;

  • the cache keeps growing as generation proceeds, but each token is computed only once.

Implementation points

  • Cache structure: each Transformer block stores one set of keys and values, where the key is already transposed, with the shape (batch size, number of heads, per-head embedding size, generated length); the value has the shape (batch size, number of heads, generated length, per-head embedding size);

  • Incremental computation: the key and value of the new token are concatenated with the cache before computing attention;

  • Position encoding: the position encoding of the new token needs an offset (the generated length).

Model

GPT cached embedding layer

The GPT cached embedding layer (GPTEmbeddingWithCache) needs to support a position offset: the position encoding of the new token starts from offset instead of from 0.

GPT cached attention layer

The GPT cached attention layer (GPTAttentionWithCache) is the core of the KV cache:

  • Without cache: the input is the whole context window before the current position, computed normally;

  • With cache: the input is only the new token at the current position, and its key and value must be concatenated with the cache before computing attention.

With a cache, no causal mask is needed, because the new token computes attention only with the tokens already generated, which naturally satisfies causality.

GPT cached Transformer block

The GPT cached Transformer block (GPTTransformerWithCache) passes the cache to the attention layer as a parameter and returns the new cache produced by the attention layer.

GPT cached model

The GPT cached model (GPTWithCache) manages the caches of all Transformer blocks:

  • each block has one cache, stored in a list;

  • during the forward pass the cache is passed block by block and the new caches are collected.

GPT cached trainer

The generate function of the GPT cached trainer GPTTrainerWithCache:

  • First generation: no cache, compute all tokens;

  • Later generations: with cache, compute only the new token;

  • Cache reset: if the sequence length exceeds the context size, reset the cache.

Hyperparameters

Model parameters

The model parameters must stay consistent with the pre-training stage.

Modeling

Loading the model

Without cache

ROMEO:
When I pray.

CAMILLO:
In my liest, I have done drunk.

CAMILLO:
Ay, since the speak, my doubt, fainners!
I am too, as to a kind in honourity,
Can a very disentent till take from here other
out, strike than 'Which children choistones
That would how have m
4.86582589 seconds

With cache

ROMEO:
When I pray.

CAMILLO:
In my liest, I have done drunk.

CAMILLO:
Ay, since the speak, my doubt, fainners!
I am too, as to a kind in honourity,
Can a very disentent till take from here other
out, strike than 'Which children choistones
That would how have m
0.62065578 seconds

In this chapter, we implemented the KV cache: cache the keys and values of the tokens already generated, so that a new token computes attention only against the cache. The time complexity of generating each token drops from O(n2)O(n^2) to O(n)O(n), and generation is much faster.

Exercises

  1. Adjust the maximum generation length steps and observe the difference in speed between no cache and with cache. Does the advantage of the cache grow more obvious the longer the generation?