A Token's Journey Across the LLM Stack

Part 4 of 5 The Life of a Token Across the LLM Stack

In brief

In brief

LLM inference has constraints from request computation, GPU memory and memory occupancy time. This example uses 128 KiB of KV cache for each token. An 8 GiB pool has capacity for at most 14 unshared requests with 4,608 tokens.

  • More token rows in a step let a matmul use each weight load again. Each active request also holds its own KV cache. Use different budgets for rows and requests.
  • Eight times as many generated tokens use about 11.3 times the KV-cache byte-seconds (cache bytes × seconds held), but peak cache increases only 1.8 times.
  • Examine an optimization again after its bottleneck changes. Keep the quality and latency target the same.

Calculate token work, GPU reuse, cache size and time held for the same request.

A service starts to accept longer reasoning traces. Answers stay short, but requests stay active for more time. The key-value (KV) cache fills, and interactive traffic waits. A faster matmul may not let any more requests start. A larger cache pool lets more requests start, but then each decode step reads more cached keys and values.

This article uses one hypothetical request to find LLM inference bottlenecks. It examines the computation that the request uses, its GPU memory and its memory occupancy time. These quantities give KV-cache bytes for each token and request capacity in 8 GiB. They show the bottleneck after an optimization.

The previous articles explain the machinery. The kernel and serving articles use the same dimensions.

1. Start with one hypothetical request

A token starts as an ID, becomes a hidden state and reads permitted previous context. It supplies information for next-token logits. Each generated token changes the work of the next step.

Fig. 1. Token IDs, embeddings, contextual hidden states and next-token logits are different representations. Sampling selects a new token and adds it to the end of the sequence. This starts the next step. Full interactive figure

Examine the request in four connected views. The token view gives the necessary computation. The GPU view shows how hardware does the computation. The memory view shows the KV cache kept between steps. The request view shows when that cache gets service. They are views of one task, not stages you can make better in isolation.

For this hypothetical example, one replica uses a dense decoder with these properties:

Quantity Assumption
Layers and hidden width L=32L=32, H=4096H=4096
Attention 32 query heads, Hkv=8H_{\mathrm{kv}}=8 K/V heads, d=128d=128 for each head
Precision bf16 weights and cache, b=2b=2 bytes for each scalar
Request S0=4096S_0=4096 prompt tokens, Ng=512N_g=512 generated tokens
Cache pool 8 GiB available for KV after weights, workspaces, and other reserves
Execution one GPU, full causal attention, no prefix hit, compression, paging slack, or speculative draft initially

KiB, MiB and GiB are powers of two. Rates use decimal prefixes. BF16 is bfloat16. Generated tokens include any reasoning and control tokens kept in the cache.

2. Token rows set the cost of each step

Comparison table: a projection at M=16 (15.9 FLOPs/byte, 33.8 μs) versus M=256 token rows (227.6 FLOPs/byte, 42.9 μs) shows more weight reuse.
Fig. 2. The projection uses each weight load for more token rows at M=256 than at M=16. It does more token work for each load but uses more time. The minimum times use hypothetical 200 TFLOP/s and 1 TB/s ceilings.

Use the query projection AM×4096B4096×4096A_{M\times4096}B_{4096\times4096}. MM is the number of token rows, one for each token in this step. A prompt chunk supplies many rows. Ordinary decode adds one row for each active request.

Count two FLOPs for each multiply-add. In this optimistic model, each input is read one time and the output is written one time:

F=2MKN,D=b(KN+MK+MN),AI=F/D. F=2MKN,\qquad D=b(KN+MK+MN),\qquad \mathrm{AI}=F/D.

FF is the number of floating-point operations (FLOPs), and DD is the number of bytes moved. Here K=N=4096K=N=4096. Arithmetic intensity (AI) is FLOPs for each byte moved.

Use an illustrative compute ceiling P=200P=200 TFLOP/s and high-bandwidth memory (HBM) bandwidth B=1B=1 TB/s. The Roofline ridge point is P/B=200P/B=200 FLOPs/byte.

A kernel is memory-bound when its intensity is less than this value. It is compute-bound when its intensity is more than this value. The optimistic minimum time is max⁡(F/P,D/B)\max(F/P,D/B).

At M=16M=16, arithmetic intensity is about 15.9 FLOPs/byte, and memory traffic gives a 33.8 μs minimum. At M=256M=256, it is 227.6 FLOPs/byte, and arithmetic gives a 42.9 μs minimum. More rows use more time but do more token work for each weight load. The two estimates do not include the rest of the layer, attention, kernel launches, communication and imperfect utilization.

Token rows and active requests are separate budgets. A 256-token prefill chunk uses projection weights again without admission of 256 requests. Admission lets a request start only when free KV-cache blocks are available.

SARATHI puts prefill and decode tokens into the same linear operations. This mixed batching can help when cache capacity limits decode batch size. An online latency check is still necessary for the selected chunk size.

