<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Inference From First Principles on Programmer.ie: Modern AI programming</title>
		<link>http://programmer.ie/books/inference/</link>
		<description>Recent content in Inference From First Principles on Programmer.ie: Modern AI programming</description>
		<generator>Hugo</generator>
		<language>en-US</language>
		
		
		
		
			<lastBuildDate>Thu, 22 Oct 2026 00:00:00 +0100</lastBuildDate>
		
			<atom:link href="http://programmer.ie/books/inference/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>What Is Inference?</title>
				<link>http://programmer.ie/books/inference/01-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/01-chapter/</guid>
				<description>&lt;p&gt;I asked a 124-million-parameter model to continue a sentence by sixteen tokens. On a CPU it took about 2.7 seconds. The answer was:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;An inference engine takes a trained model and a request, and it must turn them into a model that can be used to generate a model that can be used to generate&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Three things are true of that result at once. It was slow for something that produced a few dozen characters. It was repetitive to the point of being useless. And it was entirely correct, in the sense that the program did exactly what greedy decoding of that model is defined to do. Run it again and you get the same sixteen tokens.&lt;/p&gt;</description>
			</item>
			<item>
				<title>From Training to Execution</title>
				<link>http://programmer.ie/books/inference/02-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/02-chapter/</guid>
				<description>&lt;p&gt;The GPT-2 file on my disk is 548,105,171 bytes. The model it contains has 124,439,808 parameters, and each is a 32-bit float, so the parameters occupy 497,759,232 bytes. About 50 megabytes of the file are not parameters at all.&lt;/p&gt;&#xA;&lt;p&gt;That gap is a small thing, and it is the whole subject of this chapter in miniature. We say &amp;ldquo;the model&amp;rdquo; as though it were one object, a block of learned numbers. What actually arrives from training is a bundle of things: tensors that were learned, tensors that were not, a description of how to wire them together, a tokeniser, default generation settings, and the code that interprets all of them. An inference system has to take that bundle and turn it into something that executes. Between the two lie decisions that nobody made explicitly, and several of them change what the model does.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Tokens, Embeddings and Probability</title>
				<link>http://programmer.ie/books/inference/03-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/03-chapter/</guid>
				<description>&lt;p&gt;Chapter 1 ended with a sentence that looped. Forty greedy steps from the same prompt produce this:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;An inference engine takes a trained model and a request, and it must turn them into a model that can be used to generate a model that can be used to generate a model that can be used to generate a model that can be used to generate a model that can be used to generate&lt;/p&gt;</description>
			</item>
			<item>
				<title>The Transformer as a Computation</title>
				<link>http://programmer.ie/books/inference/04-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/04-chapter/</guid>
				<description>&lt;p&gt;I wrote GPT-2&amp;rsquo;s forward pass out by hand. It is about forty lines of tensor operations: an embedding lookup, twelve repetitions of a block built from layer norm, attention and a two-layer feed-forward network, a final layer norm, and a matrix product. Fed the weights of the real model, it returns logits that agree with the library&amp;rsquo;s to within \(1.2 \times 10^{-4}\) on logits as large as 323 in magnitude, and picks the same most probable token at every position of four different prompts.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Autoregressive Generation</title>
				<link>http://programmer.ie/books/inference/05-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/05-chapter/</guid>
				<description>&lt;p&gt;Generating 64 tokens from GPT-2 on my CPU took 11.5 seconds. I then took the 64 tokens it had produced, appended them to the prompt, and ran the model once over the whole 81-token sequence. That took 0.42 seconds, and at every one of the 64 positions the model&amp;rsquo;s most probable next token was exactly the token the slow loop had chosen.&lt;/p&gt;&#xA;&lt;p&gt;Producing the answer was 27 times slower than checking it. That asymmetry is the most important structural fact about generation, and the rest of Part III is largely a sequence of ways to exploit it. We should be careful about the number, and I will qualify it below, because the slow loop is a naive one and a competent loop would narrow the gap. But the direction is not in doubt, and it rests on a distinction that is easy to blur: &lt;strong&gt;autoregressive generation is serial in which tokens are chosen, and parallel in how tokens are scored.&lt;/strong&gt;&lt;/p&gt;</description>
			</item>
			<item>
				<title>Building Our First Inference Engine</title>
				<link>http://programmer.ie/books/inference/06-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/06-chapter/</guid>
				<description>&lt;p&gt;The sampler in this chapter&amp;rsquo;s original engine had a bug that no test caught and no output revealed. Step \(k\) of a request with seed \(s\) used the random seed \(s + k\). That looks harmless, and it means that request 2&amp;rsquo;s step 0 draws the same random number as request 1&amp;rsquo;s step 1, request 3&amp;rsquo;s step 0 the same as request 2&amp;rsquo;s step 1, and so on. For 100 requests of 32 steps each, 3,200 draws needed 3,200 independent random streams, and the scheme provided 131. When I fed two requests the same scores at every step, the output of seed 2 was an exact one-step-shifted copy of seed 1 in all 31 compared positions.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Matrix Multiplication and GPU Execution</title>
				<link>http://programmer.ie/books/inference/07-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/07-chapter/</guid>
				<description>&lt;p&gt;The engine from Chapter 6 generates 32 tokens from GPT-2 in 6.4 seconds on one CPU thread. Move the same weights to the GPU in this machine and it takes 0.45 seconds. The output is the same 32 tokens. That is a 14-fold improvement, and it should feel too small.&lt;/p&gt;&#xA;&lt;p&gt;The same GPU multiplies two large matrices at about 7,000 billion floating-point operations per second. One CPU thread manages about 53 billion. That is a ratio of roughly 130. So where did the other 90 per cent of the advantage go? Part of the answer is that a language model is not one large matrix multiplication. It is hundreds of small ones, and small ones behave differently. A single-token step through the output layer of GPT-2 uses about 2 per cent of the arithmetic this GPU can deliver. The chip spends the rest of that time waiting for weights to arrive from memory. Another part of the answer is that, below a certain size, a GPU call costs about 35 microseconds whatever it computes, and a CPU can multiply two small matrices in a tenth of that.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Attention and Its Computational Cost</title>
				<link>http://programmer.ie/books/inference/08-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/08-chapter/</guid>
				<description>&lt;p&gt;For a 16,384-token sequence with GPT-2&amp;rsquo;s twelve heads in half precision, one attention score tensor is 6.0 GiB. A straightforward implementation of attention needs two of them at once. On this machine it asked for 12.3 GiB, on a card with 12, and did not fail. I will explain below why it did not, because the explanation is itself instructive. PyTorch&amp;rsquo;s own attention function, given the same inputs, used 24 MiB, which is the size of its output. The two agreed on the result to within the rounding error of 16-bit floating point, and the second was eleven times faster at a length of 8,192.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Prefill and Decode</title>
				<link>http://programmer.ie/books/inference/09-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/09-chapter/</guid>
				<description>&lt;p&gt;On this machine, GPT-2 takes 12 milliseconds to read a 16-token prompt and produce its first token, and 11 milliseconds for each token after that. Give it a prompt of 1,000 tokens and the first token takes 44 milliseconds, but the tokens after it still take 11. A 64-token reply to the short prompt spends 98 per cent of its time in the second phase. A 4-token reply to the long prompt spends 56 per cent in the first.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Key-Value Caching</title>
				<link>http://programmer.ie/books/inference/10-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/10-chapter/</guid>
				<description>&lt;p&gt;I reused a key-value cache built for one prompt to continue a different one. Nothing raised an error. The next-token scores were off by 11.6 on the median across twenty trials, and by 28.7 in the worst, and the model picked the right next token in only 40 per cent of them. In a second experiment I built the cache with weights that differed from the real ones by 2 per cent in a single layer, as an adapter swap might. The scores were off by 0.04, and the right token came out in 20 trials of 20.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Memory Bandwidth and Compute Bottlenecks</title>
				<link>http://programmer.ie/books/inference/11-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/11-chapter/</guid>
				<description>&lt;p&gt;I wrote down a prediction for how long 58 different GPU operations should take, using nothing but their size and three numbers measured on this machine. The median measurement came out 10 to 14 per cent above the prediction. At least nineteen in twenty were within a factor of two. And not one memory-bound operation ran faster than its bound, which is what a bound is for.&lt;/p&gt;&#xA;&lt;p&gt;Then I used the same model to predict the time of a whole decode step as the batch size grew, and it was wrong by a factor of three. It said the step would stay at its floor until a batch of around 256. The measured step started to climb at 64, and at 256 it was 30 milliseconds against a prediction of 10.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Quantization and Numerical Precision</title>
				<link>http://programmer.ie/books/inference/12-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/12-chapter/</guid>
				<description>&lt;p&gt;I quantised the same matrix, the 38.6-million-entry embedding table of GPT-2, to four bits in two different ways. Applied to the input side, where tokens are looked up, it cost 0.7 per cent in perplexity. Applied to the output side, where the same numbers produce the scores for the next token, perplexity went from 61 to 8,123. The same matrix, the same error of about 13 per cent in its weights, and a difference of four orders of magnitude in the consequence.&lt;/p&gt;</description>
			</item>
			<item>
				<title>FlashAttention and Optimized Kernels</title>
				<link>http://programmer.ie/books/inference/13-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/13-chapter/</guid>
				<description>&lt;p&gt;I wrote exact block-wise attention in plain PyTorch, the algorithm that FlashAttention is built on. It gave the same answer as ordinary attention to within rounding. At 8,192 tokens it needed 16 MiB of extra memory where ordinary attention needed 3,148. And it was sixteen to eighteen times slower.&lt;/p&gt;&#xA;&lt;p&gt;The version of the same algorithm that PyTorch ships as a fused kernel, running on the same inputs, needed 12 MiB and, depending on length and run, was between 5.5 and 13.5 times &lt;em&gt;faster&lt;/em&gt; than ordinary attention.&lt;/p&gt;</description>
			</item>
			<item>
				<title>PagedAttention</title>
				<link>http://programmer.ie/books/inference/14-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/14-chapter/</guid>
				<description>&lt;p&gt;A server with room for 32,768 tokens of KV cache can hold exactly 32 sequences if it sets aside 1,024 tokens for each. In my simulation of a plausible chat workload, those 32 sequences used 33 per cent of the memory they had been given. The other two thirds sat reserved for tokens that, on average, would never be generated.&lt;/p&gt;&#xA;&lt;p&gt;Give the same budget to an allocator that hands out 16-token blocks as sequences grow, and the server holds between 92 and 96 sequences at a time, using 98 per cent of the memory, and finishes the same 3,000 requests in 2.6 to 2.7 times fewer steps.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Continuous Batching</title>
				<link>http://programmer.ie/books/inference/15-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/15-chapter/</guid>
				<description>&lt;p&gt;Under a light load, three tenths of the capacity of the server, requests to a statically batched GPT-2 waited a median of one to one and a half seconds for their first token. The same requests to the same model on the same GPU with continuous batching waited 55 to 60 milliseconds. At a load near capacity the median wait for a first token was five to six seconds for the static server with a batch of 8, and 1.4 to 2.4 seconds with a batch of 32. The continuous server&amp;rsquo;s was still 60 to 70 milliseconds.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Prefix Caching</title>
				<link>http://programmer.ie/books/inference/16-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/16-chapter/</guid>
				<description>&lt;p&gt;With a 512-token prefix already in the cache, a 32-token follow-up got its first token in 22 milliseconds. Without it, the same request took 37. A second tenant&amp;rsquo;s request, probing the same prefix, could tell the difference every single time: in 40 trials, the probe that hit a cached prefix was faster than every one that did not.&lt;/p&gt;&#xA;&lt;p&gt;The cache is a speed-up, and the speed-up is a measurement anyone can make. If two tenants share a prefix cache, either can find out, by timing, whether the other has recently sent a particular prompt. Giving each tenant its own scope removes that signal. In the same experiment the scoped probe was indistinguishable from a cold one (the chance that a cold probe was slower than a scoped one was 55 per cent, close to a coin toss), and it costs a share of the hit rate that depends heavily on how big the cache is.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Speculative Decoding</title>
				<link>http://programmer.ie/books/inference/17-chapter/</link>
				<pubDate>Wed, 21 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/17-chapter/</guid>
				<description>&lt;p&gt;The same 3-billion-parameter model, on the same GPU, produced tokens between 0.77 and 1.51 times as fast as it normally does, depending only on what it was writing and how many tokens a small helper model guessed ahead. On repetitive or structured text with six tokens guessed per step, it was 1.51 times faster. On paragraphs of prose with the same setting, it was slower than not guessing at all.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Compilation and Execution Graphs</title>
				<link>http://programmer.ie/books/inference/18-chapter/</link>
				<pubDate>Wed, 21 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/18-chapter/</guid>
				<description>&lt;p&gt;One decode step of GPT-2 took 16.5 milliseconds when PyTorch ran it operation by operation, and 3.4 milliseconds when the same GPU work was recorded once and replayed. The tokens were identical, all 129 of them. Four fifths of the eager step was not the GPU computing anything; it was the host deciding what to launch next.&lt;/p&gt;&#xA;&lt;p&gt;The previous draft of this chapter reported a different result: that compilation could not be measured at all, because TorchInductor &amp;ldquo;could not find a C++ compiler&amp;rdquo; on this machine. That was wrong. Visual Studio 2022 is installed; its compiler was simply not on the &lt;code&gt;PATH&lt;/code&gt; of the shell that ran the test. The error was real, the conclusion drawn from it was not, and the chapter had been recording an environment accident as a fact about the machine. With the compiler&amp;rsquo;s environment loaded, Inductor works on the CPU, though not in the way I first expected, and on the GPU it does not work because a different dependency is missing. Section by section, this chapter separates three things that the word &amp;ldquo;compile&amp;rdquo; covers, measures what each does to a decode step, and counts what each costs before it pays.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Mixture-of-Experts Inference</title>
				<link>http://programmer.ie/books/inference/19-chapter/</link>
				<pubDate>Wed, 21 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/19-chapter/</guid>
				<description>&lt;p&gt;Mixtral 8x7B computes each token with 13 billion parameters and stores 47 billion. That sounds like a model that is three and a half times cheaper to run than its size suggests, and for one token at a time it nearly is. On a layer built to Mixtral&amp;rsquo;s shape, one token chose two of eight experts and the layer took 3.95 milliseconds, reading only the experts it needed. Sixteen tokens chose between them all eight, and the same layer took 9.7 milliseconds, while a dense layer with the same &lt;em&gt;active&lt;/em&gt; width took 1.75. The saving that sparsity promises is a saving per token. A batch pays for the union of what its tokens chose.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Expert Routing and Load Balancing</title>
				<link>http://programmer.ie/books/inference/20-chapter/</link>
				<pubDate>Wed, 21 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/20-chapter/</guid>
				<description>&lt;p&gt;Three small mixture-of-experts language models were trained identically except for how they were encouraged to balance their experts. All three reached the same quality on held-out text, to within the difference between seeds. Then each was given the same fixed capacity per expert at inference, as a serving system with static shapes would, for batches of 64 tokens. The model with no balancing term lost 0.28 bits per character at a capacity factor of 2.0; the two balanced models lost 0.05. At a factor of 1.25 the loss was 0.68 bits against 0.33. The weights were not different in kind, nor was the quality without a limit. What differed was how evenly the router spread its tokens, and that is invisible until an execution engine with a finite budget meets it.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Multi-Head and Multi-Latent Attention</title>
				<link>http://programmer.ie/books/inference/21-chapter/</link>
				<pubDate>Thu, 22 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/21-chapter/</guid>
				<description>&lt;p&gt;Llama-3.2-3B keeps 112 kibibytes of keys and values for every token of every sequence. Had it been built with a separate key/value head for each of its 24 query heads, instead of 8 shared ones, that would be 336. On the 12 GB card of this book, with the weights loaded, the first design leaves room for 11 sequences of 4,096 tokens and the second for 3.&lt;/p&gt;&#xA;&lt;p&gt;That saving is a decision made when the model was designed, and a serving system can lose it without noticing. The way the book&amp;rsquo;s own starter code wrote grouped-query attention (repeat each shared key/value head for its queries, then run ordinary attention) reads the same bytes as the multi-head version. In the measurement below, going from 32 key/value heads to 1 changed its decode time by almost nothing (29 to 31 milliseconds). Written so that each cached byte is read once, the same step at Llama-3.2&amp;rsquo;s 8 key/value heads took 1.85 milliseconds instead of 30.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Sliding-Window Attention</title>
				<link>http://programmer.ie/books/inference/22-chapter/</link>
				<pubDate>Thu, 22 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/22-chapter/</guid>
				<description>&lt;p&gt;Put a 2,048-token window on Llama-3.2-1B and score it on the second half of a 4,096-token passage. With full attention its score is 3.00 bits per token. With the window it is 7.07, more than twice as bad. Now let the window also keep the very first token of the passage, and the score is 3.35. One token, kept out of 2,048, takes back 91 per cent of the damage.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Long-Context Inference</title>
				<link>http://programmer.ie/books/inference/23-chapter/</link>
				<pubDate>Thu, 22 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/23-chapter/</guid>
				<description>&lt;p&gt;Llama-3.2-1B advertises a context of 131,072 tokens. On the 12 GiB card of this book, asked to prefill 4,096 of them with the library&amp;rsquo;s default attention, it used 4.9 GiB of extra memory, nearly four times what 2,048 needed. A prefill of 8,192, tried once outside the final measurements, wanted nearly 19 GiB and took two and a half minutes because the driver quietly spilled the excess into system memory. The model accepted the tokens in every case. Nothing in &amp;ldquo;accepts 131,072 tokens&amp;rdquo; said that.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Model Architecture Versus Runtime Architecture</title>
				<link>http://programmer.ie/books/inference/24-chapter/</link>
				<pubDate>Thu, 22 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/24-chapter/</guid>
				<description>&lt;p&gt;Seven things were changed about how Llama-3.2-1B was run, one at a time, on twelve prompts of 48 greedy tokens each: a chunked prefill (twice), a different attention kernel (twice), a static cache, a padded batch, and float32 arithmetic. In 79 of the 84 runs the output was identical to the baseline&amp;rsquo;s, token for token. The other five differed at a token where the model had been within 0.02 logits of a tie, three of them an exact tie, and the largest change to the logits at the end of any prompt was 0.027.&lt;/p&gt;</description>
			</item>
			<item>
				<title>From Inference Loop to API</title>
				<link>http://programmer.ie/books/inference/25-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/25-chapter/</guid>
				<description>&lt;p&gt;Twenty-nine awkward requests were sent to a first-draft inference service, the kind that takes the framework&amp;rsquo;s defaults: a body that is not JSON, a prompt that is empty, an option spelt wrongly, a temperature of &lt;code&gt;NaN&lt;/code&gt;, a prompt of 4,000 emoji. It answered 200 to eight of them. Four of those answers were not what the caller asked for: &lt;code&gt;&amp;quot;5&amp;quot;&lt;/code&gt;, &lt;code&gt;5.0&lt;/code&gt; and &lt;code&gt;true&lt;/code&gt; were all accepted as a token limit, and a request for &lt;code&gt;max_tokens: 2&lt;/code&gt; (a misspelling of &lt;code&gt;max_new_tokens&lt;/code&gt;) returned sixteen tokens, the default of the field that did exist. It answered 500 to four others, and none of its twenty-one errors came in a shape the service had chosen or documented: most were the framework&amp;rsquo;s &lt;code&gt;detail&lt;/code&gt; lists, the rest one-line strings.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Request Scheduling and Admission Control</title>
				<link>http://programmer.ie/books/inference/26-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/26-chapter/</guid>
				<description>&lt;p&gt;The same service was sent the same 279 requests in 40 seconds, at about twice the rate its engine could serve. A 16-token request took the engine about 0.3 seconds, and the arrivals brought about two seconds of work for every second of engine time. A client was happy with an answer within two seconds.&lt;/p&gt;&#xA;&lt;p&gt;With an unbounded queue, which is what the Chapter 25 service had, 23 of the 279 requests were answered in time. The median request waited 26 seconds and the 99th percentile 57. Every request was eventually answered correctly; 256 of them were late. With a queue limited to eight, 48 were in time. With a queue that also dropped what could no longer finish by its deadline, 185 were. With an admission rule that refused, at arrival, what its own estimate said could not finish in time, 224 were, and no request that was served was late.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Concurrent Requests and Streaming</title>
				<link>http://programmer.ie/books/inference/27-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/27-chapter/</guid>
				<description>&lt;p&gt;Thirty-two clients each asked for 64 tokens. Served one after another by the engine of Chapters 25 and 26, they would have taken 22 seconds in total, and the last would have waited 21 seconds for its first word. On the batched engine of this chapter they were all answered in about 1.5 seconds, 14 to 15 times faster, at 1,320 to 1,376 tokens a second against 90 to 94 for a single stream. Every one of the 189 concurrent streams I compared with its solo run had identical token ids.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Distributed Inference</title>
				<link>http://programmer.ie/books/inference/28-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/28-chapter/</guid>
				<description>&lt;p&gt;GPT-2 was split across six processes, each holding a sixth of every layer&amp;rsquo;s attention heads and feed-forward width. Every one of the 15 runs of the split code, over 1, 2, 3, 4 and 6 processes, produced the library model&amp;rsquo;s 25 tokens exactly, and the final logits of the prompt differed from the library&amp;rsquo;s by at most 9.2e-5. The split model was also slower. One process took 23 milliseconds to produce a token. Six took 54 to 59.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Prefill/Decode Disaggregation</title>
				<link>http://programmer.ie/books/inference/29-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/29-chapter/</guid>
				<description>&lt;p&gt;Chapter 28 scaled across devices. This chapter splits the two phases of generation across different workers.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-disaggregate&#34;&gt;Why disaggregate&lt;/h2&gt;&#xA;&lt;p&gt;Prefill and decode have different bottlenecks. Prefill is compute-bound; decode is memory-bound. Running both on the same hardware forces a compromise. Disaggregation assigns prefill to compute-optimized workers and decode to memory-optimized workers.&lt;/p&gt;&#xA;&lt;h2 id=&#34;transfer-cost&#34;&gt;Transfer cost&lt;/h2&gt;&#xA;&lt;p&gt;Disaggregation requires moving KV state from prefill workers to decode workers. If transfer cost is high, it can erase the benefit. The simulator includes a transfer-cost counterexample.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Reliability, Cancellation and Recovery</title>
				<link>http://programmer.ie/books/inference/30-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/30-chapter/</guid>
				<description>&lt;p&gt;Chapter 29 split phases. This chapter handles failures.&lt;/p&gt;&#xA;&lt;h2 id=&#34;failure-modes&#34;&gt;Failure modes&lt;/h2&gt;&#xA;&lt;p&gt;Inference services face OOM, worker loss, malformed inputs, and partial streams. Each requires explicit handling.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cancellation&#34;&gt;Cancellation&lt;/h2&gt;&#xA;&lt;p&gt;Cancellation stops work and releases resources. It must propagate to all stages. gRPC cancellation shows that signalling alone is insufficient; applications must propagate it and release their own resources.&lt;/p&gt;&#xA;&lt;h2 id=&#34;timeouts&#34;&gt;Timeouts&lt;/h2&gt;&#xA;&lt;p&gt;Timeouts prevent unbounded work. They should be enforced at request and operation levels.&lt;/p&gt;&#xA;&lt;h2 id=&#34;retries&#34;&gt;Retries&lt;/h2&gt;&#xA;&lt;p&gt;Bounded retries can recover from transient failures. They must not mask persistent errors or cause duplicate side effects. Retryable transport failure differs from unsafe replay of a non-idempotent request.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Inference Protocols and Harmony</title>
				<link>http://programmer.ie/books/inference/31-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/31-chapter/</guid>
				<description>&lt;p&gt;Chapter 30 handled reliability. Part 6 now examines protocols and application-level optimization, starting with message envelopes.&lt;/p&gt;&#xA;&lt;h2 id=&#34;message-envelopes&#34;&gt;Message envelopes&lt;/h2&gt;&#xA;&lt;p&gt;Inference protocols wrap raw text in structured messages with roles and channels. This allows system, user, assistant, and tool messages to be distinguished.&lt;/p&gt;&#xA;&lt;h2 id=&#34;roles-and-channels&#34;&gt;Roles and channels&lt;/h2&gt;&#xA;&lt;p&gt;Roles identify who produced a message. Channels distinguish analysis from final output. This separation supports reasoning and safety.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tool-handoffs&#34;&gt;Tool handoffs&lt;/h2&gt;&#xA;&lt;p&gt;Tool calls require structured requests and responses. The protocol must preserve boundaries so untrusted content is not interpreted as instructions.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Claude, Caching and API-Level Optimization</title>
				<link>http://programmer.ie/books/inference/32-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/32-chapter/</guid>
				<description>&lt;p&gt;Chapter 31 examined protocols. This chapter examines API-level optimization, using public documentation only.&lt;/p&gt;&#xA;&lt;h2 id=&#34;public-api-versus-internals&#34;&gt;Public API versus internals&lt;/h2&gt;&#xA;&lt;p&gt;Provider documentation describes request/response behavior, not serving internals. We must not infer proprietary implementations from API behavior.&lt;/p&gt;&#xA;&lt;h2 id=&#34;prompt-caching&#34;&gt;Prompt caching&lt;/h2&gt;&#xA;&lt;p&gt;Prompt caching allows reuse of previously processed prefixes. Eligibility depends on documented fields such as minimum token counts and cache control markers. Savings are documented discounts, not measured system behavior.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Anthropic&amp;rsquo;s documentation defines prompt caching as an observable contract: cache breakpoints, TTLs, ordering, and usage accounting are visible. The Messages API remains stateless: the client still resends context, while provider-side caching may reduce cost. Pricing is published but volatile and contract-sensitive.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Reasoning Models and Inference-Time Compute</title>
				<link>http://programmer.ie/books/inference/33-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/33-chapter/</guid>
				<description>&lt;p&gt;Chapter 32 examined API-level optimization. This chapter examines reasoning models that spend additional inference-time compute.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reasoning-tokens&#34;&gt;Reasoning tokens&lt;/h2&gt;&#xA;&lt;p&gt;Some models generate intermediate reasoning tokens before final answers. These tokens consume compute and cost but are not always visible.&lt;/p&gt;&#xA;&lt;h2 id=&#34;budget-controls&#34;&gt;Budget controls&lt;/h2&gt;&#xA;&lt;p&gt;Budgets limit reasoning length. Higher budgets can improve accuracy but increase latency and cost. The trade-off is task-dependent. More reasoning tokens do not always improve accuracy.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Inference-time compute includes serial reasoning, parallel samples, verifier search, and adaptive allocation. The cited sources study optimal test-time compute and DeepSeek-R1&amp;rsquo;s reasoning training. Claude&amp;rsquo;s extended thinking controls are model-specific and versioned; fixed budget_tokens is not universally supported.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Tool Calling and Agentic Inference</title>
				<link>http://programmer.ie/books/inference/34-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/34-chapter/</guid>
				<description>&lt;p&gt;Chapter 33 examined reasoning budgets. This chapter examines tool use.&lt;/p&gt;&#xA;&lt;h2 id=&#34;tool-calling&#34;&gt;Tool calling&lt;/h2&gt;&#xA;&lt;p&gt;Tool calling lets a model request external computation. The runtime must parse the request, execute safely, and return results. The model proposes calls; the application is responsible for authorisation, execution, validation, and retries.&lt;/p&gt;&#xA;&lt;h2 id=&#34;interruption-and-re-entry&#34;&gt;Interruption and re-entry&lt;/h2&gt;&#xA;&lt;p&gt;Generation pauses for tool execution, then resumes with the tool result. This requires state management and trace IDs.&lt;/p&gt;&#xA;&lt;h2 id=&#34;sandboxing&#34;&gt;Sandboxing&lt;/h2&gt;&#xA;&lt;p&gt;Tools must be sandboxed. Untrusted model output must not execute arbitrary code. Tool arguments and results are untrusted data requiring schemas and policy checks.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Structured Outputs and Constrained Decoding</title>
				<link>http://programmer.ie/books/inference/35-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/35-chapter/</guid>
				<description>&lt;p&gt;Chapter 34 handled tool calls. This chapter ensures outputs conform to schemas.&lt;/p&gt;&#xA;&lt;h2 id=&#34;schemas&#34;&gt;Schemas&lt;/h2&gt;&#xA;&lt;p&gt;Structured outputs require a schema. The runtime must validate generated JSON against it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;token-level-constraints&#34;&gt;Token-level constraints&lt;/h2&gt;&#xA;&lt;p&gt;Constrained decoding restricts tokens to those that keep the output valid. This can guarantee syntactic validity but not semantic correctness.&lt;/p&gt;&#xA;&lt;h2 id=&#34;validation-and-repair&#34;&gt;Validation and repair&lt;/h2&gt;&#xA;&lt;p&gt;Validation checks output after generation. Repair attempts to fix invalid output. Validation is safer; repair can introduce errors.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;The selected sources distinguish grammar compilation, token masking, parser state, and schema validation. XGrammar and guided-generation work show that syntactic conformance can be efficient, but JSONSchemaBench shows that schema-valid JSON can still be semantically wrong or unsafe.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Latency, Throughput and Time to First Token</title>
				<link>http://programmer.ie/books/inference/36-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/36-chapter/</guid>
				<description>&lt;p&gt;Chapter 35 structured outputs. Part 7 now examines economics and evaluation, starting with metrics.&lt;/p&gt;&#xA;&lt;h2 id=&#34;definitions&#34;&gt;Definitions&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;TTFT&lt;/strong&gt;: time to first token.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;TPOT&lt;/strong&gt;: time per output token.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;E2E latency&lt;/strong&gt;: total request time.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Throughput&lt;/strong&gt;: tokens per second.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Percentiles&lt;/strong&gt;: tail behavior.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;why-percentiles&#34;&gt;Why percentiles&lt;/h2&gt;&#xA;&lt;p&gt;Averages hide tail latency. Percentiles reveal user experience. TTFT p99 matters for responsiveness.&lt;/p&gt;&#xA;&lt;h2 id=&#34;denominators&#34;&gt;Denominators&lt;/h2&gt;&#xA;&lt;p&gt;Do not mix prompt and output tokens in throughput without stating. Prompt and output have different costs.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Cost per Million Tokens</title>
				<link>http://programmer.ie/books/inference/37-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/37-chapter/</guid>
				<description>&lt;p&gt;Chapter 36 defined metrics. This chapter converts them to cost.&lt;/p&gt;&#xA;&lt;h2 id=&#34;cost-components&#34;&gt;Cost components&lt;/h2&gt;&#xA;&lt;p&gt;Cost includes hardware amortization, power, cooling, networking, storage, and operational overhead. API billing adds provider margin and abstraction.&lt;/p&gt;&#xA;&lt;h2 id=&#34;utilization&#34;&gt;Utilization&lt;/h2&gt;&#xA;&lt;p&gt;Utilization is critical. Low utilization raises cost per token. The estimator shows sensitivity to utilization.&lt;/p&gt;&#xA;&lt;h2 id=&#34;forecasts-versus-measurements&#34;&gt;Forecasts versus measurements&lt;/h2&gt;&#xA;&lt;p&gt;Estimates are forecasts based on assumptions. Measured spend requires actual billing and usage data.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Separate API list price from measured self-hosted cost. Build cost from token mix, cache hits, batch efficiency, utilisation, hardware time, energy, and rejected or aborted work. Do not compare providers without model, quality, region, contract, and input/output assumptions. Pope et al. model inference cost and latency for large models, but their measurements are for specific models and TPU v4 configurations.&lt;/p&gt;</description>
			</item>
			<item>
				<title>GPU Utilization and Capacity Planning</title>
				<link>http://programmer.ie/books/inference/38-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/38-chapter/</guid>
				<description>&lt;p&gt;Chapter 37 estimated cost. This chapter plans capacity.&lt;/p&gt;&#xA;&lt;h2 id=&#34;occupancy&#34;&gt;Occupancy&lt;/h2&gt;&#xA;&lt;p&gt;GPU occupancy measures how many warps are active. Low occupancy can indicate underutilization or memory bottlenecks.&lt;/p&gt;&#xA;&lt;h2 id=&#34;memory-limits&#34;&gt;Memory limits&lt;/h2&gt;&#xA;&lt;p&gt;Memory limits cap batch size and context length. Exceeding memory causes OOM.&lt;/p&gt;&#xA;&lt;h2 id=&#34;queue-saturation&#34;&gt;Queue saturation&lt;/h2&gt;&#xA;&lt;p&gt;Queue saturation occurs when arrival rate exceeds service rate. Latency grows without bound.&lt;/p&gt;&#xA;&lt;h2 id=&#34;capacity-headroom&#34;&gt;Capacity headroom&lt;/h2&gt;&#xA;&lt;p&gt;Capacity planning requires headroom for bursts. Extrapolating beyond measured load is unsafe. The model rejects loads beyond observed.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Correctness, Determinism and Reproducibility</title>
				<link>http://programmer.ie/books/inference/39-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/39-chapter/</guid>
				<description>&lt;p&gt;Chapter 38 planned capacity. This chapter examines correctness and reproducibility.&lt;/p&gt;&#xA;&lt;h2 id=&#34;floating-point-nondeterminism&#34;&gt;Floating-point nondeterminism&lt;/h2&gt;&#xA;&lt;p&gt;Floating-point operations are not associative. Parallel reductions can produce different results. GPU kernels may vary by version and hardware.&lt;/p&gt;&#xA;&lt;h2 id=&#34;batching-effects&#34;&gt;Batching effects&lt;/h2&gt;&#xA;&lt;p&gt;Batch size can affect numerical results due to reduction order. Batch invariance is not automatic.&lt;/p&gt;&#xA;&lt;h2 id=&#34;seed-limitations&#34;&gt;Seed limitations&lt;/h2&gt;&#xA;&lt;p&gt;Seeds help reproducibility but do not guarantee identical results across hardware or library versions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Separate seeded repeatability, deterministic algorithms, batch invariance, numerical tolerance, and semantic equivalence. Record model/tokenizer revisions, runtime and driver versions, dtype, kernels, hardware, request ordering, and sampler state. Cross-hardware bitwise identity is a stronger and often unavailable guarantee. PyTorch documents that deterministic algorithms can reduce performance and still not promise cross-version identity.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Designing Meaningful Inference Benchmarks</title>
				<link>http://programmer.ie/books/inference/40-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/40-chapter/</guid>
				<description>&lt;p&gt;Chapter 39 addressed reproducibility. This chapter designs benchmarks.&lt;/p&gt;&#xA;&lt;h2 id=&#34;realistic-workloads&#34;&gt;Realistic workloads&lt;/h2&gt;&#xA;&lt;p&gt;Benchmarks must reflect real usage: prompt lengths, output lengths, concurrency, and task types.&lt;/p&gt;&#xA;&lt;h2 id=&#34;baselines&#34;&gt;Baselines&lt;/h2&gt;&#xA;&lt;p&gt;A benchmark needs a baseline. Compare against a simple, well-understood implementation.&lt;/p&gt;&#xA;&lt;h2 id=&#34;statistical-uncertainty&#34;&gt;Statistical uncertainty&lt;/h2&gt;&#xA;&lt;p&gt;Repeated trials and confidence intervals quantify uncertainty. Single runs are insufficient.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Freeze the system under test, model, revision, quality target, workload, arrival process, cache state, and measurement points. Report TTFT, TPOT, ITL, end-to-end percentiles, throughput, goodput, errors, and power where relevant. MLPerf separates scenarios, quality targets, latency constraints, throughput, system metadata, and power. vLLM documents cache-related benchmark hazards. Separate repository-reported reference graphs from measurements reproduced by this book.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Designing the Inference Runtime</title>
				<link>http://programmer.ie/books/inference/41-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/41-chapter/</guid>
				<description>&lt;p&gt;Chapter 40 designed benchmarks. Part 8 now builds the Inference Lab capstone, starting with design.&lt;/p&gt;&#xA;&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;/h2&gt;&#xA;&lt;p&gt;The runtime integrates tokenizer, model backend, sampler, cache, scheduler, API, and metrics. Each component has a typed contract.&lt;/p&gt;&#xA;&lt;h2 id=&#34;adrs&#34;&gt;ADRs&lt;/h2&gt;&#xA;&lt;p&gt;Architecture decision records document choices. The example includes two ADRs: CPU-first and typed contracts.&lt;/p&gt;&#xA;&lt;h2 id=&#34;contracts&#34;&gt;Contracts&lt;/h2&gt;&#xA;&lt;p&gt;Contracts enable swappable backends and testability. The contract test verifies a backend generates expected output.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Compare runtimes by explicit subsystems: request state, scheduler, cache manager, executor, sampler, protocol, and telemetry. Pinned implementations such as DeepInfer, PagedAttention, and SGLang distinguish reusable patterns from model- or vendor-specific choices. Define invariants at subsystem boundaries before optimising.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Implementing Scheduling and Caching</title>
				<link>http://programmer.ie/books/inference/42-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/42-chapter/</guid>
				<description>&lt;p&gt;Chapter 41 designed the runtime. This chapter integrates scheduling and caching.&lt;/p&gt;&#xA;&lt;h2 id=&#34;integration&#34;&gt;Integration&lt;/h2&gt;&#xA;&lt;p&gt;The runtime combines admission, scheduling, caching, and cancellation. Feature flags control which components are active.&lt;/p&gt;&#xA;&lt;h2 id=&#34;deterministic-scenarios&#34;&gt;Deterministic scenarios&lt;/h2&gt;&#xA;&lt;p&gt;Deterministic concurrency scenarios allow reproducible testing. The example schedules 4 of 5 requests and cleans up cancellation.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Co-design scheduling and cache allocation; neither can be treated as an isolated queue or allocator. Make admission, preemption, prefix sharing, reclamation, and fairness observable state transitions. Prove semantic parity and isolation before claiming performance improvements. Orca introduced iteration-level scheduling; PagedAttention and SGLang extend cache and scheduling integration.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Adding Multiple Model Backends</title>
				<link>http://programmer.ie/books/inference/43-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/43-chapter/</guid>
				<description>&lt;p&gt;Chapter 42 integrated scheduling. This chapter adds multiple backends.&lt;/p&gt;&#xA;&lt;h2 id=&#34;backend-contract&#34;&gt;Backend contract&lt;/h2&gt;&#xA;&lt;p&gt;A common contract allows swappable backends. The PyTorch toy backend passes conformance. vLLM and SGLang are stubs with explicit skip reasons.&lt;/p&gt;&#xA;&lt;h2 id=&#34;capabilities&#34;&gt;Capabilities&lt;/h2&gt;&#xA;&lt;p&gt;Each backend reports capabilities. Unsupported features raise errors rather than silently falling back.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Define a backend contract for tokens, logits/sampling ownership, cache semantics, streaming events, errors, and capabilities. Use conformance tests to expose protocol and tokenizer differences. Fail closed on unsupported model/hardware/feature combinations. Transformers documentation and gpt-oss verification provide external conformance references; DeepInfer provides a pinned first-party pattern but is not independently measured.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Benchmarking Against Established Engines</title>
				<link>http://programmer.ie/books/inference/44-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/44-chapter/</guid>
				<description>&lt;p&gt;Chapter 43 added backends. This chapter benchmarks fairly.&lt;/p&gt;&#xA;&lt;h2 id=&#34;apples-to-oranges&#34;&gt;Apples-to-oranges&lt;/h2&gt;&#xA;&lt;p&gt;Comparisons must match workload, hardware, and configuration. Undocumented settings invalidate results.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-to-compare&#34;&gt;What to compare&lt;/h2&gt;&#xA;&lt;p&gt;Compare output correctness, TTFT, throughput, peak memory, and task success. Report all.&lt;/p&gt;&#xA;&lt;h2 id=&#34;research-context&#34;&gt;Research context&lt;/h2&gt;&#xA;&lt;p&gt;Compare engines only under a shared workload, model artefact, quality target, arrival process, and cache policy. Record warm/cold state, versions, command lines, hardware, failures, and raw per-request data. Keep vendor/repository reference results in a separate table from book-reproduced measurements. MLPerf and vLLM document the metadata needed for comparability.&lt;/p&gt;</description>
			</item>
			<item>
				<title>What We Learned: Inference From First Principles</title>
				<link>http://programmer.ie/books/inference/45-chapter/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0100</pubDate>
				<guid>http://programmer.ie/books/inference/45-chapter/</guid>
				<description>&lt;p&gt;The final chapter synthesizes what was built and what remains open.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-we-learned&#34;&gt;What we learned&lt;/h2&gt;&#xA;&lt;p&gt;Inference is a system, not just a model. It spans tokenisation, computation, memory, caching, scheduling, serving, protocols, and economics.&lt;/p&gt;&#xA;&lt;h2 id=&#34;evidence-audit&#34;&gt;Evidence audit&lt;/h2&gt;&#xA;&lt;p&gt;Every headline claim must map to evidence. The manifest records 45 chapters with tests and results. Failures and negative results are preserved. Audit each claim as established background, book hypothesis, local result, or first-party system report. Require an evidence chain from claim to source or raw result, environment, command, and code revision. State whether artefacts are merely available, locally functional, reproduced, or independently replicated.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
