CSE Roadmap

Specialist tier · about 5 hours · 4 parts

Part 2 of 4 · 14 min read

Definitions

Covers: Definitions; The pipeline; Results; Design rules; Interview questions, with the follow-ups; Common mistakes; What the example does not do.

Definitions

Prefill and decode

  • Prefill: processing all input tokens in parallel to build the cache and the first output. Decode: generating one token per step, reading the whole model and cache each time.

TTFT and TPOT

  • TTFT: time to first token. TPOT: time per output token after the first.

KV cache

  • KV cache: stored attention keys and values of earlier tokens, so each step computes only the new token's.

Memory-bound and compute-bound

  • Memory-bound: step time set by bytes moved from memory. Compute-bound: set by arithmetic. The ridge point is where the two times are equal.

Static, dynamic and continuous batching

  • Static: wait for a full batch, finish all together. Dynamic: also start after a time window. Continuous: swap finished requests out and new ones in every step.

Speculative decoding

  • Speculative decoding: a draft model proposes K tokens, the target verifies them in one pass, and a rejection rule keeps the target's distribution.

Quantisation

  • Quantisation: storing numbers in fewer bits (weights, cache or activations) to cut memory and bandwidth, at some cost in accuracy.

The pipeline

AAAWgmp1bWIAAAAeanVtZGMycGEAEQAQgAAAqgA4m3EDYzJwYQAAABZcanVtYgAAAEdqdW1kYzJtYQARABCAAACqADibcQN1cm46YzJwYTo2ZDM2NjIyYi1hNWQyLTQxYTItOWVhOC1jMDAyNzA5MjIzZDMAAAADl2p1bWIAAAApanVtZGMyYXMAEQAQgAAAqgA4m3EDYzJwYS5hc3NlcnRpb25zAAAAALxqdW1iAAAARGp1bWRjYm9yABEAEIAAAKoAOJtxE2MycGEuaW5ncmVkaWVudC52MwAAAAAYYzJzaJQqEydsaJRe3AD01Cs+TKAAAABwY2JvcqNpZGM6Zm9ybWF0bWltYWdlL3N2Zyt4bWxqaW5zdGFuY2VJRHgseG1wOmlpZDo4YzlkZDEzZC01NjE4LTQzZDgtODdkZC1jNWM0NzE0MzI4ZGZscmVsYXRpb25zaGlwaHBhcmVudE9mAAAB4mp1bWIAAABBanVtZGNib3IAEQAQgAAAqgA4m3ETYzJwYS5hY3Rpb25zLnYyAAAAABhjMnNoc1iZI4IKkiwZIYH7T5JOJAAAAZljYm9yomdhY3Rpb25zgqJmYWN0aW9ua2MycGEub3BlbmVkanBhcmFtZXRlcnOha2luZ3JlZGllbnRzgaJjdXJseC1zZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmluZ3JlZGllbnQudjNkaGFzaFggNgiCXm3g4dTaN+DVNQnuuVakVM2wNixZPFy/PqOQFgukZmFjdGlvbngdY29tLmFudGhyb3BpYy5jbGF1ZGUucHJvdmlkZWRqcGFyYW1ldGVyc6F4H2NvbS5hbnRocm9waWMub3JpZ2luLWNvbmZpZGVuY2VndW5rbm93bmtkZXNjcmlwdGlvbnhmQ2xhdWRlIHByb3ZpZGVkIHRoaXMgZmlsZSBhdCB0aGUgcmVxdWVzdCBvZiBhIHVzZXIgYW5kIG1heSBoYXZlIGNyZWF0ZWQgb3IgbW9kaWZpZWQgdGhlIGZpbGUgY29udGVudHMubXNvZnR3YXJlQWdlbnShZG5hbWVmQ2xhdWRlcmFsbEFjdGlvbnNJbmNsdWRlZPUAAADIanVtYgAAAEBqdW1kY2JvcgARABCAAACqADibcRNjMnBhLmhhc2guZGF0YQAAAAAYYzJzaICnSpcblCzYTgAkWLz39IkAAACAY2JvcqVjYWxnZnNoYTI1NmNwYWRNAAAAAAAAAAAAAAAAAGRoYXNoWCDXKAPNc242kYy/uAj5r3PoM6omj5mAKcaVOnmgxy1EpmRuYW1lbmp1bWJmIG1hbmlmZXN0amV4Y2x1c2lvbnOBomVzdGFydBiuZmxlbmd0aBkeBAAAAj5qdW1iAAAAJ2p1bWRjMmNsABEAEIAAAKoAOJtxA2MycGEuY2xhaW0udjIAAAACD2Nib3KlY2FsZ2ZzaGEyNTZpc2lnbmF0dXJleE1zZWxmI2p1bWJmPS9jMnBhL3VybjpjMnBhOjZkMzY2MjJiLWE1ZDItNDFhMi05ZWE4LWMwMDI3MDkyMjNkMy9jMnBhLnNpZ25hdHVyZWppbnN0YW5jZUlEeCx4bXA6aWlkOmZhYTZlOWVhLTVkZTAtNGFlZS05YmY5LTZkODU1NzFmZjQ3YnJjcmVhdGVkX2Fzc2VydGlvbnODomN1cmx4LXNlbGYjanVtYmY9YzJwYS5hc3NlcnRpb25zL2MycGEuaW5ncmVkaWVudC52M2RoYXNoWCA2CIJebeDh1No34NU1Ce65VqRUzbA2LFk8XL8+o5AWC6JjdXJseCpzZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmFjdGlvbnMudjJkaGFzaFggi1AC5qpSodB8bVCUUMlMuvIfHwTPDoqOradQZk+yfyaiY3VybHgpc2VsZiNqdW1iZj1jMnBhLmFzc2VydGlvbnMvYzJwYS5oYXNoLmRhdGFkaGFzaFggJHSnAVVZOOkcM6PC+sIijwKkHmSDJ9akO5MmvUJYAgV0Y2xhaW1fZ2VuZXJhdG9yX2luZm+jZG5hbWVvQW50aHJvcGljIEZpbGVzZ3ZlcnNpb25lMS4wLjBrc3BlY1ZlcnNpb25lMi40LjAAABA4anVtYgAAAChqdW1kYzJjcwARABCAAACqADibcQNjMnBhLnNpZ25hdHVyZQAAABAIY2JvctKEWQISogEmGCFZAgowggIGMIIBjaADAgECAhRA5aAK7sI50L64g/oGQgU9Z1UTADAKBggqhkjOPQQDAzBJMRcwFQYDVQQKEw5BbnRocm9waWMsIFBCQzEuMCwGA1UEAxMlQW50aHJvcGljIENvbnRlbnQgQ3JlZGVudGlhbHMgUm9vdCBDQTAeFw0yNjA4MDcxODQzNTZaFw0yODA4MDYxOTQzNTZaMEQxFzAVBgNVBAoTDkFudGhyb3BpYywgUEJDMSkwJwYDVQQDEyBBbnRocm9waWMgQ2xhdWRlIENvbnRlbnQgU2lnbmluZzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJh6CmvLUBgFFNU0vUKlOVtE6djd17L5SuwX0LemFisBM3dkd/3cyjxFA3Qo5S46fX0/ihY0VZ7mfb9KF703t5OjWDBWMA4GA1UdDwEB/wQEAwIHgDAVBgNVHSUEDjAMBgorBgEEAYPoXgIBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUzlHiBIFOZFsj+OPEz5o+nMHXXMIwCgYIKoZIzj0EAwMDZwAwZAIwMXMdFJ4BetLLVY7ORuE9noqbbAZOZn/aArXyTwFAZfKrPzxF2vPoJNf1+UCdg1XGAjBwX1zd9WGqYkqmL5SFqw1QySjr1zJfpJM9+1rdDwSPLMOPOjKuiXjoU/pUUeG9RwmhY3BhZFkNngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZYQB81kV+oPeJ+zs3gRaQi+M44nki7/7NoOz3mVPQBvukZueLrD2Zx4zsCCXCUsxUgDv/wbgI6cJbmEPcntupzK4U=KV cache, batch size and step time (13B model, 80 GB GPU, assumed hardware)KV cache: positions the model must process to generate N tokens after a 5-token promptN = 20no cache 290 cache 25 max logit difference 4e-15N = 40no cache 980 cache 45 max logit difference 5e-15N = 80no cache 3,560 cache 85 max logit difference 7e-15N = 160no cache 13,520 cache 165 max logit difference 7e-15Largest batch that fits (weights 26 GB; KV cache 1.68 GB per 2,048-token sequence)512 tokens16-bit cache 128 8-bit cache 257 4-bit weights 175 (8x fewer KV heads: 1029)2,048 tokens16-bit cache 32 8-bit cache 64 4-bit weights 43 (8x fewer KV heads: 257)8,192 tokens16-bit cache 8 8-bit cache 16 4-bit weights 10 (8x fewer KV heads: 64)Decode step at 2,048 tokens: compute time vs memory time (ms) and tokens per secondbatchcomputememory (weights + KV cache)tokens/s10.0813.87240.3316.424580.6719.7406161.3326.4606322.6739.8803Compute is under 10% of the step time at every batch size here, so the GPU waits on memory: batching raises tokens per second, but sublinearly (batch 32: 11x batch 1).Without a KV cache the weights alone would hit the compute limit at a batch of about 156. Hardware numbers are assumed round figures; an A100-80GB is about 2 TB/s.
KV cache work, batch limits and decode-step time (assumed hardware).

Results

Tokens generated (5-token prompt) Positions, no cache Positions, cache Max logit difference
20 290 25 4e-15
40 980 45 5e-15
80 3,560 85 7e-15
160 13,520 165 7e-15
Sequence length 16-bit cache 8-bit cache 4-bit weights 1/8 as many KV heads (hypothetical)
512 128 257 175 1,029
2,048 32 64 43 257
8,192 8 16 10 64
Batch (sequence 2,048) Compute ms Memory ms Tokens per second
1 0.08 13.8 72
4 0.33 16.4 245
8 0.67 19.7 406
16 1.33 26.4 606
32 2.67 39.8 803
AAAWgmp1bWIAAAAeanVtZGMycGEAEQAQgAAAqgA4m3EDYzJwYQAAABZcanVtYgAAAEdqdW1kYzJtYQARABCAAACqADibcQN1cm46YzJwYTo3MTRmNzEzMi0wNjk0LTRiNmQtYjBkOC02YmUzNTJlNjIzNGQAAAADl2p1bWIAAAApanVtZGMyYXMAEQAQgAAAqgA4m3EDYzJwYS5hc3NlcnRpb25zAAAAALxqdW1iAAAARGp1bWRjYm9yABEAEIAAAKoAOJtxE2MycGEuaW5ncmVkaWVudC52MwAAAAAYYzJzaPMAbO4W/6IOxj2NMCPSlrIAAABwY2JvcqNpZGM6Zm9ybWF0bWltYWdlL3N2Zyt4bWxqaW5zdGFuY2VJRHgseG1wOmlpZDpmNjZjMDc3Ny0xMjVmLTRlM2EtYjUzNS04N2JjNTIxY2I2OTJscmVsYXRpb25zaGlwaHBhcmVudE9mAAAB4mp1bWIAAABBanVtZGNib3IAEQAQgAAAqgA4m3ETYzJwYS5hY3Rpb25zLnYyAAAAABhjMnNokbwCGWpUyFYJluunt9ioyAAAAZljYm9yomdhY3Rpb25zgqJmYWN0aW9ua2MycGEub3BlbmVkanBhcmFtZXRlcnOha2luZ3JlZGllbnRzgaJjdXJseC1zZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmluZ3JlZGllbnQudjNkaGFzaFggFZgfUIxh8vuvPayP2U0xybFGXFLLRCH5vyb7LDmdmMGkZmFjdGlvbngdY29tLmFudGhyb3BpYy5jbGF1ZGUucHJvdmlkZWRqcGFyYW1ldGVyc6F4H2NvbS5hbnRocm9waWMub3JpZ2luLWNvbmZpZGVuY2VndW5rbm93bmtkZXNjcmlwdGlvbnhmQ2xhdWRlIHByb3ZpZGVkIHRoaXMgZmlsZSBhdCB0aGUgcmVxdWVzdCBvZiBhIHVzZXIgYW5kIG1heSBoYXZlIGNyZWF0ZWQgb3IgbW9kaWZpZWQgdGhlIGZpbGUgY29udGVudHMubXNvZnR3YXJlQWdlbnShZG5hbWVmQ2xhdWRlcmFsbEFjdGlvbnNJbmNsdWRlZPUAAADIanVtYgAAAEBqdW1kY2JvcgARABCAAACqADibcRNjMnBhLmhhc2guZGF0YQAAAAAYYzJzaJ0wzFwKMGWg/MmNc0JHfDQAAACAY2JvcqVjYWxnZnNoYTI1NmNwYWRNAAAAAAAAAAAAAAAAAGRoYXNoWCBvXYTIg/mL/x86wLKB8pyIYvNgl6rlg7NqYw49S3/0smRuYW1lbmp1bWJmIG1hbmlmZXN0amV4Y2x1c2lvbnOBomVzdGFydBidZmxlbmd0aBkeBAAAAj5qdW1iAAAAJ2p1bWRjMmNsABEAEIAAAKoAOJtxA2MycGEuY2xhaW0udjIAAAACD2Nib3KlY2FsZ2ZzaGEyNTZpc2lnbmF0dXJleE1zZWxmI2p1bWJmPS9jMnBhL3VybjpjMnBhOjcxNGY3MTMyLTA2OTQtNGI2ZC1iMGQ4LTZiZTM1MmU2MjM0ZC9jMnBhLnNpZ25hdHVyZWppbnN0YW5jZUlEeCx4bXA6aWlkOmQ0ZmYyYjBhLTgyNjgtNDZlMS05YjY2LWJhYTZlZTZhMWIzNHJjcmVhdGVkX2Fzc2VydGlvbnODomN1cmx4LXNlbGYjanVtYmY9YzJwYS5hc3NlcnRpb25zL2MycGEuaW5ncmVkaWVudC52M2RoYXNoWCAVmB9QjGHy+689rI/ZTTHJsUZcUstEIfm/JvssOZ2YwaJjdXJseCpzZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmFjdGlvbnMudjJkaGFzaFggiXt+0At/uc6ftG7y+ddRxto4B7Kwiqx4rsXWtQONMpCiY3VybHgpc2VsZiNqdW1iZj1jMnBhLmFzc2VydGlvbnMvYzJwYS5oYXNoLmRhdGFkaGFzaFggfM39/zueVQYS4dKUCjw+BtO8Oj6uTo/erI6Y2YkNMYl0Y2xhaW1fZ2VuZXJhdG9yX2luZm+jZG5hbWVvQW50aHJvcGljIEZpbGVzZ3ZlcnNpb25lMS4wLjBrc3BlY1ZlcnNpb25lMi40LjAAABA4anVtYgAAAChqdW1kYzJjcwARABCAAACqADibcQNjMnBhLnNpZ25hdHVyZQAAABAIY2JvctKEWQISogEmGCFZAgowggIGMIIBjaADAgECAhRA5aAK7sI50L64g/oGQgU9Z1UTADAKBggqhkjOPQQDAzBJMRcwFQYDVQQKEw5BbnRocm9waWMsIFBCQzEuMCwGA1UEAxMlQW50aHJvcGljIENvbnRlbnQgQ3JlZGVudGlhbHMgUm9vdCBDQTAeFw0yNjA4MDcxODQzNTZaFw0yODA4MDYxOTQzNTZaMEQxFzAVBgNVBAoTDkFudGhyb3BpYywgUEJDMSkwJwYDVQQDEyBBbnRocm9waWMgQ2xhdWRlIENvbnRlbnQgU2lnbmluZzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJh6CmvLUBgFFNU0vUKlOVtE6djd17L5SuwX0LemFisBM3dkd/3cyjxFA3Qo5S46fX0/ihY0VZ7mfb9KF703t5OjWDBWMA4GA1UdDwEB/wQEAwIHgDAVBgNVHSUEDjAMBgorBgEEAYPoXgIBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUzlHiBIFOZFsj+OPEz5o+nMHXXMIwCgYIKoZIzj0EAwMDZwAwZAIwMXMdFJ4BetLLVY7ORuE9noqbbAZOZn/aArXyTwFAZfKrPzxF2vPoJNf1+UCdg1XGAjBwX1zd9WGqYkqmL5SFqw1QySjr1zJfpJM9+1rdDwSPLMOPOjKuiXjoU/pUUeG9RwmhY3BhZFkNngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZYQEK3SR2Mfotc3s4BDPPGhLcZFVRhN2msiXudQtVMXoozJ2iCekzqzPU5KlBajAj8ShgdjOJ02ww+rlUTjDaKSJI=Continuous batching, speculative decoding and quantisation (toy simulations)Median and p95 latency in decoding steps; 8 slots; mean output 78 tokens, mean longest in a batch of 8 203requests per stepstatic p50 / p95dynamic (window 20)continuousutilisation s / d / c0.01483 / 1,134139 / 46758 / 2040.38 / 0.16 / 0.180.02370 / 735199 / 56058 / 2020.39 / 0.22 / 0.240.03369 / 715299 / 72659 / 2060.39 / 0.29 / 0.320.04791 / 1,547805 / 1,56758 / 2110.39 / 0.37 / 0.410.077,811 / 14,5598,022 / 14,68564 / 2160.39 / 0.39 / 0.69Naive batching holds every response until the longest in its batch ends, so it saturates near 0.039 requests per step (continuous: about 0.10).Speculative decoding: speed-up over plain decoding by acceptance rate (draft cost c = 0.128 of a target step, a 4B draft against a 70B Chinchilla target, 1.8 vs 14.1 ms)acceptance 0.51.39x with K = 2 (1.94 tokens per verification at K = 4)acceptance 0.71.83x with K = 4 (2.77 tokens per verification at K = 4)acceptance 0.82.25x with K = 5 (3.36 tokens per verification at K = 4)acceptance 0.93.03x with K = 9 (4.10 tokens per verification at K = 4)Correctness: the accept/reject rule reproduced the target distribution (distance 0.006 and 0.005) although the draft was 0.15 and 0.47 away from it.Quantisation on the tiny model: KL from the 16-bit model and top-1 agreement (weights | KV cache)8 bitsweights KL 0.000, agree 1.00KV cache KL 0.0000, agree 1.006 bitsweights KL 0.001, agree 0.97KV cache KL 0.0001, agree 1.004 bitsweights KL 0.027, agree 0.93KV cache KL 0.0019, agree 0.983 bitsweights KL 0.113, agree 0.88KV cache KL 0.0113, agree 0.962 bitsweights KL 0.847, agree 0.70KV cache KL 0.0914, agree 0.88
Batching policies, speculative decoding speed-up and quantisation (toy simulations).
Requests per step Static p50 / p95 Dynamic p50 / p95 Continuous p50 / p95 Utilisation (s / d / c)
0.01 483 / 1,134 139 / 467 58 / 204 0.38 / 0.16 / 0.18
0.02 370 / 735 199 / 560 58 / 202 0.39 / 0.22 / 0.24
0.03 369 / 715 299 / 726 59 / 206 0.39 / 0.29 / 0.32
0.04 791 / 1,547 805 / 1,567 58 / 211 0.39 / 0.37 / 0.41
0.07 7,811 / 14,559 8,022 / 14,685 64 / 216 0.39 / 0.39 / 0.69
Draft cost c a = 0.5 a = 0.7 a = 0.8 a = 0.9
0.05 (best K, speed-up) 3, 1.63x 6, 2.35x 8, 3.09x 13, 4.67x
0.128 (best K, speed-up) 2, 1.39x 4, 1.83x 5, 2.25x 9, 3.03x
Tokens per verification at K=4 1.94 2.77 3.36 4.10
Bits Weights: KL, top-1 agreement KV cache: KL, top-1 agreement
8 0.00007, 0.997 0.00001, 0.998
6 0.0014, 0.975 0.0001, 0.997
4 0.027, 0.931 0.0019, 0.982
3 0.113, 0.875 0.011, 0.959
2 0.847, 0.705 0.091, 0.884
  1. The cache trades memory for compute, and at scale memory is the scarcer resource.
  2. Decode is memory-bound, so reducing bytes (quantisation, fewer KV heads, shorter context) helps more than adding FLOPs.
  3. Batching raises throughput sublinearly because the cache grows with the batch.
  4. Continuous batching mostly removes waiting, not compute: latency stayed near 60 steps median while static batching collapsed.
  5. Speculative decoding pays only when acceptance is high and the draft is cheap.
  6. Quantisation sensitivity must be measured; it differs between weights and cache and between models.

Design rules

  • Measure TTFT and TPOT separately, and name which one your users feel.
  • Size the cache first: batch x sequence x layers x hidden x 2 x bytes decides how many requests fit.
  • Use continuous batching for variable-length outputs; static batching wastes slots on the longest reply.
  • Quantise one thing at a time and compare quality on your own evaluation set, not only perplexity.
  • Check acceptance rate on your real traffic before adopting speculative decoding; pick K from it.
  • Put stable content first in prompts so prefix caching can reuse it.
  • Report hardware, batch, sequence length and precision with every latency number.
  • Treat vendor speed-ups as upper bounds until you reproduce them on your workload.

Interview questions, with the follow-ups

Why is decoding memory-bound and prefill compute-bound?

"Prefill processes many tokens in one pass, so the weights read from memory are reused across all of them and arithmetic dominates. Decode produces one token per sequence per step, so every step reads all the weights and the cache for little arithmetic. In my model compute was under 10 percent of the step time at every feasible batch." Follow-up: "What would make decode compute-bound?" A large batch; without the cache the ridge in my model was near batch 156, but the cache grows with the batch and memory fills first.

How does the KV cache work and what does it cost?

"It stores keys and values of past tokens so each step computes only the new one: linear instead of quadratic work, with identical outputs (mine matched to 1e-14). The cost is 2 x batch x sequence x layers x hidden x bytes; the Llama 2 13B example is 54 GB at batch 32 and 2,048 tokens." Follow-up: "How do you reduce it?" Quantise it, use fewer key-value heads, use paged allocation, or shorten context.

Static versus continuous batching?

"Static waits for the slowest request in a batch; with variable output lengths most slots idle. Continuous batching refills a slot as soon as a request ends. In my simulation static saturated near 0.039 requests per step and continuous near 0.10, and at 0.07 static latency exploded while continuous stayed near 64 steps median." Follow-up: "What do you give up?" Scheduler complexity and per-step overhead, which my simulation ignores.

When does speculative decoding help?

"When the draft is much cheaper than the target and agrees often. Expected tokens per verification is (1 - a^(K+1)) / (1 - a) and the cost is K draft steps plus one target step. At draft cost 0.128 I needed acceptance near 0.8 for a 2x gain. The rejection rule keeps the target distribution, so quality is unchanged." Follow-up: "Does it help at large batch?" Less: a compute-bound server has no spare compute to spend on verifying extra tokens (my model does not cover this).

Common mistakes

  • Quoting one latency number without batch, sequence length and hardware.
  • Ignoring the cache when sizing a GPU.
  • Using static batching for variable-length generation.
  • Assuming quantisation is free or uniformly harmful.
  • Choosing K without measuring acceptance rate.
  • Putting changing text at the start of a prompt, defeating prefix caching.
  • Optimising TPOT when TTFT is the complaint.
  • Trusting a vendor's speed-up on a different workload.

