CS2680 Modern AI Systems: Agents and System Optimizations
Lecture Notes

Lecture notes published alongside the slides. They carry the derivations, assumptions, and worked arithmetic that a slide can only summarize.

Read them either way round. Before class they tell you what the readings are for and what question the lecture is answering; after class they are where the numbers live, worked out step by step so you can check them. Every quantitative claim is either derived in the text or taken from a stated source, so if you do not believe a number you can find out where it came from — and tell me if it is wrong.

Each note ends with self-check questions and a reading guide. The self-check questions are the fastest way to find out whether you actually followed the lecture; the reading guide tells you what to look for in each assigned paper and what you can safely skip.

Tentative: these notes are drafted before the semester and will be corrected as the course runs. If a number looks wrong, it may well be — say so in class or by email, and you may earn bonus credit for it.

Part I — Introduction to LLMs and Agents

Lecture 1 · Wed Sep 2
Course overview and logistics

What this course is and is not, the stack we spend the semester walking down, and the back-of-the-envelope calculation showing that for any model with real usage the lifetime bill is dominated by serving rather than training.

Lecture 2 · Wed Sep 9
Modern ML basics: transformers, training, and where inference cost comes from

A transformer block as a small pile of matrix multiplies: parameter counting, where the FLOPs go, and the four consumers of training memory. Then the training loop and where its factor of three comes from, and the worked budget that puts the reference 7B’s persistent state at 107.8 GB against an 80 GB card — which is why distributed training is a requirement rather than an optimization. Then the same model forwards only: prefill against decode, the roofline, and the collision that organises the rest of the semester — the hardware wants a decode batch of 295 and the KV cache permits 29.

Lecture 3 · Mon Sep 14
Agents from a user’s perspective

What an agent is, minimally. Where the tokens actually go across a multi-turn session, why context is the scarce resource, and how to tell a model failure from a harness, tool, or specification failure. Assignment 1 is in flight, due Sep 20.

Lecture 4 · Wed Sep 16
Agents from a designer’s perspective I: the loop, tools, and context

Writing the loop yourself rather than importing one: tool interfaces as API design, retries and error recovery, stopping conditions, and context management as a cache policy. Assignment 2 goes out.

Lecture 5 · Wed Sep 23
Agents from a designer’s perspective II: specification, verification, and evaluation

The distance between a loop that runs and an agent that works: the specification you ship and the two lines of it your own code reads, the verifier placed inside the loop and what its output costs, and the frozen task set that is the only instrument able to say whether a change helped. Then diagnosis, instrumentation, and when one context is not the design.

Optional content

Written as lectures, then taken off the schedule — both notes below are part of the optional content now: not lectured, and nothing later assumes them. Lecture 6 is still the most directly useful note for Assignments 1 and 2, and Lecture 24 closed the LLMs-for-systems block that used to run as Part III; both stay up. Their readings are on the readings page, under working with agents and LLMs for systems.

Part II — Systems for LLMs

Lecture 7 · Mon Sep 28
GPU programming for MLSys: architecture, memory, and kernels

How a GPU trades everything a CPU uses to make one thread finish sooner for the ability to keep thousands in flight: the memory hierarchy, occupancy and latency hiding, coalescing, tensor cores, and Triton as a language in which a kernel is a readable object. The semester’s one GPU programming meeting, and the machine every later number is measured against.

Lecture 9 · Wed Sep 30
Efficient LLM computing: GPU kernels

Attention as normally written moves a matrix nobody wants through HBM twice, which pins it at 64 FLOP/byte and 22% of an H100. Keeping the score matrix on chip makes intensity S/2 and crosses the ridge point at 590 tokens — so FlashAttention’s memory win is categorical (68.7 GB that does not fit becomes 33.5 MB) and its speed win obeys Amdahl. Then why none of it rescues decode.

Lecture 10 · Mon Oct 5
Efficient LLM serving: paging and the KV allocator

A serving engine is mostly an allocator, and the naive one reserves KV to the maximum sequence length: 15% memory utilization and 29 concurrent sequences where the bytes would have held 200. Paging the cache fixes it — 29 to 199 — and the same block table turns out to make sharing, migration, and preemption possible. After it, the SLO binds before the memory does.

Lecture 11 · Mon Oct 5
Efficient LLM serving: batching and scheduling I

A static batch runs until its longest member finishes, so a batch of thirty-two is a batch of eight. Re-forming the batch every iteration recovers 4.05× from bookkeeping alone, and it works only because the cache is paged. Then selective batching, head-of-line blocking priced in milliseconds, and the length prediction nobody has.