FlashAttention does not write the full score and probability matrices to HBM. FlashAttention-2 makes work partitioning and execution better. The matmul and FlashAttention article explains the two methods. They decrease execution cost, not the KV cache that stays after each step.

3. Stored history limits concurrent requests

Memory map: temporary attention data versus the KV cache kept across steps (128 KiB for each token, 576 MiB at 4608 tokens) that FlashAttention does not remove.
Fig. 3. Queries and temporary attention data are separate from the KV cache kept across decode steps. In this post's model, each filled KV entry uses 128 KiB for each token. FlashAttention's lower HBM traffic does not remove it.

The KV cache in Fig. 3 contains keys and values for each kept position in each layer. For ordinary full attention, the KV-cache size formula gives:

qKV=2LHkvdb=131,072 bytes/token=128 KiB/token. q_{\mathrm{KV}}=2LH_{\mathrm{kv}}db =131{,}072\ \mathrm{bytes/token} =128\ \mathrm{KiB/token}.

This request holds 512 MiB after prefill and 576 MiB at length 4608. An 8 GiB pool has capacity for at most 14 such full-length unshared histories (no prefix caching between requests). This is an equal-length bound; alignment, block slack, temporary memory and shared prefixes change actual use.

Multi-head, multi-query and grouped-query attention (MHA/MQA/GQA) change HkvH_{\mathrm{kv}}, the number of K/V heads. With other dimensions fixed, 32 K/V heads use 512 KiB/token, and one head uses 16 KiB/token. Quality evaluation is necessary for these architecture choices. They are not runtime switches that preserve the checkpoint's output distribution.

Paging and prefix caching in vLLM change how the cache is allocated and shared. A filled token entry still uses 128 KiB here. With unshared 16-token blocks, the last block wastes less than 2 MiB. A shared prefix prevents duplicate history storage when requests have the same model and full prefix identity: the tokens plus any other cache-key inputs.

Attention kernels and cache allocation change different memory costs. Decreased temporary attention reads and writes to HBM do not remove the stored KV cache. Paging decreases wasted reservations, but decode still reads each filled entry. FlashAttention makes each step cheaper. With paging, the pool can hold more requests.

4. Count how long each request holds cache

Cache integrals: 512 generated tokens give 10.88 GiB·s, and 4096 hold KV cache for a much longer time and give 122.88 GiB·s.
Fig. 4. In this constant-step example, the prompt's KV cache stays during the full decode while the generated suffix increases. Eight times the generated tokens gives about 11.3 times the byte-seconds.

Cache size alone does not show how long a request holds memory while other requests wait.

For this example only, decode adds one token at intervals of Δt=0.04\Delta t=0.04 seconds, with no pauses and immediate cleanup. Do not include prefill. Use continuous growth. For NgN_g generated tokens, the time held is W=NgΔtW=N_g\Delta t. The cache's byte-seconds (bytes held multiplied by seconds) are

AKV≈qKVΔt(S0Ng+Ng22). A_{\mathrm{KV}} \approx q_{\mathrm{KV}}\Delta t \left(S_0N_g+\frac{N_g^2}{2}\right).

The first term is the prompt's cache. The second is the growing suffix. Discrete steps give slightly different values. A measured occupancy trace is necessary for variable step times, eviction, sharing or compression.

Generated tokens Decode time Final unshared cache Byte-seconds during decode
512 20.48 s 576 MiB 10.88 GiB·s
4096 163.84 s 1 GiB 122.88 GiB·s

Eight times the generation holds cache eight times as long and, because the suffix increases, uses about 11.3 times the byte-seconds. This shows the relation between reasoning length and hidden reasoning tokens and capacity.

For stable admitted traffic, Little's law gives average active requests as arrival rate times average time held: Rˉ=λE[W]\bar R=\lambda E[W], with λ\lambda in admissions for each second. At a hypothetical λ=0.02\lambda=0.02 requests/s, the two rows give averages of 0.4096 and 3.2768 active decode requests. For all active decode requests, the total size of unshared cache has an average of λE[AKV]\lambda E[A_{\mathrm{KV}}]: 0.2176 and 2.4576 GiB. These values do not include prefill and bursts. If offered load is more than capacity, there is no stable average: queue lengths increase or admission changes.

Longer output increases generated work, peak KV cache memory and time held. This decreases serving capacity. Final-answer length or peak cache alone does not show the full cost.

5. Compare the methods in one table

The table shows each method’s changes:

Method What it changes What stays or is added Checks
GQA / MQA K/V bytes for each position K/V heads shared in the model. Quality may change. checkpoint quality and supported head layout
FlashAttention temporary attention reads and writes to HBM dense attention arithmetic and the stored KV cache supported shape, hardware, actual bottleneck
FlashAttention-2 work partitioning and execution speed same stored KV cache and dense attention arithmetic delivered kernel performance
PagedAttention allocation waste and sharing block lookup and last-block slack cache pool occupancy and block-size tradeoff
Prefix caching repeated prompt computation and duplicate prefix cache cache kept between requests, cache-key checks, eviction exact prefix hits are available long enough
Chunked prefill / SARATHI size of scheduling units and mixed-batch reuse chunk overhead, attention reads of earlier tokens chunk efficiency and time-to-first-token (TTFT) / inter-token latency (ITL) target
Speculative decoding target-model steps for each accepted token draft work and state, verification time for each accepted token and sampling correctness
Reasoning effort / budget how much reasoning the model does, and how more tokens can increase cache size and time held ratio of added task quality (graded) to resource cost