What the example does not do

  • No GPU or kernels: time comes from a two-term formula (bytes over bandwidth, FLOPs over peak); real kernels, launch overhead and communication change it.
  • Assumed peak: 312 TFLOP/s is my assumption for an A100-class GPU; the 2 TB/s figure is the published A100-80GB bandwidth, rounded.
  • The batching simulation uses one step as the time unit, no prefill cost and no preemption.
  • The quantisation toy uses random weights, so its tolerance to bits is not evidence about trained models; the cache vs weights ordering may differ.
  • No paged attention, FlashAttention, tensor parallelism, or disaggregated prefill.
  • Speculative decoding is tested on a synthetic draft with controlled disagreement, not a real small model.
  • Optional real experiment (I did not run this): serve a small open model with vLLM or llama.cpp, measure TTFT, TPOT and throughput at batch 1, 8 and 32, then repeat with a quantised build and prefix caching on.

Check yourself

Why does the KV cache, not the weights, limit how many requests one GPU can serve? (Weights are a fixed cost, while the cache grows with batch size and sequence length. For Llama 2 13B at batch 32 and 2,048 tokens the cache is 53.69 GB, twice the 26 GB of weights.)

For the curious Batching policy changes latency more than speed

Static batching holds every reply until the longest in its batch finishes; continuous batching refills a slot the moment a reply ends. At 0.04 requests per step the p95 was 1,547 steps for static and 211 for continuous, and at 0.07 static was overloaded. Speculative decoding keeps the target model's output distribution exactly, and pays off only when the draft's acceptance rate is high (about 0.8 or more for a 2x gain at c = 0.128). The hardware figures are assumed round numbers and the model is tiny.

