Skip to content

ci: run lance-linalg's release tests on the runner's own CPU - #8844

Open
LuciferYang wants to merge 1 commit into
lance-format:mainfrom
LuciferYang:ci/linalg-native-release-run
Open

ci: run lance-linalg's release tests on the runner's own CPU#8844
LuciferYang wants to merge 1 commit into
lance-format:mainfrom
LuciferYang:ci/linalg-native-release-run

Conversation

@LuciferYang

Copy link
Copy Markdown
Contributor

What this changes

qemu-pre-haswell already builds lance-linalg's lib tests in release mode. This adds one step that runs that same binary a second time, on the runner's own CPU instead of under qemu, by overriding the cargo runner to env for that step only. The build step and the new run move above the QEMU setup steps, and the job's name: changes because it now does two things.

Why: the dispatched SIMD kernels have never run in an optimized build

The job emulates a Nehalem, and every runtime feature gate in lance-linalg tests for avx, avx2, fma, or an avx512* feature. A Nehalem has none of them, so SIMD_SUPPORT resolves to None and every dispatch takes its fallback arm. That is correct for a SIGILL check, but it means the dispatched kernels are never executed in an optimized build anywhere in CI: the four jobs that run tests all use the ci profile, which inherits dev.

Running the binary that is already on disk closes that gap, and it closes it for free. The bug shape this is aimed at is an out-of-bounds store inside a SIMD kernel that only the optimizer's unrolling makes reachable. Nothing in CI executes those instructions today.

Cost

Nothing beyond the test run itself. Measured locally: after cargo test --release -p lance-linalg --lib --no-run, changing only the runner env var and running again reports every crate Fresh and recompiles nothing. The runner override is not an input to cargo's build fingerprint. The job's existing 60 minute budget already covers a from-scratch release build.

What the native run does not cover

Worth stating so the next reader does not assume more than is there.

The binary is built with the job's RUSTFLAGS: "-C target-cpu=x86-64-v2", and env RUSTFLAGS replaces the per-target rustflags in .cargo/config.toml wholesale. So #[cfg(target_feature = "avx2")] code is compiled out of it, and only the runtime-dispatched kernels are reachable, since #[target_feature(enable = "avx2")] is additive per function. Both runs use default features, so fp16kernels is off.

Which dispatch tier the native run takes depends on the runner's CPU, and GitHub does not contract a CPU model. test_x86_runtime_feature_report writes the detected features to stderr, so the job log records what actually happened rather than leaving it to be inferred.

Why the new step sits before the QEMU build

A step runs only if the ones before it succeeded, and the QEMU steps include building QEMU 8.2.10 from source on a cache miss. With the build and the native run first, a QEMU failure cannot take the native signal down with it. Nothing in the QEMU setup is a prerequisite for the cargo build: --no-run never invokes the runner, and lance-linalg's build.rs needs only a C compiler.

The move does not disturb the two ordering constraints in the job. Swatinem/rust-cache still precedes the first cargo invocation, and Restore QEMU 8.2.10 still precedes both steps that read its cache-hit output.

The rename, and the one line of Rust

The job id qemu-pre-haswell is unchanged, so the rust-cache key, which is derived from github.job, is unaffected. Only the display name changes.

rust/lance-linalg/src/distance/dot_f16.rs referred to the job by its display name, which the rename would have left pointing at a string that exists nowhere in the repository. It now names the job id, matching what rust/lance-linalg/src/simd/i32.rs already does.

Test plan

  • cargo test --release -p lance-linalg --lib: 389 passed on aarch64-apple-darwin, and 448 passed on x86_64-apple-darwin with RUSTFLAGS="-C target-cpu=x86-64-v2" and the pass-through runner. That second run is the closest local equivalent of the x86 leg, and it confirms three things at once: the v2 baseline builds, env works as a cargo runner, and test_x86_runtime_feature_report is visible without --nocapture
  • cargo fmt --all -- --check, cargo clippy -p lance-linalg --all-targets -- -D warnings, and RUSTDOCFLAGS="-D warnings" cargo doc -p lance-linalg --no-deps --document-private-items: clean
  • The workflow parses, and the resulting step order was checked against both ordering constraints above

The AVX2 and AVX-512 arms were compiled but not executed. This machine is aarch64, and an x86_64 build under Rosetta reports neither feature, so those arms first execute when this job runs on a real x86 runner. That is the change.

Two gaps this leaves open

  • No job runs lance-linalg in an optimized profile with --features fp16kernels. Turning it on compiles C, which would cost a rebuild and undo the zero-cost property above, so it belongs in its own change
  • .cargo/config.toml is not in this workflow's paths: filter, so a PR that changes [profile.release] or the x86 baseline runs no Rust CI at all. One line fixes it, but it also makes more PRs run the full Rust suite, which is a runner budget call for a maintainer rather than a drive-by here

@github-actions github-actions Bot added A-index Vector index, linalg, tokenizer A-ci CI / build workflows ci Github Action or Test issues labels Aug 28, 2026

@lance-gatekeeper lance-gatekeeper Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Gate recommendation: approve with a non-blocking risk.

The change correctly reuses the x86-64-v2 release artifact, preserves the Nehalem fallback/SIGILL run, and adds the native execution without recompiling.

The remaining risk is intentional: GitHub does not contract an AVX-capable runner, so a green native run does not by itself prove that a SIMD arm executed. The existing feature report makes the actual tier visible in the log; no further change is requested for this pull request.

@lance-gatekeeper lance-gatekeeper Bot added K-approved Latest Gatekeeper recommendation permits acceptance. K-risk Latest Gatekeeper recommendation includes a non-blocking risk. labels Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ci CI / build workflows A-index Vector index, linalg, tokenizer ci Github Action or Test issues K-approved Latest Gatekeeper recommendation permits acceptance. K-risk Latest Gatekeeper recommendation includes a non-blocking risk.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant