summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuren Hao <yurenh2@illinois.edu>2026-07-16 04:33:29 -0500
committerYuren Hao <yurenh2@illinois.edu>2026-07-16 04:33:29 -0500
commit35e7582287ab5a82bf57561895b5a095dc9b6e24 (patch)
tree650d64e699c1ba996e784284e9ac8001def3ba26
parent5f8dd1c4d7106665cf9722e7a394893bb87c9b07 (diff)
RESULT 29: qcomp8 tax-free (+0.0018) = T64 8-bit compute green light; --centmirror ships (cos 1.000000000, 1.72x -> 1.39x)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FAPDWQ49M5Ye3NpTndTpn
-rw-r--r--docs/campaign/CASCADE_ABLATION_PLAN.md19
-rw-r--r--ep_run/casc_eq_train.py30
2 files changed, 46 insertions, 3 deletions
diff --git a/docs/campaign/CASCADE_ABLATION_PLAN.md b/docs/campaign/CASCADE_ABLATION_PLAN.md
index 12751d9..1502ed2 100644
--- a/docs/campaign/CASCADE_ABLATION_PLAN.md
+++ b/docs/campaign/CASCADE_ABLATION_PLAN.md
@@ -568,6 +568,25 @@ direction), not training-under-fault; wave-2 = co-training with faults injected
+### RESULT 29 (2026-07-16): qcomp VERDICT — 8-bit COMPUTE quantization is FREE (T64 green light); centmirror ships (1.39x).
+qcomp arms (compute on DAC-grid weights, fp32 master = word-streaming / shadow accumulation),
+same protocol, vs ctl 1.2678:
+| bits | qcomp (T64 scenario) | qup (naked resident) |
+|---|---|---|
+| 8 | **1.2696 (+0.0018 = ZERO)** | 1.3096 (+0.042) |
+| 6 | 1.3026 (+0.035) | 1.3598 (+0.092) |
+| 4 | 1.4077 (+0.140) | — |
+- 8-bit DACs + digital master = tax-free at 42M: the Y3/pc AD7528 line and the T64 word-streaming
+ architecture pass gate #1b. 6-bit compute has a real but moderate tax; 4-bit heavy.
+- BP mirror suite RUNNING (bp_qctl 49.5k, then qup10/8/6 + qcomp8/6/4): the Delta-vs-Delta verdict
+ (EP-specific or generic) lands tonight; RESULT 28's naked-cell reading stays provisional till then.
+- ESTIMATOR COST ENGINEERING sealed: --centmirror (the -beta pass initialized as the MIRROR of the
+ +beta solution at the shared free anchor + 1 polish sweep; second free pass and K-1 sweeps
+ deleted). Gradtest cos 1.000000000 vs sequential centered (relerr 2.2e-5). Quiet bench B12/amp:
+ plain 4.389 it/s | sequential centered 2.547 (1.72x) | centfast 2.684 (1.64x) | **centmirror
+ 3.169 (1.39x)**. With est_late@80%: amortized ~1.08x — centered is now essentially free at scale
+ (8B ledger: 3.2x -> ~3.45x vs BP).
+
### RESULT 28 (2026-07-16): STAGE-0 HW GATE #1 — naked analog-resident updates need >10 bits; T64's word-streaming scenario measured next.
Protocol: arms7 (resume s45000 -> 55000, ctl 1.2678). --qup_bits = weights snapped to an ABSOLUTE
per-tensor grid after every update, stochastic rounding (= analog-resident cells, NO shadow).
diff --git a/ep_run/casc_eq_train.py b/ep_run/casc_eq_train.py
index 17a0c70..8e246d1 100644
--- a/ep_run/casc_eq_train.py
+++ b/ep_run/casc_eq_train.py
@@ -71,6 +71,9 @@ ap.add_argument('--qcomp_bits', type=int, default=0) # STAGE-0 T64 scenario
ap.add_argument('--qup_bits', type=int, default=0) # STAGE-0: quantize weights to an absolute
# per-tensor grid after each update (stochastic
# rounding); emulates finite analog cell levels
+ap.add_argument('--centmirror', action='store_true') # centered's -beta pass initialized as the MIRROR
+ # of the +beta solution (d- = -d+ at shared anchor)
+ # + one polish sweep; skips its free pass entirely
ap.add_argument('--centfast', action='store_true') # centered via ONE doubled batch [x;x], +beta/-beta halves
# (shared kernels; math identical to sequential centered)
args = ap.parse_args()
@@ -369,6 +372,7 @@ def relax(z0, zs, ins, outs, y, beta, K, x, bmask=None):
GOV['rho'] = rlist[-1] / rlist[-2] # per-sweep contraction ratio = live loop-gain meter
GOV['res'] = rlist[-1]
GOV['kuse'] = K
+ GOV['_last_d'] = d
return zs, outs
prev_res, k = None, 0
@@ -386,6 +390,7 @@ def relax(z0, zs, ins, outs, y, beta, K, x, bmask=None):
forces(True) # final graphed round at the settled state (theta-read)
rebuild(True)
GOV['kuse'] = k + 1
+ GOV['_last_d'] = d
return zs, outs
def dFdtheta(zs, x, y, beta):
@@ -496,9 +501,28 @@ def ep_step(x, y):
gsC = torch.autograd.grad(obj_loss(readout(zp[-1].detach()).reshape(-1, vocab), y.reshape(-1)),
all_params, allow_unused=True)
b2 = -beta_t if EST == 'centered' else 2.0 * beta_t
- z0b, zsb, insb, outsb = free_states_graphed(x)
- zsb_free = [z.clone() for z in zsb]
- zpb, lob = relax(z0b, zsb, insb, outsb, y, b2, GOV['K'], x)
+ if EST == 'centered' and args.centmirror:
+ # MIRROR WARM-START: d-(free anchor) = -d+ exactly (linear in beta); init the -beta
+ # states as the mirror of the settled +beta solution, then ONE polish sweep corrects
+ # the O(beta^2) even part. Skips the second free pass and K-1 sweeps.
+ dm = [(-di).detach() for di in GOV['_last_d']]
+ zsb_free = zs_free
+ prev = z0
+ zsb, insb, outsb = [], [], []
+ with torch.autocast('cuda', dtype=torch.bfloat16, enabled=args.amp):
+ for l in range(args.L):
+ i = prev.detach().requires_grad_(True)
+ o = blocks[l](i, mask)
+ zsb.append(o.detach().float() + dm[l])
+ insb.append(i); outsb.append(o)
+ prev = zsb[l]
+ _k1 = GOV.get('kuse')
+ zpb, lob = relax(z0, zsb, insb, outsb, y, b2, 1, x)
+ GOV['kuse'] = _k1 # telemetry: report the +beta pass's K, not the mirror polish
+ else:
+ z0b, zsb, insb, outsb = free_states_graphed(x)
+ zsb_free = [z.clone() for z in zsb]
+ zpb, lob = relax(z0b, zsb, insb, outsb, y, b2, GOV['K'], x)
with torch.no_grad():
drift2 = sum(float((a - b).norm()) for a, b in zip(zpb, zsb_free)) / max(
sum(float(b.norm()) for b in zsb_free), 1e-9)