<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parallelism | Prince Modi</title><link>https://princemodi.me/tag/parallelism/</link><atom:link href="https://princemodi.me/tag/parallelism/index.xml" rel="self" type="application/rss+xml"/><description>Parallelism</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Mon, 13 Jul 2026 00:00:00 +0000</lastBuildDate><image><url>https://princemodi.me/media/icon_hua5d2116872382d6405c4fb215e02fa8e_2300_512x512_fill_lanczos_center_3.png</url><title>Parallelism</title><link>https://princemodi.me/tag/parallelism/</link></image><item><title>Attention, Parallelism, and MoE Communication: A Ground-Up Walkthrough</title><link>https://princemodi.me/post/attention/</link><pubDate>Mon, 13 Jul 2026 00:00:00 +0000</pubDate><guid>https://princemodi.me/post/attention/</guid><description>&lt;p>&lt;em>Note: Significant portions of this article, including diagrams and code, were generated with the assistance of Claude (Anthropic). I wanted to be upfront about that, since I&amp;rsquo;d want to know before spending my time on something, and I imagine you might feel the same. If you find any inaccuracies feel free to point them out to me.&lt;/em>&lt;/p>
&lt;h2 id="part-1-inside-one-attention-block">Part 1: Inside one attention block&lt;/h2>
&lt;h3 id="what-is-w_k-really-where-does-it-sit-in-the-pipeline">What is &lt;code>W_K&lt;/code>, really? Where does it sit in the pipeline?&lt;/h3>
&lt;p>A token&amp;rsquo;s &amp;ldquo;hidden state&amp;rdquo; going into an attention block is a vector of length &lt;code>d_model&lt;/code>. A batch of &lt;code>B&lt;/code> sequences, each &lt;code>T&lt;/code> tokens long, gives a tensor of shape &lt;code>(B, T, d_model)&lt;/code>. &lt;code>W_K&lt;/code> is just a plain, non-head-aware &lt;code>(d_model, d_model)&lt;/code> matrix. Multiplying &lt;code>x @ W_K&lt;/code> gives back a flat &lt;code>(B, T, d_model)&lt;/code> tensor with no visible head structure yet. Q and V are produced the same way, each with their own separate weight matrix.&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 420" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>Entry point of an attention block&lt;/title>
&lt;defs>&lt;marker id="a1" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;rect x="190" y="40" width="300" height="44" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="62" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">x: (B,T,d_model) = (2,4,8)&lt;/text>
&lt;line x1="340" y1="84" x2="340" y2="104" stroke="#888780" stroke-width="1.5" marker-end="url(#a1)"/>
&lt;rect x="140" y="104" width="400" height="56" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="122" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">project + reshape (per head)&lt;/text>
&lt;text x="340" y="140" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">Q,K,V each (T,d_head)=(4,4), head 0&lt;/text>
&lt;line x1="340" y1="160" x2="340" y2="184" stroke="#888780" stroke-width="1.5" marker-end="url(#a1)"/>
&lt;rect x="100" y="184" width="480" height="70" rx="8" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="340" y="208" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">Q @ Kᵀ → scores, shape (T,T) = (4,4)&lt;/text>
&lt;text x="340" y="230" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#633806">every query row meets every key column, HERE&lt;/text>
&lt;line x1="340" y1="254" x2="340" y2="278" stroke="#888780" stroke-width="1.5" marker-end="url(#a1)"/>
&lt;rect x="140" y="278" width="400" height="56" rx="8" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="340" y="296" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#085041">softmax(scores) → weights (4,4)&lt;/text>
&lt;text x="340" y="314" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">weights @ V → head output (T,d_head)=(4,4)&lt;/text>
&lt;line x1="340" y1="334" x2="340" y2="358" stroke="#888780" stroke-width="1.5" marker-end="url(#a1)"/>
&lt;rect x="140" y="358" width="400" height="56" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="376" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">concat all heads + × W_O&lt;/text>
&lt;text x="340" y="394" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">→ final output (T,d_model) = (4,8)&lt;/text>
&lt;/svg>
&lt;p>The only step where token positions actually interact is the amber box: &lt;code>Q @ Kᵀ&lt;/code>. Everything else (projections, softmax normalization, output projection) is per-token or per-head local. That single fact turns out to explain almost everything else in this post.&lt;/p>
&lt;h3 id="how-does-splitting-heads-actually-work-mechanically">How does &amp;ldquo;splitting heads&amp;rdquo; actually work mechanically?&lt;/h3>
&lt;p>Reshaping &lt;code>d_model = n_heads × d_head&lt;/code> is pure relabeling, no computation. Take one token&amp;rsquo;s 8-number &lt;code>K&lt;/code>-vector: chopping it into two groups of 4 consecutive numbers &lt;em>is&lt;/em> &amp;ldquo;head 0&amp;rdquo; and &amp;ldquo;head 1.&amp;rdquo; Nothing forces that split point; it&amp;rsquo;s just a convention that has to be applied consistently to Q, K, and V so head 0&amp;rsquo;s pieces line up across all three.&lt;/p>
&lt;p>Because the split happens on the &lt;strong>output columns of the weight matrix itself&lt;/strong>, you can literally hand GPU 0 the left half of &lt;code>W_K&lt;/code>&amp;rsquo;s columns and GPU 1 the right half. Each GPU computes its own head from scratch, with zero communication needed until the very end.&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 440" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>Tensor parallelism: column-wise head split&lt;/title>
&lt;defs>&lt;marker id="a2" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;rect x="200" y="44" width="280" height="24" rx="4" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="56" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#444441">h (d_model)&lt;/text>
&lt;line x1="340" y1="68" x2="340" y2="98" stroke="#888780" stroke-width="1.5" marker-end="url(#a2)"/>
&lt;text x="356" y="88" font-family="sans-serif" font-size="12" fill="#5F5E5A">× W_K&lt;/text>
&lt;rect x="180" y="104" width="80" height="86" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;text x="220" y="142" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#3C3489">H0&lt;/text>
&lt;rect x="260" y="104" width="80" height="86" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;text x="300" y="142" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#3C3489">H1&lt;/text>
&lt;rect x="340" y="104" width="80" height="86" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="380" y="142" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#085041">H2&lt;/text>
&lt;rect x="420" y="104" width="80" height="86" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="460" y="142" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#085041">H3&lt;/text>
&lt;line x1="340" y1="96" x2="340" y2="252" stroke="#888780" stroke-width="1.5" stroke-dasharray="4 3"/>
&lt;text x="525" y="132" font-family="sans-serif" font-size="12" fill="#5F5E5A">← column-wise&lt;/text>
&lt;text x="525" y="148" font-family="sans-serif" font-size="12" fill="#5F5E5A">TP split&lt;/text>
&lt;text x="260" y="204" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 0&lt;/text>
&lt;text x="420" y="204" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 1&lt;/text>
&lt;text x="340" y="270" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">KV cache per GPU (per token)&lt;/text>
&lt;rect x="70" y="282" width="230" height="72" rx="8" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="4 3"/>
&lt;text x="185" y="300" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 0&lt;/text>
&lt;rect x="90" y="310" width="180" height="24" rx="4" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;text x="180" y="322" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#3C3489">K, V: H0, H1&lt;/text>
&lt;rect x="380" y="282" width="230" height="72" rx="8" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="4 3"/>
&lt;text x="495" y="300" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 1&lt;/text>
&lt;rect x="400" y="310" width="180" height="24" rx="4" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="490" y="322" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">K, V: H2, H3&lt;/text>
&lt;text x="340" y="400" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Each GPU caches only its own heads, no duplication&lt;/text>
&lt;/svg>
&lt;p>For TP&amp;rsquo;s combine step: each GPU multiplies its head output by its own &lt;strong>row&lt;/strong>-slice of &lt;code>W_O&lt;/code> (not the full matrix), producing a partial &lt;code>d_model&lt;/code>-sized output, and the true answer is the &lt;strong>sum&lt;/strong> of those partials, not a concatenation. So the collective that combines TP&amp;rsquo;s two GPUs is an &lt;strong>all-reduce&lt;/strong>, not an all-gather: a distinction that matters later.&lt;/p>
&lt;h3 id="why-doesnt-mla-deepseeks-attention-variant-shard-cleanly-this-way">Why doesn&amp;rsquo;t MLA (DeepSeek&amp;rsquo;s attention variant) shard cleanly this way?&lt;/h3>
&lt;p>Standard multi-head attention has a natural per-head cache: head 1&amp;rsquo;s K/V lives in its own slice. MLA throws that away: it compresses K and V into &lt;strong>one shared latent vector per token&lt;/strong>, and every head reconstructs its own K/V from that &lt;em>same&lt;/em> shared vector via a per-head up-projection. That compression is the entire reason MLA&amp;rsquo;s KV cache is so small.&lt;/p>
&lt;p>The problem: if you TP-shard by head, every GPU still needs the &lt;em>entire&lt;/em> shared latent to reconstruct even its own heads. There&amp;rsquo;s no per-head slice to hand out, because the compression collapsed it into one shared thing.&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 480" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>MLA under tensor parallelism: cache duplication&lt;/title>
&lt;defs>&lt;marker id="a3" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;rect x="200" y="44" width="280" height="24" rx="4" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="56" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#444441">h (d_model)&lt;/text>
&lt;line x1="340" y1="68" x2="340" y2="96" stroke="#888780" stroke-width="1.5" marker-end="url(#a3)"/>
&lt;text x="356" y="86" font-family="sans-serif" font-size="12" fill="#5F5E5A">× W_DKV (compress)&lt;/text>
&lt;rect x="270" y="102" width="140" height="36" rx="6" fill="#FAEEDA" stroke="#BA7517" stroke-width="1"/>
&lt;text x="340" y="120" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">c_KV&lt;/text>
&lt;text x="424" y="112" font-family="sans-serif" font-size="12" fill="#5F5E5A">dim 512, no head divisions&lt;/text>
&lt;text x="424" y="128" font-family="sans-serif" font-size="12" fill="#5F5E5A">one shared vector for ALL heads&lt;/text>
&lt;text x="256" y="120" text-anchor="end" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">cached&lt;/text>
&lt;line x1="340" y1="138" x2="340" y2="170" stroke="#888780" stroke-width="1.5" marker-end="url(#a3)"/>
&lt;text x="356" y="158" font-family="sans-serif" font-size="12" fill="#5F5E5A">× W_UK, W_UV (decompress)&lt;/text>
&lt;rect x="180" y="176" width="80" height="22" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;text x="220" y="187" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#3C3489">H0&lt;/text>
&lt;rect x="260" y="176" width="80" height="22" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;text x="300" y="187" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#3C3489">H1&lt;/text>
&lt;rect x="340" y="176" width="80" height="22" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="380" y="187" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">H2&lt;/text>
&lt;rect x="420" y="176" width="80" height="22" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="460" y="187" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">H3&lt;/text>
&lt;text x="340" y="238" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">Every GPU needs full c_KV to decompress its heads&lt;/text>
&lt;text x="340" y="272" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">KV cache per GPU (per token)&lt;/text>
&lt;rect x="70" y="284" width="230" height="68" rx="8" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="4 3"/>
&lt;text x="185" y="302" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 0&lt;/text>
&lt;rect x="95" y="312" width="180" height="24" rx="4" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="185" y="324" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#633806">full c_KV (dim 512)&lt;/text>
&lt;rect x="380" y="284" width="230" height="68" rx="8" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="4 3"/>
&lt;text x="495" y="302" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 1&lt;/text>
&lt;rect x="405" y="312" width="180" height="24" rx="4" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="495" y="324" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#633806">full c_KV (dim 512)&lt;/text>
&lt;text x="340" y="384" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Identical copies. TP didn't split the cache at all&lt;/text>
&lt;text x="340" y="404" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">With TP=8, that's 8 full copies of c_KV, and MLA's savings are erased&lt;/text>
&lt;text x="340" y="428" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">This is why DeepSeek-style models use DP, not TP, for attention&lt;/text>
&lt;/svg>
&lt;p>This is why modern MoE serving stacks (and both papers this post is built around) run &lt;strong>DP-EP&lt;/strong>, not TP-EP: DP replicates attention entirely (no sharing, no duplication problem), and EP is a completely different axis (sharding &lt;em>experts&lt;/em>, not KV cache) used for the FFN.&lt;/p>
&lt;hr>
&lt;h2 id="part-2-dp-tp-cp-pp-which-axis-does-each-one-cut">Part 2: DP, TP, CP, PP: which axis does each one cut?&lt;/h2>
&lt;p>Once Q/K/V are reshaped to &lt;code>(B, T, n_heads, d_head)&lt;/code>, every axis of that tensor is a candidate for a different parallelism strategy:&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 200" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>Which parallelism strategy splits which tensor axis&lt;/title>
&lt;text x="340" y="36" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">Tensor shape (B, T, n_heads, d_head): one axis per strategy&lt;/text>
&lt;rect x="40" y="60" width="130" height="56" rx="8" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>
&lt;text x="105" y="80" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">B (batch)&lt;/text>
&lt;text x="105" y="100" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#0C447C">→ split by DP&lt;/text>
&lt;rect x="186" y="60" width="130" height="56" rx="8" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="251" y="80" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#085041">T (sequence)&lt;/text>
&lt;text x="251" y="100" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">→ split by CP&lt;/text>
&lt;rect x="332" y="60" width="130" height="56" rx="8" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;text x="397" y="80" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#3C3489">n_heads&lt;/text>
&lt;text x="397" y="100" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#3C3489">→ split by TP&lt;/text>
&lt;rect x="478" y="60" width="130" height="56" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="543" y="80" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">d_head&lt;/text>
&lt;text x="543" y="100" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#444441">→ never split&lt;/text>
&lt;text x="340" y="150" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">d_head can't be split without splitting a single dot product&lt;/text>
&lt;text x="340" y="170" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">mid-computation, that's the axis that needs communication&lt;/text>
&lt;/svg>
&lt;p>The rule that decides all four: an axis needs communication only when the computation must &lt;strong>combine information across&lt;/strong> different slices of it. &lt;code>B&lt;/code> and &lt;code>n_heads&lt;/code> are axes attention treats as fully independent (batch elements never interact; heads never interact until the very last step). &lt;code>T&lt;/code> is the axis attention is &lt;em>defined&lt;/em> to reduce over: a query needs to see keys from potentially every position, so cutting &lt;code>T&lt;/code> genuinely separates data the computation needs together. &lt;code>d_head&lt;/code> would split a single dot product mid-sum, essentially never attempted.&lt;/p>
&lt;p>Ranking these by actual communication cost gives &lt;code>B &amp;lt; n_heads &amp;lt; T &amp;lt; d_head&lt;/code>, &lt;strong>not&lt;/strong> simply &amp;ldquo;deeper in the tensor shape = more communication.&amp;rdquo; &lt;code>n_heads&lt;/code> (TP) needs one cheap combine step at the very end; &lt;code>T&lt;/code> (CP) needs genuine ongoing exchange, which is exactly why CP is a whole research subfield and TP mostly isn&amp;rsquo;t.&lt;/p>
&lt;h3 id="how-does-cps-communication-actually-work">How does CP&amp;rsquo;s communication actually work?&lt;/h3>
&lt;p>Splitting &lt;code>T&lt;/code> for the Q/K/V &lt;em>projection&lt;/em> is exactly as free as DP splitting &lt;code>B&lt;/code>: the projection is per-token, so a GPU can compute Q/K/V for its own local tokens with zero communication. The break happens one step later, at the score computation, because that&amp;rsquo;s the one operation whose entire job is &amp;ldquo;let every token look at every other token&amp;rdquo;:&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 290" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>CP is silent like DP until attention needs to look across tokens&lt;/title>
&lt;defs>&lt;marker id="a4" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;text x="340" y="30" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">CP splits T: silent until attention needs to look across it&lt;/text>
&lt;rect x="55" y="50" width="260" height="56" rx="8" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>
&lt;text x="185" y="68" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">x[:, 0:2, :]&lt;/text>
&lt;text x="185" y="86" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#0C447C">(2,2,8), tokens 0,1&lt;/text>
&lt;rect x="365" y="50" width="260" height="56" rx="8" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="495" y="68" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#085041">x[:, 2:4, :]&lt;/text>
&lt;text x="495" y="86" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">(2,2,8), tokens 2,3&lt;/text>
&lt;line x1="185" y1="106" x2="185" y2="130" stroke="#888780" stroke-width="1.5" marker-end="url(#a4)"/>
&lt;line x1="495" y1="106" x2="495" y2="130" stroke="#888780" stroke-width="1.5" marker-end="url(#a4)"/>
&lt;rect x="55" y="130" width="260" height="56" rx="8" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>
&lt;text x="185" y="148" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">× W_Q, W_K, W_V (full)&lt;/text>
&lt;text x="185" y="166" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#0C447C">→ Q,K,V for tokens 0,1&lt;/text>
&lt;rect x="365" y="130" width="260" height="56" rx="8" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="495" y="148" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#085041">× W_Q, W_K, W_V (full)&lt;/text>
&lt;text x="495" y="166" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">→ Q,K,V for tokens 2,3&lt;/text>
&lt;line x1="40" y1="210" x2="640" y2="210" stroke="#888780" stroke-width="1" stroke-dasharray="4 3"/>
&lt;text x="340" y="200" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">same as DP so far, zero communication&lt;/text>
&lt;text x="340" y="228" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">attention itself needs every token's K,V, not just the local shard&lt;/text>
&lt;text x="340" y="262" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">→ this is the query-out / partial-back / merge step below&lt;/text>
&lt;/svg>
&lt;p>Two real implementations exist for that cross-boundary exchange. NanoCP/Helix route the query directly to whichever remote GPU holds the needed KV shard, get a partial result + a scaling factor back, and merge (the same online-softmax trick FlashAttention uses internally). Ring Attention does it differently: no fixed destination, just a &lt;strong>rotating relay&lt;/strong>:&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 420" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>Ring Attention communication topology&lt;/title>
&lt;defs>&lt;marker id="a5" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;text x="340" y="24" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">Ring Attention: chunks rotate, partials accumulate&lt;/text>
&lt;line x1="340" y1="70" x2="520" y2="190" stroke="#888780" stroke-width="1.5" marker-end="url(#a5)"/>
&lt;line x1="520" y1="190" x2="340" y2="310" stroke="#888780" stroke-width="1.5" marker-end="url(#a5)"/>
&lt;line x1="340" y1="310" x2="160" y2="190" stroke="#888780" stroke-width="1.5" marker-end="url(#a5)"/>
&lt;line x1="160" y1="190" x2="340" y2="70" stroke="#888780" stroke-width="1.5" marker-end="url(#a5)"/>
&lt;text x="430" y="118" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">KV chunks rotate this way&lt;/text>
&lt;rect x="270" y="42" width="140" height="56" rx="8" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>
&lt;text x="340" y="60" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">GPU 0&lt;/text>
&lt;text x="340" y="78" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#0C447C">own KV + partial&lt;/text>
&lt;rect x="450" y="162" width="140" height="56" rx="8" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>
&lt;text x="520" y="180" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">GPU 1&lt;/text>
&lt;text x="520" y="198" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#0C447C">own KV + partial&lt;/text>
&lt;rect x="270" y="282" width="140" height="56" rx="8" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>
&lt;text x="340" y="300" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">GPU 2&lt;/text>
&lt;text x="340" y="318" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#0C447C">own KV + partial&lt;/text>
&lt;rect x="90" y="162" width="140" height="56" rx="8" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>
&lt;text x="160" y="180" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">GPU 3&lt;/text>
&lt;text x="160" y="198" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#0C447C">own KV + partial&lt;/text>
&lt;text x="340" y="362" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Each hop: merge new chunk into running partial (LSE)&lt;/text>
&lt;text x="340" y="380" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">then forward your own previous chunk to the next GPU&lt;/text>
&lt;text x="340" y="398" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">After N hops, every GPU has seen the whole sequence&lt;/text>
&lt;/svg>
&lt;p>Ring trades a longer, bandwidth-friendly relay for training-scale CP groups; the routed/point-to-point style is lower-latency for the smaller, more dynamic groups decode-time serving needs, which is exactly the design choice NanoCP makes.&lt;/p>
&lt;p>&lt;strong>On PP:&lt;/strong> worth a note since it&amp;rsquo;s easy to assume it&amp;rsquo;s training-only. It&amp;rsquo;s genuinely preferred over TP once GPUs span more than one fast-interconnect domain, because TP needs an all-reduce &lt;em>every layer&lt;/em> (brutal over slow links) while PP only passes activations across one boundary per stage. Sarathi-Serve reports roughly 2× lower median latency for PP vs. TP once crossing nodes over ordinary Ethernet. This is exactly why UltraEP&amp;rsquo;s DeepSeek-V3 config uses &lt;code>EP64-PP4&lt;/code> rather than adding TP.&lt;/p>
&lt;hr>
&lt;h2 id="part-3-the-toy-transformer">Part 3: The toy transformer&lt;/h2>
&lt;p>Rather than keep everything abstract, here&amp;rsquo;s a complete, runnable forward pass, embeddings through two full transformer layers to next-token logits, with the same toy dimensions used throughout (&lt;code>d_model=8&lt;/code>, &lt;code>n_heads=2&lt;/code>, &lt;code>T=4&lt;/code>). Every stage prints its actual shape and values.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">seed&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">42&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_printoptions&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">precision&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">suppress&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---------------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Toy dimensions -- same numbers used throughout the conversation&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---------------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">vocab_size&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">6&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">d_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">8&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">n_heads&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">d_head&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">d_model&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="n">n_heads&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">d_ff&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">16&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">T&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4&lt;/span> &lt;span class="c1"># sequence length&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">num_layers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">title&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s2">&amp;#34;=&amp;#34;&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">78&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">title&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;=&amp;#34;&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">78&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">layernorm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">eps&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">1e-5&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mu&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keepdims&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">var&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">var&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keepdims&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">mu&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sqrt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">var&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">eps&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">softmax&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">max&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keepdims&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">e&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keepdims&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gelu&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mf">0.5&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tanh&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sqrt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mf">0.044715&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">**&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># causal mask: query position i may only see key position j &amp;lt;= i&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">causal_mask&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">triu&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ones&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">T&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">T&lt;/span>&lt;span class="p">)),&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">astype&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">bool&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># True = masked out&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---------------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># STAGE 0: token ids -&amp;gt; embeddings -&amp;gt; + positional embedding&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---------------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;STAGE 0: token ids -&amp;gt; embedding -&amp;gt; + positional embedding&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">token_ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">array&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="c1"># toy input sequence, length T=4&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;token_ids:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">token_ids&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34; shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">token_ids&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">embed_table&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">vocab_size&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_model&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embed_table&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">token_ids&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1"># (T, d_model)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">x = embedding lookup, shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">pos_embed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">T&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_model&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">pos_embed&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">x after + positional embedding, shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---------------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Transformer layers&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---------------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">layer&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num_layers&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;LAYER &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">layer&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -- pre-attention LayerNorm&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x_ln&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">layernorm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;x_ln shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x_ln&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x_ln&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;LAYER &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">layer&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -- project to Q, K, V (x_ln @ W_Q / W_K / W_V)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">W_Q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_model&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">W_K&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_model&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">W_V&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_model&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">W_O&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_model&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x_ln&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_Q&lt;/span> &lt;span class="c1"># (T, d_model)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">K&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x_ln&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_K&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">V&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x_ln&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_V&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Q shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">K shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">K&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">K&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">V shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">V&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">V&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;LAYER &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">layer&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -- reshape last dim into (n_heads, d_head)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Qh&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reshape&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">T&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_heads&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_head&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">transpose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># (n_heads, T, d_head)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Kh&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">K&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reshape&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">T&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_heads&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_head&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">transpose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Vh&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">V&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reshape&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">T&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_heads&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_head&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">transpose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Qh shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Qh&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34; = (n_heads, T, d_head)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Head 0 Q (T,d_head):&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Qh&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Head 1 Q (T,d_head):&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Qh&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;LAYER &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">layer&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -- Q @ Kᵀ -&amp;gt; scores (T,T), causal masked, softmax&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">head_outputs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">h&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_heads&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Qh&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">Kh&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">T&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sqrt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_head&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># (T, T)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scores_masked&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">where&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">causal_mask&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mf">1e9&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scores&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">-- Head &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> --&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;raw scores (T,T):&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scores&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;causal-masked scores:&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scores_masked&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">weights&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">softmax&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">scores_masked&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;softmax weights (each row sums to 1):&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">weights&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;row sums:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">weights&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">out_h&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">weights&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">Vh&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1"># (T, d_head)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;head &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> output = weights @ V, shape &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">out_h&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">out_h&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">head_outputs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">out_h&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;LAYER &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">layer&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -- concat heads, x W_O, residual add&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">concat&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">concatenate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">head_outputs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># (T, d_model)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;concat heads shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">concat&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">concat&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attn_out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">concat&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_O&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">attn_out = concat @ W_O, shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">attn_out&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">attn_out&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">attn_out&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">x after residual add, shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;LAYER &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">layer&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -- pre-FFN LayerNorm -&amp;gt; FFN (up, GELU, down) -&amp;gt; residual&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x_ln2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">layernorm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">W_up&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_ff&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">W_down&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_ff&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d_model&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">hidden&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gelu&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x_ln2&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_up&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;hidden = gelu(x_ln2 @ W_up), shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hidden&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hidden&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ffn_out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">hidden&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_down&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">ffn_out = hidden @ W_down, shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ffn_out&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ffn_out&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">ffn_out&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">x after FFN residual add, shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---------------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Final: LayerNorm -&amp;gt; unembed -&amp;gt; logits -&amp;gt; next-token probabilities&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># ---------------------------------------------------------------------&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">section&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;FINAL: LayerNorm -&amp;gt; unembed -&amp;gt; logits -&amp;gt; next-token probabilities&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">x_final&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">layernorm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">W_unembed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_model&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vocab_size&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.3&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">logits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x_final&lt;/span> &lt;span class="o">@&lt;/span> &lt;span class="n">W_unembed&lt;/span> &lt;span class="c1"># (T, vocab_size)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;logits shape:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">logits&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shape&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">logits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">probs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">softmax&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logits&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">next-token probabilities per position (rows sum to 1):&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">probs&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;row sums:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">probs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">next_token_pred&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">probs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argmax&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">axis&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">argmax predicted token id at every position:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">next_token_pred&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;only the LAST position&amp;#39;s row is the actual &amp;#39;next token&amp;#39; prediction:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">next_token_pred&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The masked score matrix is the part worth staring at: row 0 collapses to &lt;code>[1,0,0,0]&lt;/code> after softmax (the first token can only attend to itself), while row 3 gets a genuine distribution across all four positions: proof the causal mask is doing exactly what it should.&lt;/p>
&lt;hr>
&lt;h2 id="part-4-what-is-the-ffn-actually-for">Part 4: What is the FFN actually &lt;em>for&lt;/em>?&lt;/h2>
&lt;h3 id="what-do-w_up-and-w_down-do-intuitively">What do &lt;code>W_up&lt;/code> and &lt;code>W_down&lt;/code> do, intuitively?&lt;/h3>
&lt;p>Shape-wise: &lt;code>W_up&lt;/code> is &lt;code>(d_model, d_ff)&lt;/code>: expansion. &lt;code>W_down&lt;/code> is &lt;code>(d_ff, d_model)&lt;/code>: contraction back to fit the residual add. But the &lt;em>functional&lt;/em> answer comes from real interpretability research (Geva et al., EMNLP 2021, &lt;em>&amp;ldquo;Transformer Feed-Forward Layers Are Key-Value Memories&amp;rdquo;&lt;/em>): each of the &lt;code>d_ff&lt;/code> hidden units behaves like one entry in a lookup table. &lt;code>W_up&lt;/code>&amp;rsquo;s columns are &lt;strong>keys&lt;/strong>: learned pattern detectors a token gets dot-producted against. GELU is the gate deciding how strongly each pattern fired. &lt;code>W_down&lt;/code>&amp;rsquo;s rows are &lt;strong>values&lt;/strong>: what gets added if that pattern fired.&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 400" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>FFN shape flow: narrow, wide, narrow again&lt;/title>
&lt;defs>&lt;marker id="a6" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;rect x="250" y="40" width="180" height="56" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="58" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">x_ln2&lt;/text>
&lt;text x="340" y="76" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">(T,d_model) = (4,8)&lt;/text>
&lt;line x1="340" y1="96" x2="340" y2="120" stroke="#888780" stroke-width="1.5" marker-end="url(#a6)"/>
&lt;rect x="150" y="120" width="380" height="56" rx="8" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="340" y="138" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#085041">hidden = GELU(x_ln2 @ W_up)&lt;/text>
&lt;text x="340" y="156" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">(T,d_ff) = (4,16), nonlinearity here&lt;/text>
&lt;line x1="340" y1="176" x2="340" y2="200" stroke="#888780" stroke-width="1.5" marker-end="url(#a6)"/>
&lt;rect x="250" y="200" width="180" height="56" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="218" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">ffn_out&lt;/text>
&lt;text x="340" y="236" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">hidden @ W_down → (4,8)&lt;/text>
&lt;line x1="340" y1="256" x2="340" y2="280" stroke="#888780" stroke-width="1.5" marker-end="url(#a6)"/>
&lt;rect x="180" y="280" width="320" height="56" rx="8" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="340" y="298" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">x = x + ffn_out&lt;/text>
&lt;text x="340" y="316" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#633806">residual add, shapes must match: (4,8)&lt;/text>
&lt;text x="340" y="360" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Without GELU, two linear layers collapse into one, no extra power&lt;/text>
&lt;text x="340" y="380" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">The residual add is why ffn_out must return to d_model, not stay at d_ff&lt;/text>
&lt;/svg>
&lt;p>I proved the &amp;ldquo;collapse without GELU&amp;rdquo; claim rather than just asserting it: &lt;code>(x @ W_up) @ W_down&lt;/code> computed directly is numerically identical to &lt;code>x @ (W_up @ W_down)&lt;/code> collapsed into a single &lt;code>(d_model, d_model)&lt;/code> matrix, and &lt;code>np.allclose&lt;/code> returns &lt;code>True&lt;/code>. Add GELU back in and the two stop matching entirely. The nonlinearity is the &lt;em>entire&lt;/em> reason the wide middle layer buys any extra capacity.&lt;/p>
&lt;h3 id="what-does-the-value-actually-promote">What does the &amp;ldquo;value&amp;rdquo; actually promote?&lt;/h3>
&lt;p>This is the part that made it click for me. A follow-up paper (Geva et al., EMNLP 2022) projects each value-vector through the model&amp;rsquo;s &lt;strong>unembedding matrix&lt;/strong>, the same matrix used at the very end to turn a hidden state into vocabulary logits, and finds each one promotes a coherent cluster of &lt;em>actual words&lt;/em>:&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;A value vector might promote the cluster {Paris, France, French, European, Seine}, or the cluster {multiply, divide, arithmetic, calculate}.&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;svg width="100%" viewBox="0 0 680 380" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>The FFN as a key-value memory&lt;/title>
&lt;defs>&lt;marker id="a7" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;rect x="240" y="40" width="200" height="44" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="62" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">token: "Paris"&lt;/text>
&lt;line x1="340" y1="84" x2="110" y2="110" stroke="#888780" stroke-width="1.5" marker-end="url(#a7)"/>
&lt;line x1="340" y1="84" x2="263" y2="110" stroke="#888780" stroke-width="1.5" marker-end="url(#a7)"/>
&lt;line x1="340" y1="84" x2="416" y2="110" stroke="#888780" stroke-width="1.5" marker-end="url(#a7)"/>
&lt;line x1="340" y1="84" x2="569" y2="110" stroke="#888780" stroke-width="1.5" marker-end="url(#a7)"/>
&lt;rect x="40" y="110" width="140" height="56" rx="8" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="110" y="128" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">capital cities&lt;/text>
&lt;text x="110" y="146" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#633806">fires strongly&lt;/text>
&lt;rect x="193" y="110" width="140" height="56" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="263" y="128" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">past tense&lt;/text>
&lt;text x="263" y="146" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">barely fires&lt;/text>
&lt;rect x="346" y="110" width="140" height="56" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="416" y="128" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">numbers&lt;/text>
&lt;text x="416" y="146" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">barely fires&lt;/text>
&lt;rect x="499" y="110" width="140" height="56" rx="8" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="569" y="128" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">place names&lt;/text>
&lt;text x="569" y="146" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#633806">fires strongly&lt;/text>
&lt;line x1="110" y1="166" x2="340" y2="230" stroke="#BA7517" stroke-width="3" opacity="0.85"/>
&lt;line x1="569" y1="166" x2="340" y2="230" stroke="#BA7517" stroke-width="3" opacity="0.85"/>
&lt;line x1="263" y1="166" x2="340" y2="230" stroke="#888780" stroke-width="1" opacity="0.35"/>
&lt;line x1="416" y1="166" x2="340" y2="230" stroke="#888780" stroke-width="1" opacity="0.35"/>
&lt;rect x="190" y="230" width="300" height="56" rx="8" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="340" y="248" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#085041">weighted sum of active values&lt;/text>
&lt;text x="340" y="266" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#085041">added into the residual stream&lt;/text>
&lt;text x="340" y="318" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">W_up learns the "keys" (patterns), W_down learns the "values" (what to add)&lt;/text>
&lt;text x="340" y="338" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Every one of the d_ff neurons does this at once, learned from training data&lt;/text>
&lt;text x="340" y="358" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Source: Geva et al., EMNLP 2021 &amp;amp; 2022&lt;/text>
&lt;/svg>
&lt;p>Important honesty check: this story only exists &lt;em>after&lt;/em> training on real data. In the toy script above, &lt;code>W_up&lt;/code>/&lt;code>W_down&lt;/code> are random noise. There are no real &amp;ldquo;capital cities&amp;rdquo; detectors in there. The finding is that gradient descent &lt;em>discovers&lt;/em> useful pattern-detectors on its own during training, purely because they&amp;rsquo;re a useful building block for predicting the next token well.&lt;/p>
&lt;h3 id="why-add-to-the-residual-stream-instead-of-overwriting-it">Why add to the residual stream instead of overwriting it?&lt;/h3>
&lt;p>Because the value vectors are literally votes toward specific output words, and &lt;strong>addition is the only operation that lets those votes accumulate instead of erasing each other.&lt;/strong> This is Anthropic&amp;rsquo;s own framing from &lt;em>&amp;ldquo;A Mathematical Framework for Transformer Circuits&amp;rdquo;&lt;/em> (Elhage et al., 2021):&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;Rather than overwriting the results from previous layers, each layer of the residual block &amp;lsquo;reads&amp;rsquo; its input from the residual stream&amp;hellip; and then &amp;lsquo;writes&amp;rsquo; its result to the residual stream by adding a linear projection back in.&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;p>If FFN layers overwrote instead of added, deep networks would be pointless: layer 40 couldn&amp;rsquo;t build on anything layer 3 discovered.&lt;/p>
&lt;h3 id="is-w_down-doing-something-similar-to-v-in-qkv">Is &lt;code>W_down&lt;/code> doing something similar to &lt;code>V&lt;/code> in Q/K/V?&lt;/h3>
&lt;p>Yes, genuinely, not just an analogy. Geva et al. deliberately wrote the FFN formula to mirror attention&amp;rsquo;s: &lt;strong>match → weight → blend&lt;/strong>, in both cases. Attention: &lt;code>output = Σ softmax(Q·K) × V&lt;/code>. FFN: &lt;code>output = Σ GELU(x·W_up) × W_down&lt;/code>. Same template.&lt;/p>
&lt;p>The one real, load-bearing difference: attention&amp;rsquo;s keys are &lt;strong>dynamic&lt;/strong>: &lt;code>K = x @ W_K&lt;/code>, computed fresh from whatever&amp;rsquo;s in context. The FFN&amp;rsquo;s keys are &lt;strong>static, learned parameters&lt;/strong>, fixed the moment training ends. That&amp;rsquo;s precisely why the FFN needs zero cross-token communication while attention&amp;rsquo;s score step is the one place that genuinely does. (Second difference, more of a footnote: attention&amp;rsquo;s weights are forced to sum to 1 via softmax; GELU has no such constraint, all &lt;code>d_ff&lt;/code> keys can fire independently, unconstrained.)&lt;/p>
&lt;hr>
&lt;h2 id="part-5-moe-dispatch-and-combine">Part 5: MoE: dispatch and combine&lt;/h2>
&lt;p>MoE replaces the single shared FFN with many smaller, specialized ones (&amp;ldquo;experts&amp;rdquo;), plus a &lt;strong>gate&lt;/strong> that decides, per token, which top-k experts should process it. The gate itself is a per-token linear layer, no communication needed yet.&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 380" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>MoE gate routing decision&lt;/title>
&lt;text x="340" y="30" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">Gate routing: top-2 experts per token (no communication yet)&lt;/text>
&lt;text x="247.5" y="75" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">e0&lt;/text>
&lt;text x="302.5" y="75" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">e1&lt;/text>
&lt;text x="357.5" y="75" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">e2&lt;/text>
&lt;text x="412.5" y="75" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">e3&lt;/text>
&lt;text x="205" y="117.5" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">t0&lt;/text>
&lt;text x="205" y="172.5" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">t1&lt;/text>
&lt;text x="205" y="227.5" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">t2&lt;/text>
&lt;text x="205" y="282.5" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">t3&lt;/text>
&lt;rect x="220" y="90" width="55" height="55" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;rect x="275" y="90" width="55" height="55" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;rect x="330" y="90" width="55" height="55" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="3 3"/>
&lt;rect x="385" y="90" width="55" height="55" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="3 3"/>
&lt;rect x="220" y="145" width="55" height="55" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;rect x="275" y="145" width="55" height="55" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;rect x="330" y="145" width="55" height="55" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="3 3"/>
&lt;rect x="385" y="145" width="55" height="55" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="3 3"/>
&lt;rect x="220" y="200" width="55" height="55" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;rect x="275" y="200" width="55" height="55" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="3 3"/>
&lt;rect x="330" y="200" width="55" height="55" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;rect x="385" y="200" width="55" height="55" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="3 3"/>
&lt;rect x="220" y="255" width="55" height="55" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;rect x="275" y="255" width="55" height="55" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="3 3"/>
&lt;rect x="330" y="255" width="55" height="55" fill="none" stroke="#888780" stroke-width="0.5" stroke-dasharray="3 3"/>
&lt;rect x="385" y="255" width="55" height="55" fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5"/>
&lt;text x="340" y="336" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Every token computes this independently and locally&lt;/text>
&lt;text x="340" y="356" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">e0 was picked by all 4 tokens, already a hot expert before any GPU is involved&lt;/text>
&lt;/svg>
&lt;p>If &lt;code>e0&lt;/code> and &lt;code>e1&lt;/code> live on one GPU while &lt;code>e2&lt;/code>/&lt;code>e3&lt;/code> live on another, each token&amp;rsquo;s hidden state physically has to travel to wherever its chosen experts are (&lt;strong>dispatch&lt;/strong>), get processed there, and travel back to be blended (&lt;strong>combine&lt;/strong>):&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 400" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>MoE dispatch and combine for a single token&lt;/title>
&lt;defs>&lt;marker id="a8" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;rect x="190" y="40" width="300" height="44" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="62" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">t0 hidden state (after attention)&lt;/text>
&lt;line x1="340" y1="84" x2="185" y2="104" stroke="#888780" stroke-width="1.5" marker-end="url(#a8)"/>
&lt;line x1="340" y1="84" x2="495" y2="104" stroke="#888780" stroke-width="1.5" marker-end="url(#a8)"/>
&lt;text x="220" y="98" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">dispatch&lt;/text>
&lt;text x="460" y="98" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">dispatch&lt;/text>
&lt;rect x="55" y="104" width="260" height="56" rx="8" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>
&lt;text x="185" y="122" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">GPU 0: expert e0&lt;/text>
&lt;text x="185" y="140" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#0C447C">FFN(t0) → output_e0&lt;/text>
&lt;rect x="365" y="104" width="260" height="56" rx="8" fill="#FAECE7" stroke="#D85A30" stroke-width="0.5"/>
&lt;text x="495" y="122" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#712B13">GPU 1: expert e1&lt;/text>
&lt;text x="495" y="140" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#712B13">FFN(t0) → output_e1&lt;/text>
&lt;line x1="185" y1="160" x2="340" y2="200" stroke="#888780" stroke-width="1.5" marker-end="url(#a8)"/>
&lt;line x1="495" y1="160" x2="340" y2="200" stroke="#888780" stroke-width="1.5" marker-end="url(#a8)"/>
&lt;text x="240" y="188" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">combine&lt;/text>
&lt;text x="440" y="188" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">combine&lt;/text>
&lt;rect x="190" y="200" width="300" height="56" rx="8" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="340" y="218" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">combine: w0·out_e0 + w1·out_e1&lt;/text>
&lt;text x="340" y="236" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#633806">w0, w1 = softmax over t0's top-2 scores&lt;/text>
&lt;line x1="340" y1="256" x2="340" y2="280" stroke="#888780" stroke-width="1.5" marker-end="url(#a8)"/>
&lt;rect x="190" y="280" width="300" height="44" rx="8" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>
&lt;text x="340" y="302" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">final MoE output for t0&lt;/text>
&lt;text x="340" y="356" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">This repeats independently for every token, simultaneously&lt;/text>
&lt;text x="340" y="376" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">No LSE needed, top-2 weights are already normalized before dispatch&lt;/text>
&lt;/svg>
&lt;p>Combine here is simpler than CP&amp;rsquo;s merge: the gate already normalized &lt;code>w0, w1&lt;/code> locally before dispatch, so it&amp;rsquo;s a plain weighted sum, no rescaling trick required.&lt;/p>
&lt;h3 id="why-does-this-create-a-straggler">Why does this create a straggler?&lt;/h3>
&lt;p>All 4 tokens&amp;rsquo; dispatch calls are packed into &lt;strong>one shared collective&lt;/strong>, not 4 independent sends. If &lt;code>e0&lt;/code> gets picked by every token and &lt;code>e1&lt;/code> gets picked by fewer, the GPU hosting &lt;code>e0&lt;/code> ends up with far more total traffic than the others, and the collective &lt;em>as a whole&lt;/em> only completes once the busiest GPU finishes:&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 330" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>Dispatch timeline showing GPU wait times&lt;/title>
&lt;text x="598" y="46" text-anchor="end" font-family="sans-serif" font-size="12" fill="#5F5E5A">Barrier, all must arrive here&lt;/text>
&lt;line x1="600" y1="58" x2="600" y2="250" stroke="#5F5E5A" stroke-width="1.5" stroke-dasharray="4 3"/>
&lt;text x="598" y="256" text-anchor="end" font-family="sans-serif" font-size="12" fill="#5F5E5A">Only then does the next layer start&lt;/text>
&lt;text x="128" y="74" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 0 (10)&lt;/text>
&lt;rect x="135" y="62" width="52" height="24" rx="4" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;rect x="187" y="62" width="413" height="24" rx="4" fill="none" stroke="#5F5E5A" stroke-width="1" stroke-dasharray="4 3"/>
&lt;text x="128" y="124" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 1 (90)&lt;/text>
&lt;rect x="135" y="112" width="465" height="24" rx="4" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="590" y="124" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#633806">straggler&lt;/text>
&lt;text x="128" y="174" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 2 (15)&lt;/text>
&lt;rect x="135" y="162" width="78" height="24" rx="4" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;rect x="213" y="162" width="387" height="24" rx="4" fill="none" stroke="#5F5E5A" stroke-width="1" stroke-dasharray="4 3"/>
&lt;text x="128" y="224" text-anchor="end" dominant-baseline="central" font-family="sans-serif" font-size="12" fill="#5F5E5A">GPU 3 (20)&lt;/text>
&lt;rect x="135" y="212" width="103" height="24" rx="4" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;rect x="238" y="212" width="362" height="24" rx="4" fill="none" stroke="#5F5E5A" stroke-width="1" stroke-dasharray="4 3"/>
&lt;rect x="135" y="272" width="16" height="12" rx="3" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="157" y="281" font-family="sans-serif" font-size="12" fill="#5F5E5A">Moving data (dispatch)&lt;/text>
&lt;rect x="340" y="272" width="16" height="12" rx="3" fill="none" stroke="#5F5E5A" stroke-width="1" stroke-dasharray="4 3"/>
&lt;text x="362" y="281" font-family="sans-serif" font-size="12" fill="#5F5E5A">Idle, waiting at barrier&lt;/text>
&lt;/svg>
&lt;p>The idle GPUs&amp;rsquo; hardware is fully free during the dashed span. There&amp;rsquo;s just nothing useful for them to do, because the next layer&amp;rsquo;s computation needs &lt;em>every&lt;/em> GPU&amp;rsquo;s dispatched tokens assembled together before it can proceed at all. This is exactly the problem UltraEP solves by replicating a hot expert&amp;rsquo;s weights onto a spare GPU in real time and splitting the token load across the replicas, reacting to the &lt;em>exact&lt;/em>, current-iteration load rather than periodic, stale statistics the way its predecessor (EPLB) does.&lt;/p>
&lt;p>One clarification worth keeping: &lt;strong>continuous batching solves a different problem than this.&lt;/strong> It changes which requests are included &lt;em>between&lt;/em> iterations. Within one iteration, every included token is glued into the same batched kernel calls and the same collective, that&amp;rsquo;s the level the straggler problem actually lives at.&lt;/p>
&lt;hr>
&lt;h2 id="part-6-the-collective-operations-underneath-everything">Part 6: The collective operations underneath everything&lt;/h2>
&lt;p>Everything above eventually reduces to a handful of named collective operations. Worth knowing them by name and cost, not just by what we&amp;rsquo;ve called them informally.&lt;/p>
&lt;p>&lt;strong>Broadcast / Scatter&lt;/strong>: one rank&amp;rsquo;s data either copied identically to everyone (broadcast), or cut into pieces with one distinct piece per rank (scatter). &lt;strong>Gather / All-Gather&lt;/strong>: the reverse; everyone&amp;rsquo;s data converges onto one rank (gather) or onto every rank (all-gather). &lt;strong>Reduce / All-Reduce&lt;/strong>: same converge shape, but the center step does real work (a sum), landing on one rank or all of them:&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 460" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>Reduce versus all-reduce&lt;/title>
&lt;defs>&lt;marker id="a9" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;text x="340" y="26" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">Reduce (sum)&lt;/text>
&lt;text x="105" y="42" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">R0&lt;/text>&lt;text x="252" y="42" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">R1&lt;/text>&lt;text x="399" y="42" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">R2&lt;/text>&lt;text x="546" y="42" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">R3&lt;/text>
&lt;circle cx="105" cy="70" r="20" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>&lt;text x="105" y="70" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">a&lt;/text>
&lt;circle cx="252" cy="70" r="20" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>&lt;text x="252" y="70" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">b&lt;/text>
&lt;circle cx="399" cy="70" r="20" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>&lt;text x="399" y="70" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">c&lt;/text>
&lt;circle cx="546" cy="70" r="20" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>&lt;text x="546" y="70" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">d&lt;/text>
&lt;line x1="105" y1="90" x2="105" y2="140" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="252" y1="90" x2="105" y2="140" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="399" y1="90" x2="105" y2="140" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="546" y1="90" x2="105" y2="140" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;circle cx="105" cy="160" r="20" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>&lt;text x="105" y="160" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">Σ&lt;/text>
&lt;circle cx="252" cy="160" r="20" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>&lt;text x="252" y="160" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">-&lt;/text>
&lt;circle cx="399" cy="160" r="20" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>&lt;text x="399" y="160" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">-&lt;/text>
&lt;circle cx="546" cy="160" r="20" fill="#F1EFE8" stroke="#888780" stroke-width="0.5"/>&lt;text x="546" y="160" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">-&lt;/text>
&lt;text x="340" y="200" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Only R0 receives the summed result&lt;/text>
&lt;text x="340" y="240" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">All-Reduce (sum)&lt;/text>
&lt;text x="105" y="256" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">R0&lt;/text>&lt;text x="252" y="256" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">R1&lt;/text>&lt;text x="399" y="256" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">R2&lt;/text>&lt;text x="546" y="256" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">R3&lt;/text>
&lt;circle cx="105" cy="284" r="20" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>&lt;text x="105" y="284" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">a&lt;/text>
&lt;circle cx="252" cy="284" r="20" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>&lt;text x="252" y="284" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">b&lt;/text>
&lt;circle cx="399" cy="284" r="20" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>&lt;text x="399" y="284" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">c&lt;/text>
&lt;circle cx="546" cy="284" r="20" fill="#E6F1FB" stroke="#378ADD" stroke-width="0.5"/>&lt;text x="546" y="284" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#0C447C">d&lt;/text>
&lt;line x1="105" y1="304" x2="340" y2="328" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="252" y1="304" x2="340" y2="328" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="399" y1="304" x2="340" y2="328" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="546" y1="304" x2="340" y2="328" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;rect x="300" y="328" width="80" height="24" rx="6" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>
&lt;text x="340" y="340" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">Σ sum&lt;/text>
&lt;line x1="340" y1="352" x2="105" y2="380" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="340" y1="352" x2="252" y2="380" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="340" y1="352" x2="399" y2="380" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;line x1="340" y1="352" x2="546" y2="380" stroke="#888780" stroke-width="1.5" marker-end="url(#a9)"/>
&lt;circle cx="105" cy="400" r="20" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>&lt;text x="105" y="400" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">Σ&lt;/text>
&lt;circle cx="252" cy="400" r="20" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>&lt;text x="252" y="400" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">Σ&lt;/text>
&lt;circle cx="399" cy="400" r="20" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>&lt;text x="399" y="400" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">Σ&lt;/text>
&lt;circle cx="546" cy="400" r="20" fill="#FAEEDA" stroke="#BA7517" stroke-width="0.5"/>&lt;text x="546" y="400" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-size="14" font-weight="500" fill="#633806">Σ&lt;/text>
&lt;text x="340" y="440" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Every rank ends up holding the identical sum&lt;/text>
&lt;/svg>
&lt;p>&lt;strong>All-reduce is exactly what combined TP&amp;rsquo;s two head outputs earlier.&lt;/strong> Reduce-scatter is the same converge step, but instead of broadcasting the whole sum back, each rank keeps only its own slice, and in real implementations, &lt;strong>all-reduce isn&amp;rsquo;t a separate primitive at all, it&amp;rsquo;s reduce-scatter followed by all-gather&lt;/strong>, chained together.&lt;/p>
&lt;p>&lt;strong>All-to-all&lt;/strong> is the odd one out: no converge/diverge shape at all, just every rank sending something different to every other rank simultaneously. It&amp;rsquo;s literally a matrix transpose:&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 300" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>All-to-all as a matrix transpose&lt;/title>
&lt;defs>&lt;marker id="a10" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">&lt;path d="M2 1L8 5L2 9" fill="none" stroke="#888780" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>&lt;/marker>&lt;/defs>
&lt;text x="150" y="26" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">before (row = sender)&lt;/text>
&lt;g fill="#EEEDFE" stroke="#7F77DD" stroke-width="0.5">
&lt;rect x="80" y="40" width="36" height="36"/>&lt;rect x="116" y="40" width="36" height="36"/>&lt;rect x="152" y="40" width="36" height="36"/>&lt;rect x="188" y="40" width="36" height="36"/>
&lt;rect x="80" y="76" width="36" height="36"/>&lt;rect x="116" y="76" width="36" height="36"/>&lt;rect x="152" y="76" width="36" height="36"/>&lt;rect x="188" y="76" width="36" height="36"/>
&lt;rect x="80" y="112" width="36" height="36"/>&lt;rect x="116" y="112" width="36" height="36"/>&lt;rect x="152" y="112" width="36" height="36"/>&lt;rect x="188" y="112" width="36" height="36"/>
&lt;rect x="80" y="148" width="36" height="36"/>&lt;rect x="116" y="148" width="36" height="36"/>&lt;rect x="152" y="148" width="36" height="36"/>&lt;rect x="188" y="148" width="36" height="36"/>
&lt;/g>
&lt;g font-family="sans-serif" font-size="12" fill="#3C3489" text-anchor="middle">
&lt;text x="98" y="58" dominant-baseline="central">00&lt;/text>&lt;text x="134" y="58" dominant-baseline="central">01&lt;/text>&lt;text x="170" y="58" dominant-baseline="central">02&lt;/text>&lt;text x="206" y="58" dominant-baseline="central">03&lt;/text>
&lt;text x="98" y="94" dominant-baseline="central">10&lt;/text>&lt;text x="134" y="94" dominant-baseline="central">11&lt;/text>&lt;text x="170" y="94" dominant-baseline="central">12&lt;/text>&lt;text x="206" y="94" dominant-baseline="central">13&lt;/text>
&lt;text x="98" y="130" dominant-baseline="central">20&lt;/text>&lt;text x="134" y="130" dominant-baseline="central">21&lt;/text>&lt;text x="170" y="130" dominant-baseline="central">22&lt;/text>&lt;text x="206" y="130" dominant-baseline="central">23&lt;/text>
&lt;text x="98" y="166" dominant-baseline="central">30&lt;/text>&lt;text x="134" y="166" dominant-baseline="central">31&lt;/text>&lt;text x="170" y="166" dominant-baseline="central">32&lt;/text>&lt;text x="206" y="166" dominant-baseline="central">33&lt;/text>
&lt;/g>
&lt;text x="152" y="200" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">rank i's row j = piece sent to rank j&lt;/text>
&lt;line x1="260" y1="112" x2="420" y2="112" stroke="#888780" stroke-width="1.5" marker-end="url(#a10)"/>
&lt;text x="340" y="98" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">all-to-all&lt;/text>
&lt;text x="530" y="26" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">after (row = receiver)&lt;/text>
&lt;g fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5">
&lt;rect x="460" y="40" width="36" height="36"/>&lt;rect x="496" y="40" width="36" height="36"/>&lt;rect x="532" y="40" width="36" height="36"/>&lt;rect x="568" y="40" width="36" height="36"/>
&lt;rect x="460" y="76" width="36" height="36"/>&lt;rect x="496" y="76" width="36" height="36"/>&lt;rect x="532" y="76" width="36" height="36"/>&lt;rect x="568" y="76" width="36" height="36"/>
&lt;rect x="460" y="112" width="36" height="36"/>&lt;rect x="496" y="112" width="36" height="36"/>&lt;rect x="532" y="112" width="36" height="36"/>&lt;rect x="568" y="112" width="36" height="36"/>
&lt;rect x="460" y="148" width="36" height="36"/>&lt;rect x="496" y="148" width="36" height="36"/>&lt;rect x="532" y="148" width="36" height="36"/>&lt;rect x="568" y="148" width="36" height="36"/>
&lt;/g>
&lt;g font-family="sans-serif" font-size="12" fill="#085041" text-anchor="middle">
&lt;text x="478" y="58" dominant-baseline="central">00&lt;/text>&lt;text x="514" y="58" dominant-baseline="central">10&lt;/text>&lt;text x="550" y="58" dominant-baseline="central">20&lt;/text>&lt;text x="586" y="58" dominant-baseline="central">30&lt;/text>
&lt;text x="478" y="94" dominant-baseline="central">01&lt;/text>&lt;text x="514" y="94" dominant-baseline="central">11&lt;/text>&lt;text x="550" y="94" dominant-baseline="central">21&lt;/text>&lt;text x="586" y="94" dominant-baseline="central">31&lt;/text>
&lt;text x="478" y="130" dominant-baseline="central">02&lt;/text>&lt;text x="514" y="130" dominant-baseline="central">12&lt;/text>&lt;text x="550" y="130" dominant-baseline="central">22&lt;/text>&lt;text x="586" y="130" dominant-baseline="central">32&lt;/text>
&lt;text x="478" y="166" dominant-baseline="central">03&lt;/text>&lt;text x="514" y="166" dominant-baseline="central">13&lt;/text>&lt;text x="550" y="166" dominant-baseline="central">23&lt;/text>&lt;text x="586" y="166" dominant-baseline="central">33&lt;/text>
&lt;/g>
&lt;text x="530" y="200" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">rank i's row j = piece received from rank j&lt;/text>
&lt;text x="340" y="250" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Columns of the before-grid become rows of the after-grid&lt;/text>
&lt;text x="340" y="270" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">In MoE dispatch, cell (i,j) = "how many of rank i's tokens go to rank j's expert"&lt;/text>
&lt;/svg>
&lt;h3 id="how-much-does-each-of-these-actually-cost">How much does each of these actually cost?&lt;/h3>
&lt;p>The standard tool is the &lt;strong>α-β model&lt;/strong>: total time ≈ (number of messages) × α (fixed latency per message) + (bytes moved) × β (per-byte cost). Whether an operation is latency-bound or bandwidth-bound depends on which term dominates, and that&amp;rsquo;s where the choice of &lt;em>algorithm&lt;/em>, not just which collective, matters enormously.&lt;/p>
&lt;p>The single most important concrete result here: &lt;strong>naive all-reduce&lt;/strong> (everyone sends to rank 0, it sums, it broadcasts back) costs &lt;code>(P-1) × n&lt;/code> bytes on the busiest rank, linear in the number of ranks. &lt;strong>Ring all-reduce&lt;/strong> (pass data around a ring instead) costs &lt;code>2(P-1)/P × n&lt;/code>, which &lt;em>approaches 2n and flatlines&lt;/em> as P grows, essentially independent of rank count:&lt;/p>
&lt;svg width="100%" viewBox="0 0 680 390" role="img" xmlns="http://www.w3.org/2000/svg">
&lt;title>Naive versus ring all-reduce cost&lt;/title>
&lt;text x="340" y="26" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="500" fill="#444441">Bytes moved per rank (× message size n)&lt;/text>
&lt;rect x="108" y="276.5" width="28" height="3.5" rx="2" fill="#FAECE7" stroke="#D85A30" stroke-width="0.5"/>
&lt;rect x="144" y="276.5" width="28" height="3.5" rx="2" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="122" y="266" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">1n&lt;/text>
&lt;text x="158" y="266" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">1n&lt;/text>
&lt;rect x="258" y="255.5" width="28" height="24.5" rx="2" fill="#FAECE7" stroke="#D85A30" stroke-width="0.5"/>
&lt;rect x="294" y="273.9" width="28" height="6.1" rx="2" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="272" y="247" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">7n&lt;/text>
&lt;text x="308" y="265" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">1.75n&lt;/text>
&lt;rect x="408" y="171.5" width="28" height="108.5" rx="2" fill="#FAECE7" stroke="#D85A30" stroke-width="0.5"/>
&lt;rect x="444" y="273.2" width="28" height="6.8" rx="2" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="422" y="163" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">31n&lt;/text>
&lt;text x="458" y="265" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">1.94n&lt;/text>
&lt;rect x="558" y="59.5" width="28" height="220.5" rx="2" fill="#FAECE7" stroke="#D85A30" stroke-width="0.5"/>
&lt;rect x="594" y="273.1" width="28" height="6.9" rx="2" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="572" y="51" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">63n&lt;/text>
&lt;text x="608" y="265" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">1.97n&lt;/text>
&lt;text x="140" y="300" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">P=2&lt;/text>
&lt;text x="290" y="300" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">P=8&lt;/text>
&lt;text x="440" y="300" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">P=32&lt;/text>
&lt;text x="590" y="300" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">P=64&lt;/text>
&lt;rect x="220" y="330" width="16" height="12" rx="3" fill="#FAECE7" stroke="#D85A30" stroke-width="0.5"/>
&lt;text x="242" y="339" font-family="sans-serif" font-size="12" fill="#5F5E5A">naive&lt;/text>
&lt;rect x="340" y="330" width="16" height="12" rx="3" fill="#E1F5EE" stroke="#1D9E75" stroke-width="0.5"/>
&lt;text x="362" y="339" font-family="sans-serif" font-size="12" fill="#5F5E5A">ring&lt;/text>
&lt;text x="340" y="368" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#5F5E5A">Ring's cost barely grows as P scales, naive grows linearly, unbounded&lt;/text>
&lt;/svg>
&lt;p>That flat curve is why ring all-reduce became the default in every serious distributed training framework. The tradeoff: ring needs &lt;code>2(P-1)&lt;/code> sequential steps, so for &lt;em>tiny&lt;/em> messages the fixed per-message latency can dominate anyway. Real implementations (NCCL) switch strategy based on message size.&lt;/p>
&lt;p>The rest, briefly: &lt;strong>broadcast / scatter / gather&lt;/strong> move &lt;code>~n&lt;/code> bytes per rank, roughly &lt;code>P&lt;/code>-independent. &lt;strong>All-gather genuinely does scale with &lt;code>P&lt;/code>&lt;/strong>: the combined result is &lt;code>P·n&lt;/code>, so each rank must receive &lt;code>(P-1)·n&lt;/code> new bytes; no algorithm avoids this, since the information itself grows. &lt;strong>Reduce-scatter&lt;/strong> is exactly half of ring all-reduce (the first phase). &lt;strong>All-to-all&lt;/strong> is bandwidth-comparable to reduce-scatter, but its real cost is &lt;em>latency&lt;/em>: it needs &lt;code>P-1&lt;/code> distinct messages, and if each one carries only a handful of tokens (the common MoE case), the fixed per-message overhead &lt;code>α&lt;/code> dominates over the actual bytes. That&amp;rsquo;s the precise reason NanoCP builds a routing-based backend instead of calling a generic all-to-all: it attacks the message-count term directly, skipping pairs that have nothing real to send, rather than paying for a dense &lt;code>P×P&lt;/code> mesh every single request.&lt;/p>
&lt;hr>
&lt;h2 id="references">References&lt;/h2>
&lt;p>The two papers this whole post is built around:&lt;/p>
&lt;ul>
&lt;li>Chen, J. et al. &amp;ldquo;NanoCP: Request-Level Dynamic Context Parallelism for Data-Expert Parallel Decoding.&amp;rdquo; &lt;a href="https://arxiv.org/abs/2605.21100" target="_blank" rel="noopener">arXiv:2605.21100&lt;/a>&lt;/li>
&lt;li>Wei, X. et al. &amp;ldquo;UltraEP: Unleash MoE Training and Inference on Rack-Scale Nodes with Near-Optimal Load Balancing.&amp;rdquo; &lt;a href="https://arxiv.org/abs/2606.04101" target="_blank" rel="noopener">arXiv:2606.04101&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Attention, tensor parallelism, and MLA:&lt;/p>
&lt;ul>
&lt;li>ROCm, &amp;ldquo;The vLLM MoE Playbook.&amp;rdquo; &lt;a href="https://rocm.blogs.amd.com/software-tools-optimization/vllm-moe-guide/README.html" target="_blank" rel="noopener">rocm.blogs.amd.com&lt;/a>&lt;/li>
&lt;li>Jarvislabs, &amp;ldquo;Scaling LLM Inference: DP, PP, TP.&amp;rdquo; &lt;a href="https://docs.jarvislabs.ai/blog/scaling-llm-inference-dp-pp-tp" target="_blank" rel="noopener">docs.jarvislabs.ai&lt;/a>&lt;/li>
&lt;li>vLLM Docs, &amp;ldquo;Data Parallel Deployment.&amp;rdquo; &lt;a href="https://docs.vllm.ai/en/latest/serving/data_parallel_deployment/" target="_blank" rel="noopener">docs.vllm.ai&lt;/a>&lt;/li>
&lt;li>Brenndoerfer, M. &amp;ldquo;Tensor Parallelism: Column, Row, and Megatron Patterns.&amp;rdquo; &lt;a href="https://mbrenndoerfer.com/writing/tensor-parallelism-column-row-megatron-communication-patterns" target="_blank" rel="noopener">mbrenndoerfer.com&lt;/a>&lt;/li>
&lt;li>Shoeybi, M. et al. &amp;ldquo;Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism.&amp;rdquo; &lt;a href="https://arxiv.org/pdf/2104.04473" target="_blank" rel="noopener">arXiv:2104.04473&lt;/a>&lt;/li>
&lt;li>Jang, I. &amp;ldquo;Analyzing Parallelization of Attention.&amp;rdquo; &lt;a href="https://insujang.github.io/2022-08-03/analyzing-parallelization-of-attention/" target="_blank" rel="noopener">insujang.github.io&lt;/a>&lt;/li>
&lt;li>Bhatia, N. et al. &amp;ldquo;Helix Parallelism: Rethinking Sharding Strategies for Interactive Multi-Million-Token LLM Decoding.&amp;rdquo; &lt;a href="https://arxiv.org/html/2507.07120v1" target="_blank" rel="noopener">arXiv:2507.07120&lt;/a>&lt;/li>
&lt;li>NVIDIA Developer Blog, &amp;ldquo;Multi-Million Token Real-Time Inference.&amp;rdquo; &lt;a href="https://developer.nvidia.com/blog/asking-an-encyclopedia-sized-question-how-to-make-the-world-smarter-with-multi-million-token-real-time-inference/" target="_blank" rel="noopener">developer.nvidia.com&lt;/a>&lt;/li>
&lt;li>vLLM GitHub, RFC for Helix Parallelism implementation. &lt;a href="https://github.com/vllm-project/vllm/issues/34018" target="_blank" rel="noopener">github.com/vllm-project/vllm/issues/34018&lt;/a>&lt;/li>
&lt;li>DeepSeek-AI, &amp;ldquo;DeepSeek-V2 Technical Report.&amp;rdquo; &lt;a href="https://arxiv.org/pdf/2405.04434" target="_blank" rel="noopener">arXiv:2405.04434&lt;/a>&lt;/li>
&lt;li>Vizuara, &amp;ldquo;Decoding Multi-Head Latent Attention,&amp;rdquo; Part 1 and Part 2. &lt;a href="https://vizuara.substack.com/p/decoding-multi-head-latent-attention" target="_blank" rel="noopener">vizuara.substack.com&lt;/a>&lt;/li>
&lt;li>Towards Data Science, &amp;ldquo;DeepSeek-V3 Explained 1: Multi-head Latent Attention.&amp;rdquo; &lt;a href="https://towardsdatascience.com/deepseek-v3-explained-1-multi-head-latent-attention-ed6bee2a67c4/" target="_blank" rel="noopener">towardsdatascience.com&lt;/a>&lt;/li>
&lt;li>NVIDIA/TensorRT-LLM GitHub, feature request discussing MLA weight replication under tensor parallelism.&lt;/li>
&lt;/ul>
&lt;p>Context parallelism, FlashAttention, and the online-softmax merge:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Dao, T. et al. &amp;ldquo;Flash-Decoding for long-context inference.&amp;rdquo; &lt;a href="https://pytorch.org/blog/flash-decoding/" target="_blank" rel="noopener">pytorch.org/blog&lt;/a> (mirrored at &lt;a href="https://princeton-nlp.github.io/flash-decoding/" target="_blank" rel="noopener">princeton-nlp.github.io&lt;/a>)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Meta AI, &amp;ldquo;Context Parallelism for Scalable Million-Token Inference.&amp;rdquo; &lt;a href="https://arxiv.org/pdf/2411.01783" target="_blank" rel="noopener">arXiv:2411.01783&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>HuggingFace Blog, &amp;ldquo;FlashAttention: Online Softmax.&amp;rdquo; &lt;a href="https://huggingface.co/blog/atharv6f/flash-attention-online-softmax" target="_blank" rel="noopener">huggingface.co/blog&lt;/a>
Serving architecture, memory, and scheduling:&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Kwon, W. et al. &amp;ldquo;Efficient Memory Management for Large Language Model Serving with PagedAttention,&amp;rdquo; explained by Brenndoerfer, M. &lt;a href="https://mbrenndoerfer.com/writing/paged-attention-vllm-kv-cache-memory-management" target="_blank" rel="noopener">mbrenndoerfer.com&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Zhong, Y. et al. &amp;ldquo;DistServe: Disaggregating Prefill and Decoding for Goodput-Optimized Large Language Model Serving.&amp;rdquo; &lt;a href="https://arxiv.org/abs/2401.09670" target="_blank" rel="noopener">arXiv:2401.09670&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>NVIDIA, &amp;ldquo;GB200 NVL72.&amp;rdquo; &lt;a href="https://www.nvidia.com/en-us/data-center/gb200-nvl72/" target="_blank" rel="noopener">nvidia.com&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Introl, &amp;ldquo;NVLink and Scale-Up Networking.&amp;rdquo; &lt;a href="https://introl.com/blog/nvlink-scale-up-networking-gpu-interconnect-infrastructure-2025" target="_blank" rel="noopener">introl.com&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Straggler dynamics and MoE communication:&lt;/p>
&lt;ul>
&lt;li>Ho, Q. et al. &amp;ldquo;Solving the Straggler Problem for Iterative Convergent Parallel ML.&amp;rdquo; CMU-PDL Technical Report. &lt;a href="https://www.pdl.cmu.edu/PDL-FTP/BigLearning/CMU-PDL-15-102.pdf" target="_blank" rel="noopener">pdl.cmu.edu&lt;/a>&lt;/li>
&lt;li>Zuo, P. et al. &amp;ldquo;Serving Large Language Models on Huawei CloudMatrix384.&amp;rdquo; &lt;a href="https://arxiv.org/pdf/2508.02520" target="_blank" rel="noopener">arXiv:2508.02520&lt;/a>&lt;/li>
&lt;li>DeepSeek-AI, &amp;ldquo;DeepEP: an efficient expert-parallel communication library.&amp;rdquo; &lt;a href="https://github.com/deepseek-ai/DeepEP/blob/main/README.md" target="_blank" rel="noopener">github.com/deepseek-ai/DeepEP&lt;/a>&lt;/li>
&lt;li>DeepSeek-AI, &amp;ldquo;EPLB: Expert Parallelism Load Balancer.&amp;rdquo; &lt;a href="https://github.com/deepseek-ai/EPLB/blob/main/README.md" target="_blank" rel="noopener">github.com/deepseek-ai/EPLB&lt;/a>&lt;/li>
&lt;li>ROCm, &amp;ldquo;Dropless MoE Training with Primus-Turbo.&amp;rdquo; &lt;a href="https://rocm.blogs.amd.com/software-tools-optimization/maxtext-dropless-moe/README.html" target="_blank" rel="noopener">rocm.blogs.amd.com&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>FFN interpretability and the residual stream:&lt;/p>
&lt;ul>
&lt;li>Geva, M., Schuster, R., Berant, J., Levy, O. &amp;ldquo;Transformer Feed-Forward Layers Are Key-Value Memories.&amp;rdquo; EMNLP 2021. &lt;a href="https://aclanthology.org/2021.emnlp-main.446/" target="_blank" rel="noopener">aclanthology.org&lt;/a>&lt;/li>
&lt;li>Geva, M., Caciularu, A., Wang, K., Goldberg, Y. &amp;ldquo;Transformer Feed-Forward Layers Build Predictions by Promoting Concepts in the Vocabulary Space.&amp;rdquo; EMNLP 2022. &lt;a href="https://aclanthology.org/2022.emnlp-main.3/" target="_blank" rel="noopener">aclanthology.org&lt;/a>&lt;/li>
&lt;li>&amp;ldquo;MLPs in Transformers.&amp;rdquo; Learn Mechanistic Interpretability. &lt;a href="https://learnmechinterp.com/topics/mlps-in-transformers/" target="_blank" rel="noopener">learnmechinterp.com&lt;/a>&lt;/li>
&lt;li>Elhage, N. et al. &amp;ldquo;A Mathematical Framework for Transformer Circuits.&amp;rdquo; Transformer Circuits Thread, 2021. &lt;a href="https://transformer-circuits.pub/2021/framework/index.html" target="_blank" rel="noopener">transformer-circuits.pub&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Pipeline parallelism in serving:&lt;/p>
&lt;ul>
&lt;li>Agrawal, A. et al. &amp;ldquo;Taming Throughput-Latency Tradeoff in LLM Inference with Sarathi-Serve.&amp;rdquo; OSDI 2024.&lt;/li>
&lt;li>&amp;ldquo;RServe&amp;rdquo; (pipeline-parallel serving latency comparison against tensor-parallel vLLM).&lt;/li>
&lt;/ul></description></item></channel></rss>