September 15, 2026. Contributors: @jurajselep
PCA-QDA achieves 105,130 / 110,000 correct (95.57% ± 0.17 pp), passing the 5% error target of at least 104,500 correct. Costs cover training and prediction on one 10,000-training / 10,000-test dataset.
| Accuracy | A100 energy above idle (mJ) | A100 time (ms) | Grid energy (mJ) | Grid time (ms) |
|---|---|---|---|---|
| 95.57% ± 0.17 pp | 174 | 3.3 | 0.19 | 2.0 × 10³ |
A100 energy is above idle. The original 3.8 mJ result did not reproduce. A100 costs are measured; grid costs are theoretical. Exact values and evidence links are in submission.json.
Each dataset uses Generator(PCG64(seed)).permutation(60000) over the original
MNIST training set: the first 10,000 indices train and the next 10,000 test.
Pixels are divided by 255 in FP32 and area-resized from 28×28 to 9×9.
run.resize_recorded fixes the accumulation order to reproduce all 22 archived
input hashes across the verified CPU environments. Checksums and complete
indices are in the draw manifest.
The fixed learner is retrained independently on each dataset:
x + 1e-6.PCG64(0).reference.py defines the ordered FP32 arithmetic and logarithm approximation. protocol.json records all hyperparameters. Test labels are used only for evaluation; no learned state passes between draws.
| Draw | Dataset seed | Correct / 10,000 |
|---|---|---|
| 0 | 20261501 | 9,544 |
| 1 | 20261502 | 9,572 |
| 2 | 20261503 | 9,572 |
| 3 | 20261504 | 9,544 |
| 4 | 20261505 | 9,538 |
| 5 | 20261506 | 9,555 |
| 6 | 20261507 | 9,540 |
| 7 | 20261508 | 9,540 |
| 8 | 20261509 | 9,577 |
| 9 | 20261510 | 9,571 |
| 10 | 20261511 | 9,577 |
The exact mean is 105130 / 110000; sample standard deviation is
0.16511153255244929 percentage points (ddof=1). All eleven draws are included.
Provenance limitation: the original protocol creation timestamp (13:10 UTC) follows the evaluation freeze (11:34:43 UTC). Historical pre-evaluation selection is therefore unconfirmed. Original evidence is preserved; these reruns verify published draws, not a new held-out evaluation.
The program uses the unchanged shared scorer for spatial-computer pitch 128 / ISA v4, revision 01a0bd5.
| Quantity | Value |
|---|---|
| Energy / word-node hops | 186,854,673,900 fJ / hops |
| Runtime | 2,047,716,289 cycles (1 ns/cycle) |
| Peak scratch, including tape staging | 5,125,276 bytes |
| Memory tiles / words per tile limit | 334 / 12,288 |
| Instruction-issuing processors / simultaneous instructions | 250 / 1 |
| Host scoring time | 2.8 s |
Arithmetic executes on P(125,0), with scratch assigned nearest-first to legal
cells. The serialized schedule completes each instruction and access before the
next. Input tapes contain 810,000 training pixel words, 10,000 integer labels,
and 810,000 test pixel words; output is 10,000 integer labels. Tapes use 250
bottom ports, with 6,520 input and 40 output words per port. Floats use FP32
words; labels use raw integer words. Test labels and learned parameters are
absent from the input tape and program literals.
A local access at distance d costs max(50, 2*d) fJ and one cycle; an access
over L mesh links adds 256*L fJ, taking 2*L+1 cycles for reads or L+2
for writes. Tape operations cost 128 fJ and two cycles. Requests route
horizontally then vertically; read responses retrace the route. All legal cell
distances are at least 32, so energy in fJ equals word-node hops.
The score records placement, access counts, and costs.
The score includes initialization, tape/staging traffic, feature transformation, basis fitting, class fitting, and prediction. Sampling, resizing, and division by 255 prepare the workload and are excluded. Host scoring time covers validation, placement, cost calculation, and hashing, excluding generation, I/O, and numerical execution. Costs describe the specified serialized schedule.
The W&B-tracked rerun on NVIDIA A100-SXM4-40GB measured 173.793 mJ above idle and 3.335 ms per training-and-prediction task using independent sampled-power integration. Its three active rounds used 6,000 / 12,000 / 6,000 replays and ten-second idle windows before and after each block. All 110,000 predictions match the frozen results (105,130 correct).
| Rerun method | Above idle (mJ) |
|---|---|
| Original protocol: counter, five-second paired idle | 165.564 |
| Independent harness: counter, ten-second paired idle | 174.878 |
| Independent harness: sampled-power integral, ten-second paired idle | 173.793 |
The original archived measurement reported 3.815 mJ above idle. Its arithmetic is internally consistent, but its approximately 41 W active power did not reproduce: the tracked rerun measured approximately 117 W. The reason remains unresolved. The new run used the same GPU model and PyTorch/CUDA versions on a different physical board, with driver 580.95.05 rather than 580.105.08.
See the audit for raw records, baseline sensitivity, container PID instrumentation, and runnable W&B/Modal reproduction instructions.
Each replay refits the basis and class models and predicts all 10,000 queries.
Inputs are device-resident; transfers, allocation, graph capture, and area-resize
preprocessing are excluded. The feature transform is included. GPU reduction
order, classical Gram-Schmidt, and torch.log differ from the ordered CPU
reference; all labels agree, while intermediate values need not be bitwise equal.
NVML counter deltas and independently integrated sampled power agree closely. Both share the GPU’s sensors; neither is an external wall-plug measurement. The corrected estimate subtracts mean paired idle power from the active-window integral. Signed estimates and idle-only controls are retained. Post-work power tails affect the idle baseline: trimming the first three seconds of idle gives 180.111 mJ in an exploratory sensitivity check. This is not a confidence interval or the primary table value. Historical raw measurements remain unchanged.
For the corrected energy result, use the W&B/Modal rerun instructions. The commands below reproduce the original learner, grid execution, and standalone GPU protocol.
Use Python 3.11. From the repository root:
python3.11 -m venv .venv
.venv/bin/pip install -r mnist/submissions/medium-pca-qda-20260915/requirements.txt
.venv/bin/python -m mnist.code.data --output mnist/data
. .venv/bin/activate
cd mnist/submissions/medium-pca-qda-20260915
python verify.py --output generated/cpu_verification.json
python spatial_program.py
python run.py gpu-payloads
To regenerate predictions before scoring, use a fresh evidence directory:
python run.py prepare --evidence-dir generated/reproduction
python run.py freeze --evidence-dir generated/reproduction
python run.py score --evidence-dir generated/reproduction
For the reduced Python/C cross-check and all eleven full grid executions, use GCC on x86-64. Separate FP32 operations and disabled flush-to-zero preserve the reference arithmetic:
mkdir -p generated/compiled
python spatial_program.py --emit-c generated/compiled/reduced.c --n-train 300 --n-test 120 --n-basis 100
python spatial_program.py --emit-c generated/compiled/full.c
for variant in reduced full; do
gcc -std=c11 -O0 -ffp-contract=off -fno-fast-math -frounding-math \
-fexcess-precision=standard -fno-strict-aliasing -march=x86-64 \
-msse2 -mfpmath=sse generated/compiled/"$variant".c -lm \
-o generated/compiled/"$variant"
done
python validate_reduced.py 300 120 100 \
--compiled-executable generated/compiled/reduced \
--full-executable generated/compiled/full --payload-dir generated/payloads \
--output generated/grid_verification.json
Copy this submission and generated/payloads/ to an idle A100. In a separate
Python 3.11 environment, from the submission directory:
python -m pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cu124
python -m pip install -r requirements-gpu.txt
python gpu_benchmark.py generated/payloads generated/gpu_benchmark.json 3000 5
This verifies all eleven draws, then measures draw 0. Add --verify-only to skip
timing. Generated data and executables are ignored by Git.