Quality checks are different. The objective of exact attention and exact speculative sampling is the same computation or output distribution, apart from numerical effects. GQA and reasoning controls change the computation or the model's behavior. Outcome tests and speed tests are necessary.

6. Follow the bottleneck after each change

In this equal-length example, 16 ordinary decode requests give a projection about 15.9 FLOPs/byte. Their final unshared cache is 9 GiB. Whatever the compute capacity, the 8 GiB pool cannot hold them unless stored state or admission changes.

Apply the changes in this sequence:

  1. Make allocation better. Paging can decrease unused reservations. It cannot hold 9 GiB of filled unshared KV cache in 8 GiB. To increase this example's 14-request limit, use sharing, fewer stored bytes, shorter histories or more memory.
  2. Use a shared prefix again. In this hypothetical case, 14 requests share the same 4096-token prefix and each keeps its own 512-token tail. Their ideal filled cache is 512+14×64=1408512+14\times64=1408 MiB. Sharing removes this capacity limit, but the skipped prefill also removes rows for mixed batching. Measure execution again.
  3. Supply a prefill chunk. With available prompt work after a cache miss, chunking can make projection reuse better with few extra active requests. It also puts more work into one step, which can delay an interactive token.
  4. Decrease target steps. Speculative decoding decreases completion and cache occupancy time if accepted tokens save more than draft and verification cost. Draft memory can use all the capacity just recovered. A product of isolated speedups does not include this capacity cost.
  5. Use more reasoning. If 4096 generated tokens are necessary for the task, each equal-length request’s final unshared cache is 1 GiB. The unshared capacity limit decreases to eight. The longer trace must give a result that passes the grader and is worth that work. A short visible answer alone does not show this.

More memory, faster attention and larger batches each change a different limit.

Diagnostic matrix: measurements in four views for incorrect output, low throughput, admission failures and slow useful output.
Fig. 5. The matrix gives a likely limit and proposed measurements for each symptom in the token, GPU, memory and request views.

7. Select the next measurement

Select measurements that show differences between explanations. For a slow first useful token, measure queue time, uncached prompt work and hidden tokens before visible output. For later tokens, measure scheduler gaps, batch rows, step time and KV-cache reads. For capacity, measure filled and reserved bytes, sharing and occupancy over time.

Fig. 6. Give the name of the resource that a change affects. Predict the next limit. Compare one change under the same workload. The outcome selects the next measurement. Full interactive figure

Use the symptom and previous change to select the first view. It is not necessary to start with model cost.

Keep arrivals, lengths, prefix repetition, checkpoint, sampling and latency target fixed. Examine correctness when behavior changes. Give throughput at that quality and latency target, rather than unconstrained tokens for each second. The infrastructure essay applies this test to cost for each successful task.

Show the four views together:

Coupling map: token positions increase the KV cache, GPU cost and cache capacity give limits for request service, and request progress causes the next token.
Fig. 7. Each new token position adds cache. Compute cost and cache capacity limit request service, and request progress causes the next step. These are four connected views of one task, not a serial pipeline.

The arrows make a loop because each generated token adds context, cache and a scheduling decision. Predict which resource a change affects. Calculate how much limit it removes. Then measure the next bottleneck.

Key takeaways

  • More token rows use each weight load again. Each active request holds its own KV cache. Use different budgets for rows and requests.
  • Attention architecture, FlashAttention kernels, paging and prefix reuse each change a different cost.
  • Cache byte-seconds show the relation between generated length, time held and average cache use.
  • Different quality checks are necessary for exact execution improvements and reasoning controls.
  • Examine an optimization after its bottleneck changes, under the same task and service target.

Series navigation

Citation

Use this citation:

Ji, Wenbo. “A Token's Journey Across the LLM Stack”. fusheng-ji.github.io (June 2026). https://fusheng-ji.github.io/blog/posts/token-journey-across-llm-stack/

Or use the BibTeX entry:

@article{ji2026tokenjourneyacrossllmstack,
  title = {A Token's Journey Across the LLM Stack},
  author = {Ji, Wenbo},
  journal = {fusheng-ji.github.io},
  year = {2026},
  month = {June},
  url = {https://fusheng-ji.github.io/blog/posts/token-journey-across-llm-stack/}
}

References


Note: This blog was drafted and polished with assistance from ChatGPT and uses Aleksa Gordic's tutorials and the cited primary papers. The workload is hypothetical.

Updated 

Related notes