Complete Mathematics of "Optimization 8: Fully Register-Tiled 4×4 Kernel"¶
Optimization 7 already fused the sixteen updates into one \(p\)-loop, but it still read and wrote the \(C\) tile through memory on the way in/out and relied on the compiler to promote them to registers. Optimization 8 makes the register residency explicit and complete: it declares all sixteen \(c_{rc}\) as register accumulators, holds the eight \(a_r, b_c\) operands in registers, and performs a single read of the old \(C\) and a single write of the new \(C\) per element per tile.
1. The Mathematical Operation¶
Identical block product, still the rank-1 accumulation:
2. Explicit Register State¶
2.1 Sixteen accumulator registers¶
2.2 The two-level update¶
Initialization (read old \(C\) once):
Inner loop (pure register arithmetic):
Finalization (write new \(C\) once):
This realizes, at the \(4×4\) tile level, exactly the "defer the write" idea first introduced for a \(1×4\) tile in Optimization 4.
3. Memory Traffic Accounting (per tile)¶
Let \(N_C\) be memory transfers of the \(C\) tile over the whole kernel.
| Step | Loads | Stores |
|---|---|---|
| Old-C init | \(16\) | \(0\) |
| Inner \(p\)-loop | \(0\) | \(0\) |
| New-C finalize | \(0\) | \(16\) |
| Total | 16 | 16 |
Compare Optimization 7, where without explicit register promotion the compiler might spill; Optimization 8 guarantees only \(2\cdot16\) transfers per tile regardless of \(k\). For \(k=2000\), this is essentially free relative to the \(8k\) A/B loads.
4. Register Pressure & Feasibility¶
The hot state is \(16\) accumulators + \(8\) operand registers (\(a_0..a_3\), \(b_0..b_3\)) + address/loop pointers. On a 64-bit ISA with 16 vector registers (SSE/AVX on x86-64, or NEON on ARM) plus GPRs, this fits comfortably:
- 16 vector registers for \(\mathbf{\Gamma}\),
- 4 for the \(\mathbf{a}_p\) column,
- 4 for the \(\mathbf{b}_p\) row,
- remainder for pointers and counters.
This is why the \(4×4\) shape (16 accumulators) is a sweet spot: it is the largest tile that keeps all accumulators resident given 16 architectural vector registers, while leaving room for operands.
5. Floating-Point Considerations¶
Each \(\gamma_{rc}\) update is an FMA: one multiply and one add in a single instruction with one rounding, not two. Over the kernel:
Across all \(\frac{mn}{16}\) tiles:
The FMA latency chain per accumulator is one FMA per \(p\)-step; with 16 independent chains, the machine can sustain near its peak FMA throughput of (FP pipes) FLOPs per cycle.
6. Summary¶
| Quantity | Optim 7 | Optim 8 |
|---|---|---|
| \(\mathbf{\Gamma}\) register-resident | implicit | explicit / guaranteed |
| \(C\) traffic per tile | compiler-dependent | exactly \(2\cdot16\) |
| FMA chains (ILP) | 16 | 16 |
| FLOPs | \(2mnk\) | \(2mnk\) |
| Kernel shape | \(4\times4\) | \(4\times4\) |
Optimization 8 is the mathematical culmination of the register-tiling idea: the entire \(4×4\) output tile is carried as sixteen independent FMA chains in registers, touched only once at load and once at store, so the inner loop runs at the machine's FMA-compute ceiling rather than its memory bandwidth.