examples: geostrophic stencil through int8_tile_gemm_16x16 — real ERA5, 4/4 pre-registered bars - #275
examples: geostrophic stencil through int8_tile_gemm_16x16 — real ERA5, 4/4 pre-registered bars#275AdaWorldAPI wants to merge 7 commits into
Conversation
…ll (W1a) The AMX ladder comment at simd.rs:577 promises "the whole AMX ladder through ndarray::simd::* (W1a) without dipping into crate::hpc directly" — but the BF16 16×16 tile GEMM was only reachable via ndarray::hpc::bf16_tile_gemm, forcing consumers (lance-graph symbiont Domino POC) to violate the "all SIMD from ndarray::simd" rule. Add the re-export next to amx_available/matmul_i8_to_i32. bf16_tile_gemm_16x16 self-gates on amx_available() (the one-time arch_prctl(158) XTILEDATA grant per AMX_GOTCHAS.md Gotcha 4), using AMX TDPBF16PS when present and the F32x16 FMA fallback otherwise — safe on any CPU. std-gated like the rest of the AMX surface. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
… a bug) Breadcrumb so no future session reads one amx_available()==false as "AMX broken." Probe all FOUR gates (not just CPUID): CPUID masked-to-0, XCR0 b17/b18 tile-state, arch_prctl(158) REQ_XCOMP_PERM (-EOPNOTSUPP = kernel refuses, no byte-call forces it), GET_XCOMP_PERM mask. Observed once: all four deny -> genuinely unavailable, detect_amx() correctly false, consumers run the AVX-512/F32x16 fallback. Same binary prints [AMX TDPBF16PS] where arch_prctl returns 0 + XCR0 bits set. Placed mid-doc (before Hardware tiers/Files) on purpose — out of the head/tail zone a skim touches — so it informs without mis-scenting the file as "no AMX." Cross-ref lance-graph EPIPHANIES E-DOMINO-SOA-ORCHESTRATION-GREEN. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
…o stale Ecosystem realignment: lance-graph, OGAR, woa-rs and MedCare-rs moved to 1.97.1 in the lance-9 / DataFusion-54 sweep (lance-graph b2b08b07); this repo was left behind. The comment is restructured per lance-graph #916: it no longer restates the pinned version (that is what makes these files go stale — a bump edits channel and leaves the prose behind) and carries an append-only bump log instead. Where the old comment asserted cross-repo alignment that had since become false, the claim is corrected in place rather than deleted. Verified: cargo check green under 1.97.1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
…ERA5, u8 substrate
Operator: "Was ist mit Domino.rs" -> "Go ahead" on the falsifiable step I
proposed — route the geostrophic finite-difference stencil through the AMX
int8 tile-GEMM path domino.rs (lance-graph) tile-batches, and diff against
the numpy reference from the session's voxel_chess_probe.py.
The stencil-as-matrix mapping onto ONE AMX tile:
A[16,K=64] u8 — 16 independent latitude rows x 64 quantized
mean_sea_level_pressure samples per row
B[K=64,N=16] i8 — 16 columns, each an EXACT {-1,0,+1} centered-difference
stencil at a distinct longitude tap (no quantization
error in the operator, only in the data it multiplies)
C[16,16] i32 = A . B via int8_tile_gemm_16x16 — the SAFE dispatching
wrapper (AMX TDPBUSD when available, scalar fallback
otherwise; the crate's own fallback_matches_scalar_
reference_k64 already proves those two paths bit-exact)
Checked BEFORE speccing anything: this container has no AMX_TILE/AMX_INT8
(/proc/cpuinfo). int8_gemm_amx_tiled has NO runtime AMX check ("production
builds skip those for performance -- callers must runtime-check
amx_available() themselves") and would execute raw TDPBUSD on this host,
faulting. int8_tile_gemm_16x16 is the correct entry point precisely because
it dispatches. Measured, not assumed: amx_available() = false, so this run
exercised the scalar fallback -- reported explicitly in the output, not
silently glossed over.
Real data, real provenance: WeatherBench2 ERA5 6h 0.25deg,
mean_sea_level_pressure, t=91246 (2021-06-15 12Z, the SAME timestep as
voxel_chess_probe.py), 16 rows spanning 52.25N..59.75N around the NH
storm that probe's own E6 Rankine measurement centered on
(55.75N, 334.50E), 64-wide longitude window centered on that storm.
4096-byte fixture, include_bytes!'d next to the example (life.rs/life.txt
precedent), regenerable against the recorded store/time_index/indices.
Four pre-registered bars, all measured (not assumed) and all PASS:
BAR-1 corr(d_est, d_true) = 0.9985 (bar >= 0.98 -- fires correctly)
BAR-2 max|d_est-d_true| = 10.58 Pa (bar <= 11.86 Pa -- quant bound,
real headroom, not padding)
BAR-3 std(d_true) = 91.62 Pa (bar > 50 Pa -- non-trivial
sample, the silence guard)
DISABLE-RUN (sign-flipped stencil): corr = -0.9985 (bar <= -0.90) --
proves the harness can actually detect a broken stencil, not just
print a number that happens to look right.
Gates: my file rustfmt-clean, zero clippy findings attributed to
examples/geostrophic_stencil.rs. NOT touched: src/iterators/mod.rs, which
already has 4 pre-existing clippy errors on the clean tree (verified via
git stash before/after) -- left alone per this session's own scope
discipline, not swept.
Honest scope statement, restated in the file's own doc comment: this
validates the stencil-as-GEMM numerics and the u8-quantization pipeline on
THIS host's scalar-fallback path, not AMX TDPBUSD throughput -- that
requires Sapphire-Rapids-class hardware, which this container lacks.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
Per CLAUDE.md's own rule -- write decisions to the blackboard, not just to chat. Cross-repo context, the AMX-vs-scalar decision and its reasoning, and the loose end (no AMX host available in this container to validate the TDPBUSD path itself) recorded so a future session doesn't re-derive them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
|
Warning Review limit reached
Next review available in: 51 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdded an ERA5 geostrophic-stencil example with quantization, GEMM dispatch, validation checks, and fallback reporting. Added a BF16 tile GEMM re-export, updated the pinned Rust toolchain, and documented AMX diagnostics and probe results. ChangesAMX stencil probe
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant ERA5Fixture
participant geostrophic_stencil
participant int8_tile_gemm_16x16
participant Validation
ERA5Fixture->>geostrophic_stencil: Load and quantize pressure data
geostrophic_stencil->>int8_tile_gemm_16x16: Submit centered-difference stencil
int8_tile_gemm_16x16-->>geostrophic_stencil: Return AMX or scalar GEMM output
geostrophic_stencil->>Validation: Check correlation, error, variation, and sign flip
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1⚔️ Resolve merge conflicts 💡
📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_b4084826-3f32-4d41-b630-8be19df7f7ed) |
Resolves the four conflicts from the parallel 1.97.1 toolchain bump landing on master (#274) alongside this branch's own pin: - rust-toolchain.toml: kept this branch's stale-proof bump-log structure (version stated only in `channel`, never restated in prose), folded in master's channel-and-rust-version-must-move-together rule. Both sides pinned the identical 1.97.1. - src/simd.rs: both sides added re-exports at the same anchor — kept BOTH (this branch's bf16_tile_gemm_16x16 W1a re-export + master's runtime-dispatch trampolines). Purely additive. - .claude/AMX_GOTCHAS.md: both sides added a "Gotcha 14" — two DIFFERENT real findings. Master's (silent tile-state corruption on oversubscribed VMs) keeps 14 as merged first; this branch's (guest can DENY AMX outright, env gate) renumbered to Gotcha 15. Both retained in full. - .claude/blackboard.md: append-log collision at EOF — master's entries (chronologically older, 2026-07-*) first, this branch's 2026-08-11 geostrophic probe entry after. Nothing dropped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/geostrophic_stencil.rs`:
- Around line 8-10: Update the module documentation near the geostrophic-balance
description to identify the calculated p[tap + 1] - p[tap - 1] operation as a
longitudinal MSLP finite difference, or as a pressure-gradient component only
when noting grid-spacing normalization; do not describe it as du/dy.
In `@src/simd.rs`:
- Around line 582-585: Clarify the `src/simd.rs` comment by identifying 158 as
the x86_64 SYS_arch_prctl syscall number, not an operation argument. In
`.claude/AMX_GOTCHAS.md` lines 239-241, update both diagnostics to use
syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_PERM, XFEATURE_XTILEDATA) and
syscall(SYS_arch_prctl, ARCH_GET_XCOMP_PERM, &mask).
- Around line 582-587: Remove the unaliased bf16_tile_gemm_16x16 re-export from
the SIMD exports, leaving the existing _amx alias intact so crate::simd_ops
remains the canonical export.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 1c9f4561-c78a-47b7-982d-14dd82e16104
⛔ Files ignored due to path filters (1)
examples/geostrophic_stencil.binis excluded by!**/*.bin
📒 Files selected for processing (6)
.claude/AMX_GOTCHAS.md.claude/blackboard.mdCargo.tomlexamples/geostrophic_stencil.rsrust-toolchain.tomlsrc/simd.rs
| //! term of geostrophic balance, `du/dy` via centered differences) after the | ||
| //! input has been quantized to the shipped u8-palette convention, and how | ||
| //! close the GEMM-recovered value lands to the unquantized f64 reference. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Correct the described physical quantity.
The implementation calculates p[tap + 1] - p[tap - 1] in Lines 170-171. It does not calculate du/dy. Describe this operation as a longitudinal MSLP finite difference, or as a pressure-gradient component after grid-spacing normalization.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@examples/geostrophic_stencil.rs` around lines 8 - 10, Update the module
documentation near the geostrophic-balance description to identify the
calculated p[tap + 1] - p[tap - 1] operation as a longitudinal MSLP finite
difference, or as a pressure-gradient component only when noting grid-spacing
normalization; do not describe it as du/dy.
| // BF16 16×16 tile GEMM — AMX `TDPBF16PS` when `amx_available()`, `F32x16` FMA | ||
| // fallback otherwise. Same W1a rule: reach it via `ndarray::simd::*`, never | ||
| // `crate::hpc` directly (the one-time `arch_prctl(158)` XTILEDATA grant is gated | ||
| // inside `amx_available()`, which this dispatcher calls before any tile op). |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- src/simd.rs ---'
sed -n '570,592p' src/simd.rs
printf '%s\n' '--- .claude/AMX_GOTCHAS.md ---'
sed -n '232,246p' .claude/AMX_GOTCHAS.md
printf '%s\n' '--- all related references ---'
rg -n -C 2 'arch_prctl|ARCH_REQ_XCOMP_PERM|ARCH_GET_XCOMP_PERM|XTILEDATA|XFEATURE' src/simd.rs .claude/AMX_GOTCHAS.mdRepository: AdaWorldAPI/ndarray
Length of output: 7829
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- AMX-related files ---'
git ls-files | rg '(^|/)(simd_amx|amx|hpc|Cargo.toml|build.rs)' | head -100
printf '%s\n' '--- arch_prctl implementation references ---'
rg -n -C 4 'SYS_arch_prctl|ARCH_REQ_XCOMP_PERM|ARCH_GET_XCOMP_PERM|arch_prctl|syscall' --glob '*.rs' --glob '*.md' .
printf '%s\n' '--- relevant documentation context ---'
sed -n '74,92p' .claude/AMX_GOTCHAS.md
sed -n '278,289p' .claude/AMX_GOTCHAS.mdRepository: AdaWorldAPI/ndarray
Length of output: 16607
🌐 Web query:
Linux arch_prctl man page ARCH_REQ_XCOMP_PERM syscall SYS_arch_prctl argument form
💡 Result:
The ARCH_REQ_XCOMP_PERM operation for the arch_prctl(2) system call is used to request permission to utilize dynamically enabled XSTATE features (such as AMX) in user space applications [1][2]. The system call argument form is: syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_PERM, feature_nr); In this structure: - ARCH_REQ_XCOMP_PERM is the operation code, defined as 0x1023 in the Linux kernel headers [3]. - feature_nr is the argument representing the feature or facility being requested. Specifically, it is the number of the highest XSTATE component required for the facility to operate [1][2]. For instance, when requesting AMX support, which requires both XFEATURE_XTILE_CFG (17) and XFEATURE_XTILE_DATA (18), the appropriate argument is ARCH_XCOMP_TILEDATA (18) [3][2]. Applications can use this syscall to ensure the kernel properly handles larger xstate buffers for tasks, including adjustments for sigaltstack requirements, if the requested feature is granted [1]. Permissions granted via this call are process-wide, inherited across fork(2), and cleared upon exec(3) [1].
Citations:
- 1: https://docs.kernel.org/arch/x86/xstate.html
- 2: https://lists.openwall.net/linux-kernel/2021/10/26/923
- 3: https://codebrowser.dev/linux/linux/arch/x86/include/uapi/asm/prctl.h.html
Use unambiguous arch_prctl syscall terminology.
- In
src/simd.rs, label158as the x86_64SYS_arch_prctlsyscall number. - In
.claude/AMX_GOTCHAS.md, write both diagnostics assyscall(SYS_arch_prctl, ARCH_REQ_XCOMP_PERM, XFEATURE_XTILEDATA)andsyscall(SYS_arch_prctl, ARCH_GET_XCOMP_PERM, &mask).158is not anarch_prctloperation argument.
📍 Affects 2 files
src/simd.rs#L582-L585(this comment).claude/AMX_GOTCHAS.md#L239-L241
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/simd.rs` around lines 582 - 585, Clarify the `src/simd.rs` comment by
identifying 158 as the x86_64 SYS_arch_prctl syscall number, not an operation
argument. In `.claude/AMX_GOTCHAS.md` lines 239-241, update both diagnostics to
use syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_PERM, XFEATURE_XTILEDATA) and
syscall(SYS_arch_prctl, ARCH_GET_XCOMP_PERM, &mask).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 81cd5d2693
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -1,19 +1,21 @@ | |||
| [toolchain] | |||
| channel = "1.97.1" | |||
There was a problem hiding this comment.
Preserve the toolchains selected by CI
Changing the directory pin to 1.97.1 without updating the workflow causes unqualified cargo commands to select 1.97.1 rather than the toolchains installed by the jobs. In particular, .github/workflows/ci.yaml still declares the MSRV as 1.95.0 and installs 1.95.0 for clippy/format, so the MSRV row no longer validates the compiler promised by Cargo.toml; regressions requiring post-1.95 Rust can therefore pass CI. I confirmed the override behavior with rustup show active-toolchain in this checkout, which selects/attempts to install 1.97.1 despite 1.95.0 being the default. Update the workflow pins or invoke the matrix toolchain explicitly when retaining 1.95 MSRV coverage.
Useful? React with 👍 / 👎.
My 2026-08-11 merge of origin/master kept BOTH sides of the simd.rs re-export block, which introduced a duplicate `bf16_tile_gemm_16x16` name: once unaliased from `hpc::bf16_tile_gemm` (this branch's W1a re-export) and once from `simd_ops` (master's canonical polyfill export). The collision is a hard compile error, which is why clippy, tests, native-backend, tier4-avx512, wasm-simd, neon-qemu and hpc-stream-parallel all went red at once on 921bd7a. Resolution: drop this branch's unaliased re-export and keep master's deliberate two-name split — `bf16_tile_gemm_16x16` (the pure polyfill kernel, from simd_ops) and `bf16_tile_gemm_16x16_amx` (the tile-dispatching wrapper, from hpc). Master's arrangement already satisfies the W1a "reach it via ndarray::simd::*" intent that this branch's export was written for, so nothing is lost. No tile-GEMM function is added or removed by this branch — `int8_tile_gemm_16x16` (used by the geostrophic example) has been on master since 58200fb, and no 16x32 tile GEMM exists in the crate; the only 16x32 symbols are SIMD register types (I16x32/U16x32) in simd_nightly, which are lane widths, not tile kernels. 16x16 is AMX's native TDPBUSD accumulator geometry, not a choice. Also in this commit: - Restore the newline my merge script ate between the `_amx` re-export and the CPU-generation comment (this was the `format/stable` failure). - Correct the arch_prctl wording in AMX_GOTCHAS Gotcha 15: 158 is the x86_64 SYS_arch_prctl syscall NUMBER, not an operation argument, so both diagnostics now read `syscall(SYS_arch_prctl /* 158 */, ARCH_{REQ,GET}_XCOMP_PERM, ...)`. Raised by CodeRabbit on #275 and correct on the merits. Gates, run locally on the merged tree: `cargo fmt --check` clean, `cargo check --lib --features std` clean, `cargo clippy --lib --features std` no errors, and `cargo run --example geostrophic_stencil` green with all 4 pre-registered bars PASS on the scalar-fallback path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
What
examples/geostrophic_stencil.rs+ committed fixture: a centered-difference pressure-gradient stencil executed as a matrix throughint8_tile_gemm_16x16— A[16,64] = u8-quantized real ERA5 MSLP rows, B[64,16] = exact {−1,0,+1} stencil columns, C[16,16] i32 — proving that the same tile-GEMM path that executes learned weights executes explicit physics. A finite-difference stencil IS a matrixW.All 4 pre-registered bars PASS on real WeatherBench2 data (full provenance in the fixture header): corr 0.9985 vs f64 reference, max err 10.58 Pa vs 11.86 bar, std 91.62 Pa, sign-flip −0.9985.
Safety: uses the checked dispatcher
int8_tile_gemm_16x16(AMX TDPBUSD ↔ scalar fallback, bit-exact perfallback_matches_scalar_reference_k64), never the uncheckedint8_gemm_amx_tiled— this container has no AMX and the example runs green on the scalar path.Why it matters downstream
This is the execution seam for the "spine + moderators" architecture in the companion PR (AdaWorldAPI/lance-graph#926): storm spine features as board state, moderator sets as
W,C = A·Wthrough this exact path — domino.rs' symbiont step shape. Explicit physics and learned weights become the same instruction.Also included:
.claude/blackboard.mdprobe/decision/loose-end entry per this repo's agent protocol, and the 1.97.1 toolchain pin restructure.Gates run:
cargo fmtclean on the new file; example runs green; pre-existing clippy findings insrc/iterators/mod.rsverified pre-existing viagit stash(0 findings attributable to this change).🤖 Generated with Claude Code
https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
Generated by Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores