Files
esh-pfi-infrastructure/persistent-memory.d/2026-09-01-pfi-gx10-onboarding.md
T
vh 7d0d991fcd memory: pin the GX10 baseline's final figures
The probe finished. Median is 79.36 s/it across ten timed steps with a
min/max of 79.30 to 79.45, and peak memory is 75.1 of 121.6 GiB by
PyTorch's own max_memory_allocated -- 46 GiB spare rather than the 35 I
estimated from a live free reading, which was counting fragmentation and
the resident model rather than the allocation high-water mark.

Resolved attention backend recorded as flex_attention, read off the loaded
model rather than trusted from the request, which is the check I got wrong
the first time.
2026-09-02 01:23:50 -07:00

452 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `[2026-09-01]` pfi-gx10 (ASUS Ascent GX10) onboarded headless — and it is the intended new home for run 3c
ASUS Ascent GX10 arrived and was registered, converted to headless, and given a rack-move
playbook. **It was NOT racked** — the operator ran out of day. It is still on his desk, on
Wi-Fi, on a temporary DHCP lease.
| | |
|---|---|
| GPU | **NVIDIA GB10**, driver 580.173.02, **compute capability 12.1 (`sm_121`)** |
| CPU | 20 cores, **aarch64** |
| Memory | **121 GB UNIFIED** — CPU and GPU share it; not 121 GB *plus* VRAM |
| Storage | 916 GB NVMe, 6% used |
| OS | Ubuntu 24.04.4, kernel 6.17.0-1031-nvidia |
| Access | `infra-ops` NOPASSWD sudo (operator-bootstrapped). `lkraven` has key auth but needs a password to escalate — **automation must connect as `infra-ops`**. |
## Purpose (operator, 2026-09-01)
Local inference experiments **and** the failed training — run 3c. That is the whole point:
run 3c died on ana-ml2 when a **kilowatt-class** training box tripped a breaker
(2× 300 W GPUs + dual EPYC 9254). The GX10 is a ~240 W appliance, roughly a fifth of the
draw, on a different site's circuits.
**The memory arithmetic favours it strongly.** Run 3c is a LoRA (r=64, batch 2 × accum 8,
gradient checkpointing) over `gemma4-26b-a4b-it-bf16` — **49 GB of base weights**, working
set roughly 55–65 GB. The `gemma4-charrp` compose warns in capitals that "48.10 GiB of BF16
weights CANNOT be served here" on ana-ml2's shared GPU0. 121 GB unified turns that
constraint into a non-issue.
## What has NOT been established — do not assume any of it
1. **The box is bare.** No torch, no nvcc, no CUDA stack. Docker 29.2.1 and 822 GB free.
2. **aarch64 dependency risk.** torch 2.9.1+cu130 ARM64 wheels exist; transformers/TRL/PEFT
are pure Python. Compiled deps — flash-attn, bitsandbytes, liger, xformers — are open
questions per-arch.
3. **Triton has NO sm_121 support** (established independently by comfy-dev the same day).
Anything reaching for `torch.compile` or Triton-backed kernels is closed on this silicon.
4. **Throughput is unmeasured.** Run 3c ran 16.45 s/it on a 300 W RTX PRO 6000. GB10 will be
slower; how much decides whether 604 steps is an overnight run or two days.
**Measure this before porting anything** — the recommended first move is a probe: install
ARM64 torch, load the base, run ten steps, report s/it.
5. **Model transfer:** 49 GB from ana-ml2 over the Anaheim↔NH3 link at a **measured
32.4 MB/s** — about 25 minutes. Note that is a third of the irv-ml1↔NH3 link's 99 MB/s.
## The headless conversion, and the lesson inside it
`playbooks/gx10-headless.yaml` (`1b596c8`): multi-user.target, gnome-remote-desktop stopped,
sleep/suspend/hibernate **masked**, logind ignores lid and idle, sshd keepalives, hostname
corrected `gx10-a745` → `pfi-gx10`.
⚠ **`gdm` is a STATIC unit on Ubuntu** — pulled in by `display-manager.service`, never
"enabled". The first version guarded on `is-enabled | grep enabled`, which always skips, and
**the verify tested the same wrong property and passed**. Six green verifies having not
stopped the display manager. Both now test `is-active`. This is an instance of
[[2026-09-01-wrong-object-measurement]].
The playbook refuses to stop GDM while a seat session is held (`--var force_dm_stop=true` to
override) — automation should not yank a display out from under someone at the machine.
⚠ **elway's `--sudo` applies only to ad-hoc `--shell`/`--upload`.** Playbook steps run as the
connecting user and must carry their own `sudo`.
## The rack move, written but not run
`playbooks/gx10-rack-network.yaml` (`a0c5fc6`) — target settled: **`nh3-servers` VLAN 50,
static `10.100.50.60`**, clear of `.40`/`.42`/`.50`/`.90` and below the `.150` DHCP pool.
Requires nothing from the operator beyond racking it. The wired NIC has its own MAC
(`30:c5:99:3d:a7:45`, distinct from Wi-Fi `50:bb:b5:a2:00:a8`), so the post-move address AND
switch port are discoverable from the UDM rather than relayed.
**Design property worth preserving:** the playbook never leaves itself one path back. Wi-Fi
stays up while the wired interface is configured beside it; Wi-Fi teardown is explicitly a
separate later change. `netplan try`'s auto-rollback needs a TTY that elway cannot provide,
so a live Wi-Fi link is what substitutes for it. Two preconditions are asserted as steps
rather than assumed: carrier must be 1, and the MAC must match (interface names renumber
across kernels; MACs do not).
⚠ **The GX10 is NOT the Ada box.** Two separate machines — see
[[2026-09-01-ada-migration-branch-a]].
## `[2026-09-01 23:09]` Liveness check — alive, idle, and STILL BARE (nothing has changed)
Probed at **2026-09-01T23:09:51-07:00**, read-only:
host pfi-gx10 Ubuntu 24.04.4 LTS kernel 6.17.0-1031-nvidia aarch64
uptime 11h48m (booted 2026-09-01 11:21) load 0.00 0.01 0.00 — idle
GPU NVIDIA GB10 driver 580.173.02
memory 121 GB unified, 118 GB free
disk /dev/nvme0n1p2 916 GB, 48 G used, 822 G free (6%)
net wlP9s9 10.100.10.226/24 (DHCP) | enP7s7 DOWN, NO-CARRIER (no cable)
sessions 2x lkraven desktop (seat0 + :1) — sitting at a GUI login screen
**Compute stack unchanged and still absent:** no `torch`, no `nvcc`, no `uv`. Docker daemon
present but `infra-ops` is **not in the docker group**. Nothing has been installed since
onboarding.
⚠ **`nvidia-smi` reports FB Memory / BAR1 as `N/A`. That is CORRECT, not a fault** — GB10 is a
Grace Blackwell superchip with **unified** LPDDR5X shared between CPU and GPU, so there is no
discrete VRAM figure to report. Do not chase it as a driver problem.
## ⚠ RACKING IS **NOT** A PREREQUISITE — the Wi-Fi is not the bottleneck
Assumed the temp Wi-Fi would gate getting a 49 GB base onto the box. **Measured, and it does
not:**
link SSID PFI, 6 GHz, 160 MHz, EHT (Wi-Fi 7), -48 dBm
rx/tx bitrate 2401.9 Mbit/s both directions
measured 300 MB nh3-dev -> gx10 in 4.5 s = 67 MB/s over SSH
(SSH cipher is the limiter, not the radio — link is ~300 MB/s)
implies 49 GB bf16 base transfers in ~12 min
So the throughput probe (ARM64 torch, load base, ten steps, report s/it) can proceed **from the
desk, today**, without racking first. Racking remains one command
(`playbooks/gx10-rack-network.yaml`, VLAN 50, static `10.100.50.60`) and is worth doing for
permanence, but it does not gate the decision the probe exists to answer.
## `[2026-09-01 23:2x]` OUTFITTED (userspace) — CUDA WORKS on sm_121, full training stack imports
### ✅ RULING: BARE METAL, not Proxmox/VM. Settled, do not re-litigate.
1. **Proxmox VE has no aarch64 build.** It ships x86_64 only; the ARM ports are unofficial
community work. Running an unsupported hypervisor under a compute asset is a bad trade.
2. **The GPU cannot be cleanly passed through.** GB10 is a superchip: the GPU sits on NVIDIA's
own on-package root complex (bridges `22ce`/`22d0`/`22d1`, GPU at `000f:01:00.0`) and is
**cache-coherent with the CPU over NVLink-C2C, sharing the same physical LPDDR5X.** Passing
it to a guest means partitioning unified memory — which destroys the entire value
proposition, since **121.6 GiB GPU-addressable** is the reason this box exists.
3. **Vendor's supported path is bare metal** — it already runs NVIDIA's own kernel flavour
(`6.17.0-1031-nvidia`).
4. **Fleet convention agrees:** ana-ml2 and irv-ml1 are both bare-metal GPU hosts. Hypervisors
are separate machines in this fleet, never under the accelerators.
5. **Single tenant.** VM isolation buys multi-tenancy nobody needs; the rollback benefit is
better served by **containers + `uv` venvs**, which is what the rest of the fleet does.
### Installed and verified (all userspace, NO sudo needed)
uv 0.12.9 (aarch64), ~/.local/bin, wired into .bashrc + .profile
venv ~/ml/.venv (python 3.12)
torch 2.14.0+cu130 cuda runtime 13.0, cudnn 92400, triton 3.8.0
stack numpy 2.5.2, transformers 5.16.1, accelerate 1.14.0, peft 0.20.0,
trl 1.12.0, datasets 5.0.1, safetensors 0.8.0, hf_hub 1.29.0,
bitsandbytes 0.50.2 -- ALL import clean on aarch64
**The "per-arch unknowns" warning did not materialise for the training stack.** Everything
imported first try.
### ✅ MEASURED GPU COMPUTE — it works, and the memory is the point
device NVIDIA GB10, capability sm_121, driver 580.173.02
GPU memory 121.6 GiB total / 110.8 GiB free <- unified, fully CUDA-addressable
bf16 8192^3 ~93 TFLOP/s fp16 ~93 TFLOP/s
fp32+tf32 38.2 TFLOP/s fp32 (no tf32) 19.5 TFLOP/s
bf16/fp32 4.9x -> tensor cores ARE engaged
~93 TFLOP/s dense bf16 is roughly **A6000-class throughput with 2.5x the memory**. Capacity,
not speed, is what this box buys. A 49 GB bf16 base fits with ~70 GB to spare.
### ⚠⚠ I NEARLY REPORTED A PHANTOM PROBLEM — NO WARMUP MEANS YOU MEASURE THE JIT
First benchmark (10 iterations, **no warmup**) read **27.0 TFLOP/s bf16** — slower than a 3090
— and I was one step from reporting "tensor cores are not engaging on sm_121." Adding 5 warmup
iterations moved it to **93 TFLOP/s. The first measurement was timing the PTX JIT compile.**
⚠ **This is exactly `docs/pfi/training-throughput-playbook.md` §4: a run that completes, reports
plausible numbers, and is wrong.** It would have sent us chasing a cuBLAS fallback that does not
exist. **Always warm up before timing anything on this box** — see the JIT note below for why it
bites harder here than elsewhere.
### ⚠ sm_121 IS NOT IN TORCH'S COMPILED ARCH LIST — everything JITs from sm_120 PTX
torch.cuda.get_arch_list() -> ['sm_80','sm_90','sm_100','sm_110','sm_120']
device capability -> sm_121
There is **no sm_121 cubin in the wheel**; it runs by PTX forward-compat JIT from sm_120.
Consequences:
- **First use of every kernel pays a JIT compile** (cached afterward in `~/.nv/ComputeCache`).
This is what corrupted the benchmark above.
- ⚠ **Any library shipping cubin-only binaries with no PTX will simply fail here.** That is the
real shape of the "per-arch unknown" risk — not source builds, but prebuilt kernels.
### ✅ PRIVILEGED HALF DONE — and I WAS NEVER BLOCKED
⚠⚠ **The block was my own bad test.** `infra-ops` has had **NOPASSWD sudo since account
creation** (`/etc/sudoers.d/infra-ops`, installed 11:31 with the account). I probed with
`sudo -n -v`, which returns non-zero on **sudo >= 1.9.15** because `-v` refreshes an auth
timestamp that a NOPASSWD-only rule never creates — and asked the operator for a password that
was never needed.
pfi-gx10 sudo 1.9.15p5 sudo -n -v rc=1 sudo -n true rc=0
nh3-docker sudo 1.9.13p3 sudo -n -v rc=0 sudo -n true rc=0
ana-docker sudo 1.9.13p3 sudo -n -v rc=0 sudo -n true rc=0
irv-ml1 sudo 1.9.13p3 sudo -n -v rc=0 sudo -n true rc=0
**Always `sudo -n true`.** Fixed in `scripts/elway` (which carried the same probe and would
have started falsely prompting fleet-wide as hosts pass sudo 1.9.13) and in auto-memory
`reference_infra_ops_sudo_identity`, which *recommended the broken test*.
[[feedback_assert_effective_value_not_substring]]
⚠ **Same shape twice in one session.** I also reported "nvcc: ABSENT" from `command -v nvcc`
when the CUDA toolkit was installed all along at `/usr/local/cuda/bin/nvcc`, just not on PATH.
Both times I checked a proxy and reported it as the thing itself.
**Credential:** the temp password was `infra-ops`'s, not `lkraven`'s. Rotated to 32 random
chars and **vaulted at `pfi-gx10/infra-ops-password`** (round-trip verified). Kept rather than
locked — deviating from the canonical bootstrap's no-password posture **deliberately, because
this box has no iDRAC/BMC**, so a console break-glass credential is the only way back if key
auth breaks. ⚠ `lkraven` (uid 1000, GUI desktop user, `sudo` group) has a password nobody
knows; out of scope, but it is a gap.
### ⚠ DOCKER'S BUILDKIT DB WAS ALREADY CORRUPT — the restart surfaced it, did not cause it
`nvidia-ctk runtime configure` + `systemctl restart docker` failed with
`error initializing buildkit: error creating buildkit instance: invalid database`. **Not the
nvidia config** — `daemon.json` was valid and `nvidia-container-runtime` was present. dockerd
had been running on a process whose on-disk buildkit state was already bad; it simply could not
come back. Remediated by removing `/var/lib/docker/buildkit` (108 KB of **cache**, and the box
had **0 images, 0 containers**), then `daemon-reload` + `reset-failed` + start.
⚠ **A long-running daemon can be unable to restart for hours before anyone finds out.** Nothing
reported unhealthy until something asked it to restart.
### ✅ FINAL STATE — playbook green, 5/5 verifies
playbooks/gx10-outfit-privileged.yaml -> steps 1 ok / 1 changed / 0 failed / 6 skipped
verify 5 ok / 0 failed
NOPASSWD sudo OK
nvcc /usr/local/cuda/bin/nvcc (NOT on default PATH)
docker socket as infra-ops OK (docker group)
CUDA container sees the GB10 OK (nvidia/cuda:13.0.0-base -> nvidia-smi -L reports GB10)
userspace torch still sees GPU OK
docker Runtimes nvidia runc io.containerd.runc.v2
**The box is fully outfitted for inference + training, bare metal, containers available.**
### Historical note — what the block looked like before it was disproved
⚠ **`infra-ops` does NOT have NOPASSWD sudo on pfi-gx10** (`sudo -n -v` -> "a password is
required"), unlike the rest of the fleet — see [[reference_infra_ops_sudo_identity]], which
should be corrected: gx10 is an exception. **No gx10 credential is in the vault** (`secret list
--prefix pfi-gx10` -> 0 items), and `scripts/elway` prompts via `getpass`, which a
non-interactive session cannot answer.
Still outstanding, all needing root:
- CUDA toolkit / nvcc (absent -- needed to COMPILE kernels, not to run torch)
- NVIDIA Container Toolkit + add infra-ops to the docker group
(docker daemon runs; infra-ops gets "permission denied" on the socket)
- NOPASSWD sudo for infra-ops, so this box stops being a fleet exception
- racking (playbooks/gx10-rack-network.yaml) -- optional, NOT a prerequisite
**Nothing above blocks the run-3c throughput probe**, which needs only the driver and torch.
## `[2026-09-01 23:5x]` Run-3c throughput probe — IN FLIGHT, and the ana-ml2 baseline is now on record
### The baseline nobody had written down: ana-ml2's real s/it for run 3c
Extracted from `/tank/erp-tune/run-03c.log` (the actual run, before the breaker killed it):
step 10 10.81 s/it step 20 12.88 s/it step 24 15.76 s/it
=> 604 steps on ana-ml2 ~= 2.2-2.7 h
**This is the number the GX10 has to be compared against**, and it was sitting in a log
nobody had reduced. Anything under ~45 s/it on the GX10 makes 604 steps an overnight run.
### Exact run-3c geometry (from run-03c.json + a real adapter_config.json)
base /tank/aimodels/gemma4-26b-a4b-it-bf16 49 GB
gemma4, 30 layers, hidden 2816, 16 heads / 8 KV, MoE (A4B),
vocab 262144, sliding_window 1024, multimodal (vision+audio configs)
LoRA r 64, alpha 128, dropout 0.0, bias none, 205 target modules
(q/k/v/o + gate/up/down across all 30 language-model layers)
shape max_seq_len 16384, per_device_batch 2, grad_accum 8 (effective 16)
other gradient_checkpointing true, bf16, cosine, warmup 0.1, wd 0.01
length 604 optimizer steps, 1 epoch, save_steps 50
### ⚠ THE BACKEND-DELTA TRAP — CHECKED, and it is NOT present
CLAUDE.md warns that two frontier-panel conclusions were voided because a benchmark and a
trainer had silently different attention backends. Enumerated both sides **before** running:
ana-ml2 flash_attn NOT installed in /tank/erp-tune/venv -> falls back to sdpa
pfi-gx10 flash_attn not available for aarch64/sm_121 -> falls back to sdpa
Same backend both sides. ⚠ **Library versions DO differ and it is recorded rather than
assumed harmless:**
ana-ml2 torch 2.13.0 transformers 5.15.1 peft 0.20.0 accelerate 1.14.0
pfi-gx10 torch 2.14.0+cu130 transformers 5.16.1 peft 0.20.0 accelerate 1.14.0
The probe reads the **resolved** `_attn_implementation` back off the loaded model rather than
trusting the request, so the comparison is checkable rather than assumed.
### Probe design (§4-disciplined)
`~/ml/probe_3c.py` on the GX10. Real geometry, synthetic batches — it measures step cost, and
padding on the real run is 0.0% so the corpus does not change per-step cost materially.
- **12 steps, first 2 discarded as warmup.** Non-negotiable here: an unwarmed benchmark on
this box already read 27 TFLOP/s when the true figure was 93, because it was timing the PTX
JIT. sm_121 is not in torch's arch list.
- Reports the **step-time distribution** (median, min/max, every step), not a mean beside a
settings dump.
- Emits **every provenance key always, null when unused** — present-and-null, not absent.
### Transfer
49 GB relayed **ana-ml2 -> nh3-dev -> pfi-gx10**, ~33 MB/s, ~25 min. Relayed rather than
direct because ana-ml2's key is not authorised for `infra-ops@pfi-gx10` — and relaying costs
nothing extra, since the Wi-Fi leg is the bottleneck either way. **Deliberately did not add an
access grant just to save a hop.**
## `[2026-09-02]` GX10 BASELINE + TOOLING VERIFIED — ~79.35 s/it on the run-3c shape
⚠ **PURPOSE, stated by the operator so it is not misread later: this was a BASELINE for the box
and a check that the tooling loads.** It was NOT a decision about where run 3c runs, and no port
was undertaken. The placement reasoning below is a *byproduct* — real and worth keeping, but the
deliverable was the number and the working stack.
**Deliverable 1 — the tooling loads and runs.** aarch64 + sm_121 runs the full training stack:
torch 2.14.0+cu130, transformers, accelerate, peft, trl, datasets, safetensors, bitsandbytes,
**plus the harness's own `flex_attention` backend and chunked-loss path**. Nothing exotic was
needed beyond `python3-dev`. This box can train.
**Deliverable 2 — the baseline.**
### The number
pfi-gx10 MEDIAN 79.36 s/it min/max 79.30 / 79.45 (10 timed steps, 0.19% spread;
warmup 85.90 then 79.32, discarded)
peak memory 75.1 / 121.6 GiB -- 46 GiB SPARE, comfortably not memory-bound
attn_resolved: flex_attention (matched to the harness, read off the model)
FINAL, from the probe's own provenance block on the box
-> 604 steps ~= 13.3 h
peak 75.1 / 121.6 GiB (PyTorch max_memory_allocated) -- 46 GiB spare
ana-ml2 10.8-15.8 s/it (run-03c.log, the real run)
-> 604 steps ~= 2.2-2.7 h
⚠ **6x slower where raw compute predicts 2.7x** (93 TFLOP/s bf16 measured here vs an RTX PRO
6000 Blackwell's ~250). **Hypothesis, not a measurement:** the limiter is **memory bandwidth**
— GB10's unified LPDDR5X against dedicated graphics memory, on a workload built to be
bandwidth-hungry (seq 16384 with gradient checkpointing, which trades compute for memory
traffic by design). Confirming it needs a bandwidth-bound microbenchmark that has not been run.
⚠ **THE GX10 IS A CAPACITY BOX, NOT A THROUGHPUT BOX.** 121 GB holds models nothing else in the
fleet can. It is **not** the box to move a time-sensitive run *to*.
### Byproduct: IF run 3c ever moves here, the GX10 is the right home — and infra-ops' reversal was WRONG
⚠⚠ **infra-ops recommended ana-ml2 and the operator overruled it, correctly.** The error is
worth more than the recommendation: **I costed the failure in the units I was measuring.** I had
step times, so I priced a breaker trip as *"≤50 steps ≈ 11 minutes of lost training"* — the
recompute cost. That is not what a breaker trip at Anaheim costs.
**Operator, 2026-09-02:** *"when the breaker trips at ana, that's a 40 minute drive to reset it.
it's not 25 minutes, it's a giant pain in the ass."*
**The real cost of an Anaheim breaker trip:**
a 40-minute drive EACH WAY, on the operator's time, whenever he notices
13 hosts down: ana-ml2, ana-docker, pfi-pve (hypervisor for most of them),
pfi-postgres, pbs-ana (the fleet's PRIMARY backup server), ana-wg (WireGuard),
pfi-ana-webhost, ana-filebot, pfi-pteradactyl, pfi-tacticalrmm
⚠ including THREE SureFire CLIENT hosts (sfsrv-ana, sf-ana-container, sf-r630)
-- a client's production machines, under a hosting agreement
⚠ **`save_steps` 100 → 50 caps the RECOMPUTE, not the OUTAGE.** It was never the mitigation I
claimed; it only bounds the cheapest component of the loss.
**So: 13.3 h unattended on a desk in NH3, drawing desktop-class power and unable to take down
anything, beats 2.5 h that can put a client's hosts dark until someone drives to Anaheim.** The
GX10's slowness is close to free here — nothing is waiting on this run — and the risk it removes
is expensive and lands on the operator personally.
⚠ **GENERAL FORM, and the reason this is recorded at length: when you recommend between
options, check whether you priced the failure mode in the units you happened to be measuring.**
A metric in hand will volunteer itself as the unit of risk.
### ⚠ Power-capping ana-ml2 is a WEAK lever — measured, do not spend time on it
2x RTX PRO 6000 Blackwell Max-Q: limit 300 W, default 300 W, min 250 W, max 325 W
Capping both GPUs to the floor saves **100 W total** on a box drawing ~1 kW. Not nothing, but
nowhere near enough to make an Anaheim training run safe, and it costs throughput to buy it.
Recorded so nobody re-derives it as a clever third option.
### Probe methodology — five launches, five distinct causes, all recorded
1. reaped SSH long remote job piped through a reapable foreground ssh.
FIX: setsid nohup, log ON the box. Work survived; output did not.
2. bare LoRA target names q_proj/k_proj/... also match Gemma-4's VISION and AUDIO towers,
whose projections are Gemma4ClippableLinear -- PEFT cannot wrap
them. FIX: the real run's 205 fully-qualified names, sha recorded.
3. missing python3-dev Triton JITs a C shim at FIRST USE and needs Python.h. Torch
imports, model loads, LoRA attaches, THEN step 1 dies with a bare
CalledProcessError -- Triton devnulls the compiler's stdout.
4. naive-loss OOM (32 GiB) the 262,144-wide vocab x 32,768 positions logits tensor in fp32.
⚠ NOT a GX10 limit -- the harness docstring says it OOMs "on a
95.60 GiB card (measured)", i.e. on ana-ml2 too.
5. self-inflicted VRAM leak a stuck orphan held 80 GB while PyTorch reported 0 bytes
allocated; every relaunch was doomed before it started and blamed
the NEW run. ⚠ ASSERT THE GPU IS CLEAR BEFORE EVERY LAUNCH.
### ⚠ THE BACKEND-DELTA TRAP WAS PRESENT AND I FIRST DECLARED IT ABSENT
CLAUDE.md records two frontier-panel conclusions voided by a benchmark and a trainer having
silently different attention backends. I checked for it by asking whether **flash-attn was
installed** — the wrong discriminator entirely — and reported "no delta". The harness sets
**`ATTN_IMPLEMENTATION = "flex_attention"`** explicitly in code, with tuned kernel options; its
own comment records peak 74.3 GiB under flex vs sdpa's 79.71.
⚠ **Read the configured value in the code. Absence of an alternative is not evidence of the
default.** The probe now requests flex_attention and reads `_attn_implementation` back off the
loaded model. **RESOLVED: flex_attention — it compiles and runs on sm_121**, which was a real
open risk (flex compiles through Triton; sm_121 is not in torch's arch list).
### Faithfulness of the probe (what makes the number comparable)
LoRA the real run's 205 fully-qualified modules, sha256 c9ee070c0d67eb08
loss path copied from the harness: trunk hidden states, DROP IGNORE_INDEX before the
head, chunk lm_head+CE at loss_chunk_tokens=1024 under checkpoint, softcap 30.0
loss ratio 28.4% of positions masked to match the real 13,310,930 / 18,600,057 loss/ctx
ratio -- observed 23,351-23,638 loss tokens/step against a 23,449 target
tokens sampled [1000, 250000) to stay below every multimodal special token
(boi 255999, boa 256000, image 258880, audio 258881, eoi/eoa/video 258882-4)
warmup first 2 steps discarded; sm_121 JITs from sm_120 PTX on first use
## ⚠ NOT DONE, and deliberately: the run-3c port
Scoped but **not executed** — operator stood it down; the baseline was the goal. Scope, so it
does not have to be re-derived:
harness eitri-smithy 26 MB corpus /mnt/smithy/.../derived 2.3 GB
recipe-r3 485 KB holdout 82 MB
run-03c manifests 70 MB -> ~2.5 GB, ~75 s at 33 MB/s
venv 3.2 GB NOT portable (x86-64) -- rebuild on aarch64
⚠ **No encode cache to preserve.** The launch script's "609 MB encode cache / ~4.3 hours"
comment carries its own correction to 145.5 s, and run 3c's log shows **`[encode] done in
14.4s`** on 32 workers. Nothing worth moving.
⚠ **Copy the corpus; do NOT mount `/mnt/smithy` over NFS on this box.** A desk machine on Wi-Fi
is the wrong place for a hard NFS dependency under a 13-hour unattended run — the fleet has
already lost a host to a hard mount wedging into unkillable D-state
([[incident_esh_docker_nfs_boot_race]]).
The only untested piece is the harness's own 26 MB of Python; every library it leans on is
verified above.