DRAM-Native &|~ Classification

Status Report — August 2026

DRAM-Native Bit-Logic Classification — 2026-08-09

August is the month the tooling caught up with the algorithm. One root cause — the float32 score accumulator drifts on large sums — explains a whole cluster of earlier anomalies (merge member counts, float-vs-int32 gaps, "the float tree is exhausted"). Fixing it (exact 64-bit accumulation, SCORE_TYPE default → double) made the merge deterministic, the archive self-describing, and the IFC — the delivery tool — finally able to run a heterogeneous ensemble end to end: 66.36% == 66.36% == 66.36% (merge == retrain == IFC import).

1. The float32 Accumulation Drift — Precision is the Feature

The ensemble scores reach ~1e9 — far beyond float32's exact range (224 ≈ 16.7M). Each addition rounds, the error grows with every member, and the beam's gain/argmax evaluations become noisy. The same corpus searched with different merge accumulators tells the story:

Merge SCORE_TYPEmemberseval
float322966.79%
int64 (-int32)4467.72%
double4467.72% (= int64 exactly)

The "32-bit is free / only top bits matter" assumption is refuted. The bit-exact algorithm is sensitive to score-accumulation precision — not to the container width. The DRAM chip accumulates popcounts exactly in integer arithmetic, so the int64/double behavior is chip-faithful; the float32 drift was an emulation artifact. SCORE_TYPE now defaults to double (-DSCORE_TYPE=float reproduces the legacy behavior).

Why this explains earlier puzzles

2. Archive Format v12/v13 — Export Follows the Internal Format

The .ens archive used to store float32 (v11) even when the computation ran in double — losing precision between computation and storage. Per decision, the export now follows the internal format:

versionscore typebytesnote
v8int32 (clamp)4legacy, read-only
v9-v11float4unchanged
v12double8double builds store losslessly
v13int648int64 mode, no int32 clamp

3. lib/ki-ens.h — the .ens Format is Now One Module

All version logic was scattered across four duplicated read paths. It is now centralized in lib/ki-ens.h:

4. --max = Beam-as-a-Whole — Deterministic with Exact Accumulation

--max (alone) now activates the old tolerant formalism (stop only after beam_width consecutive dry steps) instead of zeroing --min-gain; --union was removed. With exact accumulation the single-try --max beam is deterministic:

corpussingle-try--tries 10Δ
M1-INT3266.36% (51)66.36% (51)0
M3-INT3265.25% (88)65.25% (81)0
M1-FLT3266.88% (92)66.88% (92)0
M3-FLT3265.44% (55)65.44% (55)0

5. IFC v7 — the Delivery Tool Handles Heterogeneous Ensembles

model.otto v6 stored only W0/target/offset — it could not represent a heterogeneous ensemble (CIFAR import gave 12.81% = garbage; MNIST worked only because it is single-config). v7 adds a per-member section (channel, encoding, width, xform strings) after the header. A second bug was the missing enc-LUT initialization in the import (gave exactly 10.0% = random; enc_lut_get returned garbage). Both fixed:

Merge 51 members: 66.36%  ==  Retrain: 66.36%  ==  IFC import: 66.36%

--debug-member on the import prints per-member evals for verification ([ 3/51] ens=42.1% mem=32.4% G:sig8 xf=id).

6. --no-ens-cache — Real-Live Inference on New Data

The IFC's purpose is inference on new data, so the file cache (data/prepped/cex_*.pre) is a research/dev feature. --no-ens-cache skips the file cache (read AND write) — inputs are computed from raw data every run; the in-memory xform cache stays (it builds from the run's data). Validated:

runevaltime
--import member.exp (cache)66.36%5690ms
--import member.exp --no-ens-cache (real-live)66.36%6504ms

Only +814ms — the h0 scoring dominates, so the real-live performance IS the performance.

7. The 4-Way Technology Comparison (xform=id, 377 members)

Four corpora built identically (H=256, EP=10, seed 42, uniform W0, .meta type-bound), selection via --beam 10 --max:

corpuscumulative (best-en)beam-selected
M1-INT32 (maj1, int32)62.63%66.36% (51)
M3-INT32 (maj3, int32)61.94%65.25% (88)
M1-FLT32 (maj1, float+double)62.70%66.88% (92)
M3-FLT32 (maj3, float+double)62.02%65.44% (55)

8. Member Lists are Setup- & Arithmetic-Bound

There is no universal member list. A selection is only valid for the exact setup it was made under (maj, H, EP, VN/HN, seed, W0) and the arithmetic it was scored with:

selection → retrainevalΔ
float-selected → float67.85%
float-selected → int3267.12%−0.73pp
int32-selected → int3269.61%
int32-selected → float68.15%−1.46pp

Each arithmetic performs best on its own selection; the coupling is asymmetric (int32-selected members hurt float more than the reverse). Always retrain with the corpus' exact flags — the .meta type binding now enforces the arithmetic side.

9. Fashion-MNIST: The 91% Trap

→ Fashion-MNIST paper — a second, independent dataset that sharpened the August findings. The DRAM-native bit-logic stack (Otto Score + maj1, frozen random W0) reaches a 91.6% ceiling on Fashion-MNIST — and cannot break out of the 88.7–91.6% basin, no matter the search strategy:

Strategyeval rangeFinding
--beam 10 --max, H32..512, m1t 98..10890.8–91.6%H is flat (+0.14pp from H196→H512); the ceiling is architectural
--tries N --tries-no-lock91.3–91.6%full-pool search; MORE members ≠ better (pool-monotonicity disproven)
--tries 3 + --beam-bestN 1/2/391.4–91.5%breaking the 1st-best fixation moves the attractor by ~0.1pp
--expansion-sort clarity86.8–89.2%member clarity alone is WORSE — diversity beats strength
Bit-Voting (no W0, no maj1)88.7–89.0%lower technology bound; the W0+maj1 advantage is maj1-driven

The 3.4pp gap to CNN SOTA (94–96%) is architectural — frozen random W0, no convolution, no trainable features. Every search lever moves the needle by tenths of a percent only. What speaks for the approach: speed — a 221-member sweep runs in ~1 minute (PRF trainer), orders of magnitude faster than CNN training. For a DRAM-native chip the question is not "can we reach 95%" but "how little hardware do we need for 91.6%".

Two real bugs surfaced along the way (both fixed): the IFC import started with CLI-default maj1-thresh (107) while the model was trained with 104 → every h0 bit differed → 36.6% instead of 91.1%. The model.otto format is now v8 (self-describing): it carries maj_mode, maj1-thresh, splitVN and splitHN, so --import needs no CLI flags. The --dry-run import also SEGV'd on the unloaded pixel buffer — now a clean "setup only" exit. See the Fashion-MNIST paper for the full leaderboard and the end-to-end 91.10% = 91.10% = 91.10% (merge = retrain = IFC) verification.

Summary

topicresult
float32 score accumulationdrifts at ~1e9 → refuted "32-bit is free"; SCORE_TYPE default → double
.ens archivev12 (double) / v13 (int64); export follows the internal format
format codecentralized in lib/ki-ens.h; EnsReader + ens_write + ens_verify (−420 lines)
beam scan--max = beam-as-a-whole, deterministic; --tries adds nothing; --union removed
IFC (delivery)model.otto v7 (per-member metadata) + enc-LUT fix → heterogeneous 66.36% end-to-end
IFC self-describingv8 carries maj_mode/maj1-thresh/splitVN/splitHN → import needs no CLI flags (Fashion 36.6% bug fixed)
real-live IFC--no-ens-cache: compute from raw data, +814ms
technology comparisonmaj1 > maj3; flt32-double ≈ int32; winner M1-FLT32 66.88%
Fashion-MNIST91.6% ceiling / 88.7–91.6% basin — architectural, not search-limited; 91.10% end-to-end (merge = retrain = IFC), see Fashion paper

Documentation Source
Markdown source: /docs/status-2026-08.html | All docs: /docs/ (synced from GitHub/docs)
Source code: otto-score-ifc/ | mnist/ (trainer + merge-ensemble + ifc)