Lecture 12 · Wed Oct 7
Efficient LLM serving: batching and scheduling II — disaggregation

Prefill is compute-bound and latency-tolerant; decode is bandwidth-bound and latency-critical; continuous batching put them in the same queue. Two answers: chunk the prefill until no step is dominated by it, or split the phases onto separate pools and ship the KV cache between them. The pool ratio a chat workload wants is 1.3 to 1; an agent workload wants 12 to 1.

Lecture 17 · Wed Oct 14
Efficient LLM serving: routing and load balancing

One card became many, and an LLM replica has warm state — so the router is a cache-placement policy that also has to respect queueing and capacity. Live migration of a running request costs 1.3 ms over NVLink against 129 ms to kill and recompute, and the affinity rule is an inequality: chase the prefix when the extra queueing is worth less than the prefill it saves.

Lecture 14 · Mon Oct 19
Efficient LLM serving: KV-cache optimization I

Every number in Part II is proportional to 512 KiB per token, and there are four ways to attack it. Fewer heads, fewer bits, fewer tokens — composing to 25.6× and taking concurrency from 29 to 744. It is also where Part II crosses the line from exact optimizations to approximate ones, which need a different kind of evidence.

Lecture 25 · Wed Oct 21
Efficient LLM serving: KV-cache optimization II

The two families that do not shrink the cache: read fewer of the tokens you kept, which buys TPOT and no concurrency at all, and move the bytes to another tier, which buys capacity and costs TPOT. One question sorts them — how many sequences fit — and one inequality, on its fifth appearance, prices every tier against recomputing.

Lecture 13 · Wed Nov 4
Efficient LLM serving: prefix cache

Causal attention makes a prefix’s KV cache a pure function of that prefix, so the 92% of prompt tokens an agent re-sends becomes recoverable machine time. RadixAttention’s tree, cache-aware scheduling, what a hit rate is worth in prefill FLOPs and TTFT, and the eviction policy the design space actually turns on.

Lecture 15 · Mon Nov 9
Efficient LLM serving: pruning and quantization

How GPTQ and AWQ reach 4 bits with no retraining, by two opposite philosophies — compensate every rounding error, or protect the weights that matter. Then the half the accuracy tables leave out: why a 4-bit checkpoint can serve slower than an 8-bit one when dequantization lands in the GEMM’s main loop.

Lecture 16 · Wed Nov 11
Efficient LLM serving: speculative decoding

The decode floor says one pass over 13.5 GB yields one token, and 99.66% of the arithmetic is idle. A cheap draft proposes several tokens and the target checks them all in one pass, with a rejection rule that preserves the output distribution exactly. The catch: it spends spare FLOPs, so at a large enough batch it becomes a net loss.

Lecture 18 · Wed Nov 18
Efficient agent serving systems I: declared structure and the request DAG

What becomes possible when the application tells the serving system its structure instead of handing it finished strings: Parrot’s Semantic Variables and the explicit request DAG, the three things they buy, and the same 20-step task scheduled with and without that information.

Lecture 22 · Wed Nov 18
Efficient agent serving systems I (continued): scheduling agentic programs

The second half of the Nov 18 meeting. What a scheduler can do when the application declares nothing — because most clients never will. Autellix recovers most of shortest-job-first without clairvoyance by accounting service per program rather than per request, which also exposes a 67× fairness bug hiding inside a neutral-looking policy.

Lecture 19 · Mon Nov 23
Efficient agent serving systems II: tool stalls, interception, and the sandbox

Half an agent session’s wall clock is spent generating nothing, and the session does not become free while it waits — it holds its KV cache, its scheduler slot, and a sandbox nobody budgets for. The stall priced in three currencies, the two break-evens deciding keep, swap, or discard, and a throughput expression that stops depending on how long the tools take.

Lecture 20 · Mon Nov 23
Efficient agent serving systems II (continued): session state and agent memory

Where a stalled session’s cache should live when the answer is “not here”. The fetch-versus-recompute line at session scale, the tier table, and what the client’s context policy does to the server’s cache — including the retention question nobody sets deliberately.

Lecture 21 · Mon Nov 23
Efficient agent serving systems II (continued): multi-agent workloads and performance optimization

Multi-agent workloads as a serving problem: four shapes, context isolation priced, why fan-out is the best case a prefix cache ever sees, and what a barrier does to a scheduler that cannot anticipate it. Then multi-agent systems used for performance optimization, and whether a fleet beats a good ruler.