What you will use daily at work

Practice What it looks like
Cache stable prompt prefixes System prompt, tool list, long documents.
Size the batch from cache memory Weights fixed, cache per sequence.
Quantise weights or cache only after measuring quality Compare on your own eval.
Watch TTFT and TPOT separately Prefill and decode have different fixes.

Draft: confirm the serving stack you will use (hosted API or your own) and its current batching, caching and quantisation options and prices.

What you must be able to say (one page)

  • Two phases, two bottlenecks. Prefill (processing the input tokens) is compute-bound and decode (generating output tokens one by one) is memory-bandwidth-bound. The two latency metrics follow: TTFT (time to first token, dominated by prefill) and TPOT (time per output token, dominated by decode).
  • The KV cache removes repeated work. Without it, each new token recomputes keys and values for the whole prefix. In my NumPy transformer, cached and uncached generation gave identical tokens and a maximum logit difference near 7e-15; positions processed to generate N tokens after a 5-token prompt were 25 vs 290 (N=20), 45 vs 980 (N=40), 85 vs 3,560 (N=80) and 165 vs 13,520 (N=160): linear against quadratic. Wall time at N=160 was 0.022 s vs 0.310 s on my machine (machine-specific).
  • The cache costs memory. Size = 2 x batch x sequence x layers x hidden x bytes. For Llama 2 13B (batch 32, sequence 2,048, 16-bit) the cache is 53.69 GB, more than the 26 GB of weights. Per sequence: 0.42, 1.68 and 6.71 GB at 512, 2,048 and 8,192 tokens.
  • So the cache sets the batch size. On an 80 GB GPU with 13B 16-bit weights, my arithmetic gives a largest batch of 128, 32 and 8 at 512, 2,048 and 8,192 tokens. An 8-bit cache doubles that (257, 64, 16); 4-bit weights help much less (175, 43, 10) because weights are a fixed cost and the cache scales with batch.
  • Decode is memory-bound, so batching is nearly free until it is not. My roofline-style model (312 TFLOP/s assumed for an A100-class GPU, about 2 TB/s for an A100-80GB) at sequence 2,048: batch 1 takes 13.8 ms (72 tokens/s), batch 32 takes 39.8 ms (803 tokens/s): 32 times the work for 2.9 times the time, but only 11 times the throughput, because the growing cache adds bytes to read. Compute is under 10 percent of the step time at every feasible batch size. Ignoring the cache, the weights alone would turn compute-bound near a batch of 156.
  • Batching policy changes latency more than speed. Slot limit 8, mean output 78 tokens, mean longest-of-8 203 tokens. Static batching holds every reply until the longest in its batch finishes and saturates near 0.039 requests per step; continuous batching (the idea behind Orca) refills a slot the moment a reply ends and saturates near 0.10. At 0.04 requests per step: static p50 791, p95 1,547; continuous p50 58, p95 211. At 0.07 static is overloaded (p50 7,811) while continuous holds 64.
  • Speculative decoding: a cheap draft model proposes K tokens; the target model checks them in one pass and keeps the longest agreeing prefix. With the accept/reject rule the output distribution equals the target's: in my test the total-variation distance to the target was 0.006 and 0.005 while the draft itself was 0.15 and 0.47 away. Expected tokens per verification = (1 - a^(K+1)) / (1 - a) for acceptance rate a; speed-up = that divided by (K c + 1) where c is draft cost relative to a target step.
  • How much speed-up? With c = 0.128 (a 70B Chinchilla target at 14.1 ms against a 4B draft at 1.8 ms, from the speculative sampling paper as I recall it): a=0.5 gives 1.39x (K=2); 0.7 gives 1.83x (K=4); 0.8 gives 2.25x (K=5); 0.9 gives 3.03x (K=9). In my model, cutting latency by more than half needs roughly an acceptance rate of at least 0.8.
  • Quantisation (tiny model, KL from the 16-bit model and top-1 agreement): weights at 8, 6, 4, 3, 2 bits gave KL 0.00007, 0.0014, 0.027, 0.113, 0.847 and agreement 0.997, 0.975, 0.931, 0.875, 0.705; the KV cache at the same bit widths gave KL 0.00001, 0.0001, 0.0019, 0.011, 0.091 and agreement 0.998, 0.997, 0.982, 0.959, 0.884. In this toy the cache tolerated fewer bits than the weights; this is a toy, so measure on your model.
  • Prompt caching: reusing a processed prefix. My arithmetic: a 1,000-token prompt at 1M calls a day is 1B tokens, $3,000 a day at an assumed $3 per million, or $300 with a 90 percent discount (Anthropic announced up to 90 percent lower cost for cached input when it launched prompt caching; check current terms before you plan on any discount).
  • What to say in an interview: "Prefill is compute-bound, decode is memory-bound. I use a KV cache, size it to set the batch, use continuous batching and quantise weights or cache after measuring quality, add speculative decoding when the draft's acceptance rate is high enough to pay for its cost, and cache stable prompt prefixes."
  • Honest limits: a tiny NumPy model, an arithmetic hardware model with assumed peak FLOPs, a toy request simulator; no GPU kernels, no paged attention, no FlashAttention, no real serving stack.