igneum/relay/playbooks/ca2-hot-9070-bench.ps1
igneum-labs 39ecd7c52b hot table (Counter ASIC 2.0 layer 5), measured and not adopted, on the ca2-v3 composed class (squash of tag ca2-cache-history-2026-10-05)
LoadClass::hot (Option<HotClass { mb, k, added }>) beside mix, slots, scratch, mixer_mult, growth and era; V3_CLASS = { era: None, hot: None, ..LoadClass::MX4 } (hot stays None: the hot code is behind the flag, measured and not adopted). Op::Hot, the hot slots drawn after the scratch slots, no width roll (v2_loads allows the added form's extra slots), the id suffix hot/<S><k>[added], the hot parsing inside parse_loads, the era branch first in name(). HotTable under seed_words("igneum-hot/" || epoch seed) with the cache chain and tag umHT, read at H[mulhi(src, HOT_WORDS)]; DatasetSource::hot attached by new_class_day and from_seed_bytes_class; the acceptance stand-in dataset_elem(idx, S[2], S[3]); the three emitters (hot argument after the init words, ht_segment and igneum_hot_fill beside the layout-aware cores); packfile.h hot fields beside class, era, attempt and mixerMult; OpenCL host, Metal packbench and NVRTC worker fill H on the device and self-test it. Eight packs under proto-cuda/packs-ca2-hot (replaced hot32k4 hot64k4 hot96k4 hot64k2 hot64k8, added hot32k4a hot64k4a hot96k4a) re-exported on the merged crate: vectors unchanged, program.h and program.json carry the mixer fields. docs/plans/hot-table.md (design, spec text, per-tier budget, chip model, Mac and PC measurements, the decision: layer 5 out of v3, the 3.0 note); bench-log entry and addenda with job ids and worker sha256s; the two PC playbooks.

Checks on this commit: cargo test --release 53 + 19 pass (the pinned v2, mx4, era, readwidth and hot packs); the pinned packs under proto-cuda/packs, packs-ca2-mixer, packs-ca2-era and packs-readwidth untouched; Metal packbench and Apple OpenCL --bench-pack on all eight hot packs (run lock, 2^20 at base 0): 96/96 lanes, hot table head, last line and FNV PASS, one fingerprint per pack on both harnesses, equal to the fingerprints before the rebase (hot32k4 679e5e83378d3790, hot64k4 d4c9e456b039fdef, hot96k4 7c98eceffee9fd73, hot64k2 f43b10a95879b8e5, hot64k8 c11309d743be9392, hot32k4a afb700b2d997c847, hot64k4a ba214baa9c1a9e85, hot96k4a 29e1916aed6deff5). No era or mixer behaviour changed: every resolution kept the ca2-v3 side and appended the hot branch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-05 21:57:39 +00:00

85 lines
6.5 KiB
PowerShell

# Igneum run job: the hot-table experiment (Counter ASIC 2.0 layer 5, docs/plans/hot-table.md) on PC 1's RX 9070 XT on the eGPU (machine ae432dc7), 5 October 2026 (the probe at the hot sizes 32, 64 and 96 MiB, then the five hot packs).
# Published as a plain `run` job (NOT --stop-miners): the installed app keeps every other card mining; this script switches
# off ONLY the NVIDIA card in the app through POST <app.url>api/cards, waits for its worker to stop, runs the fetched
# igneum-worker-opencl.exe (--memprobe, then --bench on every pack of the fetched packs folder), and switches the card back
# on with the settings it had. Every result line starts with RESULT so `node tools/jobs.mjs <job id>` shows them.
$ErrorActionPreference = 'Continue'
function Say([string] $m) { Write-Host ("[" + (Get-Date -Format 'HH:mm:ss') + "] " + $m) }
$jobs = Split-Path $env:IGNEUM_JOB_DIR
$fetched = Join-Path $jobs 'fetch-ca2-hot-20261005'
$exe = Join-Path $fetched 'igneum-worker-opencl.exe'
$packs = Join-Path $fetched 'packs-ca2-hot'
if (-not (Test-Path $exe)) { Write-Output "RESULT error worker missing at $exe (the fetch job runs first)"; exit 2 }
if (-not (Test-Path $packs)) { Write-Output "RESULT error packs missing at $packs"; exit 2 }
Write-Output "RESULT worker $exe sha256 $((Get-FileHash -Algorithm SHA256 $exe).Hash.ToLower())"
# the card's OpenCL device index on the current (3683.0) platform, from the worker's own list (the older platform's duplicate is marked dup)
$list = & $exe --list 2>&1
$list | ForEach-Object { "RESULT list $_" }
$dev = $null
$cardName = 'gfx1201'
foreach ($l in $list) { if ($l -match '^\s*\[(\d+)\].*gfx1201' -and $l -notmatch 'dup') { $dev = [int]$Matches[1]; break } }
# 5 October 2026, 20:40 UTC: the Sonnet eGPU box dropped off PC 1's USB4 link (gfx1201 absent at 20:45:34Z). Gate G1's
# AMD vendor is then the integrated gfx1036 (coordinator's ruling): bit-exactness only (vectors, hot table head, last
# line and FNV, the 2^24 fingerprint at base 0 equal to the 5090's and the Mac's); its probe and hash rate say nothing
# about the 9070 XT (2 MB of cache, approximate) and are skipped as owed. If gfx1201 is back at run time, it runs as planned.
if ($null -eq $dev) {
foreach ($l in $list) { if ($l -match '^\s*\[(\d+)\].*gfx1036' -and $l -notmatch 'dup') { $dev = [int]$Matches[1]; $cardName = 'gfx1036'; break } }
}
if ($null -eq $dev) { Write-Output 'RESULT error neither gfx1201 nor gfx1036 in --list'; exit 2 }
Write-Output "RESULT amd-device $dev $cardName"
Write-Output "RESULT device $dev"
# the app: switch off the NVIDIA card only, remember its settings
$appDir = $env:IGNEUM_APP_DIR
if (-not $appDir) { $appDir = Join-Path $env:LOCALAPPDATA 'igneum\app' }
$urlFile = Join-Path $appDir 'app.url'
$url = $null
if (Test-Path $urlFile) { $url = (Get-Content -LiteralPath $urlFile -Raw).Trim() }
$card = $null
if ($url) {
try {
$st = Invoke-RestMethod -Uri ($url + 'api/state') -Method GET -TimeoutSec 10
$card = $st.mining.cards | Where-Object { ($_.vendor -eq 'amd' -and $_.key -match $cardName) } | Select-Object -First 1
if (-not $card) { $card = $st.cards | Where-Object { ($_.vendor -eq 'amd' -and $_.key -match $cardName) } | Select-Object -First 1 }
} catch { Say ("api/state: " + $_.Exception.Message) }
}
if ($card) {
Write-Output ("RESULT card " + $card.key + " enabled=" + $card.enabled + " identities=" + $card.identities + " power_pct=" + $card.power_pct + " state=" + $card.state)
$body = @{ cards = @(@{ key = $card.key; enabled = $false; identities = [int]$card.identities; power_pct = [int]$card.power_pct }) } | ConvertTo-Json -Depth 5
try { Invoke-RestMethod -Uri ($url + 'api/cards') -Method POST -Body $body -ContentType 'application/json' -TimeoutSec 10 | Out-Null; Say "card off requested" } catch { Say ("api/cards off: " + $_.Exception.Message) }
$t = 0
while ($t -lt 90) {
Start-Sleep -Seconds 5; $t += 5
try { $st = Invoke-RestMethod -Uri ($url + 'api/state') -Method GET -TimeoutSec 10; $c2 = $st.mining.cards | Where-Object { $_.key -eq $card.key }; if (-not $c2) { $c2 = $st.cards | Where-Object { $_.key -eq $card.key } }; if ($c2 -and $c2.state -eq 'off' -and $c2.pid -eq 0) { break } } catch { }
}
Write-Output ("RESULT card-off after " + $t + " s")
Start-Sleep -Seconds 5
} else { Write-Output 'RESULT card none-found (the app is not running or has no NVIDIA card); measuring with whatever else runs on the GPU' }
# the probe ran in run-readwidth-9070-20261005 (bench-log, 5 October 2026); this second run is the bench only
# the probe at the hot sizes (64 MiB exists from the 9070 XT entry: 9.17 G loads/s; 32 and 96 MiB are new; 1024 MiB again, the same session)
if ($cardName -eq 'gfx1201') {
foreach ($mib in @(32, 64, 96, 1024)) {
Write-Output "RESULT memprobe $mib start $(Get-Date -Format HH:mm:ss)"
& $exe --memprobe --probe-mib $mib --device $dev 2>&1 | ForEach-Object { "RESULT $_" }
}
} else { Write-Output 'RESULT memprobe skipped (gfx1036: its cache says nothing about the 9070 XT; the 32, 96 and 1024 MiB rows stay owed)' }
# the eight hot packs (five replaced, three added, docs/plans/hot-table.md 2.3): --bench-pack builds the pack, fills the hot table on the device from the epoch seed, self-tests it
# (cache, dataset, hot table head, last line and FNV, 96 vector lanes) and times 5 dispatches of 2^24 nonces
foreach ($pk in @('hot32k4', 'hot64k4', 'hot96k4', 'hot64k2', 'hot64k8', 'hot32k4a', 'hot64k4a', 'hot96k4a')) {
$d = Join-Path $packs $pk
Write-Output "RESULT bench $pk start $(Get-Date -Format HH:mm:ss)"
if ($cardName -eq 'gfx1201') {
& $exe --bench-pack --pack $d --batches 5 --batch-log2 24 --device $dev 2>&1 | ForEach-Object { "RESULT $_" }
& $exe --bench-pack --pack $d --batches 5 --batch-log2 24 --device $dev --group-warps 8 2>&1 | Where-Object { $_ -match '^RESULT|error|FAIL' } | ForEach-Object { "RESULT $_" }
} else {
# bit-exactness only: one timed dispatch after the warm-up, the same 2^24 nonces at base 0 as the 5090 and the Mac (about 6 s each at 3 MH/s); the mhs= field is not a number
& $exe --bench-pack --pack $d --batches 1 --batch-log2 24 --device $dev 2>&1 | ForEach-Object { "RESULT $_" }
}
}
if ($card) {
$body = @{ cards = @(@{ key = $card.key; enabled = [bool]$card.enabled; identities = [int]$card.identities; power_pct = [int]$card.power_pct }) } | ConvertTo-Json -Depth 5
try { Invoke-RestMethod -Uri ($url + 'api/cards') -Method POST -Body $body -ContentType 'application/json' -TimeoutSec 10 | Out-Null; Write-Output ("RESULT card restored enabled=" + $card.enabled) } catch { Write-Output ("RESULT error card restore: " + $_.Exception.Message) }
}
exit 0