CPU-7: multi-position CPU execution — a 42% batching defect, its 1.46x fix, and a falsified cost model - #316
Open
chrishayuk wants to merge 2 commits into
Open
CPU-7: multi-position CPU execution — a 42% batching defect, its 1.46x fix, and a falsified cost model#316chrishayuk wants to merge 2 commits into
chrishayuk wants to merge 2 commits into
Conversation
Written so CPU work can be picked up cold. Covers what is frozen and where, what was learned independently of whether the candidate ships, the exact commands to resume CPU-6, the productionisation order if it passes, and the CPU-7 programme with its ranked opportunity list. The short version: there is a CPU integer projection path 32% faster than production (264 ms/token, 3.79 tok/s, 81% of attainable bandwidth) and it is NOT validated. CPU-6 is frozen and parked to test exactly that, unchanged, under a repaired gate.
…PU-7)
CPU-7A concurrency is not a lever CLOSED, negative
CPU-7B N=2 costs 1.02x one traversal PASSED
CPU-7B2 and it transfers across geometry PASSED
CPU-7C1 batching is 42% SLOWER than serial DEFECT FOUND
CPU-7C2 raising the FFN fixes it, 1.46x LANDED
stationarity then buys nothing FALSIFIED
Protocols and full run logs in `docs/cpu7-*.md`, every gate frozen before
the run that adjudicated it.
## The batching defect, and its fix
`execute_layer` ran the FFN through `h.par_iter_mut()`, so every
projection inside saw `caller_owns_the_machine` and collapsed to ONE
worker. Positions in parallel, each re-entering the executor — the
ownership rule this module already states, broken from the other end.
arm slabs/call K=2 time /(2A)
A serial 5.03 536.6 ms 1.000
B legacy batched 2.81 745.4 ms 1.389
C FFN multi-position 5.14 510.7 ms 0.952
`slabs/call` is the row partition the executor actually used, and it is
what attributes the loss rather than leaving it an argument. Two supplied
continuation positions now evaluate for LESS than two ordinary serial
steps.
## What is falsified
CPU-7C1 banked a cost model: `T_K ~= K(1-g)T_1 + m_K·g·T_1`, with `g`
measured independently and `m_K` imported from CPU-7B, predicting the
recurrent tranche to 0.4%. Arm E was built to ask whether that survived a
change of substrate. It does not.
logical weight traffic 53.55 -> 29.48 GB -45%, as designed
wall time 510.7 -> 517.5 ms unmoved
CPU-7B2 then ruled out geometry: `m_2` is 0.976-1.005 across every
production shape including the deep `5120x17408` FFN down projection,
with the original square shape reproducing 1.005 as its own control. So
the isolated kernel amortises on exactly these shapes at exactly this
worker count, and the whole layer does not.
NOT established, and deliberately not claimed: that the workload became
compute-bound. The ledger counts LOGICAL weight-load demand, not DRAM
transactions, and no instrument here separates the two.
## Also fixed: the crate did not build off aarch64
`SDOT_LANES` was `#[cfg(target_arch = "aarch64")]` while
`Q8xQ8::project_rows` compared against it un-gated, so `larql-vindex` has
not compiled on any non-aarch64 target since df36ca9. Found by the
cross-target check, not by review — `x86_64-unknown-linux-gnu` cannot be
used here (`ring`'s build script needs a cross C toolchain), but
`x86_64-apple-darwin` catches the same class.
## Invariants added
- every projection site belongs to a declared operator class, and the
class shares must sum to `p`. A new site makes `other` go nonzero
rather than silently contaminating a derived `g`.
- the ledger charges what was READ: one traversal only when the kernel
says it grouped, `n` otherwise.
- the stationary kernel REFUSES rather than falling back silently; the
caller must consult `supports` first.
- each position keeps its own activation quantisation and accumulator.
A joint scale would be a new representation wearing a schedule's name,
and a test plants a 400x neighbour to prove it is not.
`step_many` is a verification primitive: it consumes supplied token ids
and never samples position t+1 from position t's logits. Its gates
compare the token AFTER the batch, because correct logits for the batch
itself do not catch a wrong recurrent state.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #315 —
integer.rsandarithmetic.rsdo not exist onmain, andstationary.rsis a direct extension of CPU-5's K5 row, so this cannot be based offmainand compile.CPU-7 asked whether the CPU can serve more than one token per weight traversal. The kernel says yes. The layer says no, and finding out why produced a production defect, its fix, and a falsified cost model.
The production defect, and its fix
execute_layerran the FFN throughh.par_iter_mut(), so every projection inside sawcaller_owns_the_machineand collapsed to ONE worker. Positions in parallel, each re-entering the executor — this module's own ownership rule, broken from the other end.slabs/callis the row partition the executor actually used; it is what attributes the loss rather than leaving it an argument. Two supplied continuation positions now evaluate for less than two ordinary serial decode steps, with bit-exact parity. That is target-side substrate for speculative verification.What is falsified
CPU-7C1 banked
T_K ~= K(1-g)T_1 + m_K·g·T_1, withgmeasured independently andm_Kimported from CPU-7B, predicting the recurrent tranche to 0.4%. Arm E existed to ask whether that survived a change of substrate. It does not:CPU-7B2 then ruled out geometry —
m_2is 0.976-1.005 across every production shape, including the deep5120x17408FFN down projection, with the original square shape reproducing 1.005 as its own in-run control. So the isolated kernel amortises on exactly these shapes at exactly this worker count and the whole layer does not.Not claimed: that the workload became compute-bound. The ledger counts LOGICAL weight-load demand, not DRAM transactions, and nothing here separates the two. An earlier draft of the write-up did claim it; it is retracted in
docs/cpu7b2-geometry-transfer.md.Also fixed: the crate did not build off aarch64
SDOT_LANESwas#[cfg(target_arch = "aarch64")]whileQ8xQ8::project_rowscompared against it un-gated, solarql-vindexhas not compiled on any non-aarch64 target since df36ca9 (#315). Found by the cross-target check, not by review. Note for future cfg-gated work:x86_64-unknown-linux-gnuis unusable locally (ring's build script needs a cross C toolchain) and its failure looks like a toolchain problem;x86_64-apple-darwincatches the same class.Invariants added
p. A new site makesothergo nonzero rather than silently contaminating a derivedg. This caught a real instrumentation hole: inferring the FFN share fromp - gwould have given 0.699 against the true 0.593.notherwise.supportsfirst.step_manyA verification primitive: it consumes supplied token ids and never samples position
t+1from positiont's logits, which would make the traversal autoregressive again and destroy the parallelism it exists to expose. Its gates compare the token AFTER the batch, because correct logits for the batch itself do not catch a wrong recurrent state. Causal isolation is checked by comparingstep_many([a,b,c,d])againststep_many([a,b,c])thenstep(d).Gates
The crate's per-file coverage policy still fails on 15 files, all pre-existing and byte-identical before and after this branch; four of them arrive with #315.
Not done
CPU-7C3 (attention, a 6.6% tranche) is deliberately NOT built: it is not worth building until we know why a 59.3% FFN tranche produced no speedup. The next instrument is per-class projection wall time inside arms C/E/D, which is readable at K>1 only because C2 removed the position-parallel nesting — the fix under test is what makes its own diagnostic possible.
Protocols and full run logs, every gate frozen before the run that adjudicated it:
docs/cpu7-parallelism-protocol.md,docs/cpu7c-two-position-layer.md,docs/cpu7c2-multi-position-surfaces.md,docs/cpu7b2-geometry-transfer.md.