-
Notifications
You must be signed in to change notification settings - Fork 766
feat(lance-linalg): runtime SIMD dispatch for pre-Haswell x86_64 from-source builds #6630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
63040e1
6141fed
378dbb0
77cce31
d39482c
8a08fa8
d000a67
2c71e4c
d5205dc
bdeda97
1903ba4
acf70b7
c247ddd
fb2403c
0969e3d
bb8af46
2c16954
97865b5
334229a
07cd967
6b94ccd
67586aa
86e6c84
225bd4b
18d93d4
b1670de
6d0f401
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -253,6 +253,42 @@ jobs: | |
| - name: Check benchmarks | ||
| run: cargo check --profile ci --benches | ||
|
|
||
| qemu-pre-haswell: | ||
| # Verifies that lance-linalg's runtime SIMD dispatch still works | ||
| # correctly when the binary is built with the lower x86-64-v2 baseline | ||
| # (the legacy build path documented in CONTRIBUTING.md). Emulates a | ||
| # Nehalem CPU under qemu-user; catches any accidental AVX2/FMA | ||
| # instructions that leak past the runtime dispatch. | ||
| # | ||
| # The published-wheel default baseline (`target-cpu=haswell`) is set in | ||
| # `.cargo/config.toml`; this job overrides RUSTFLAGS for one job to | ||
| # exercise the legacy path without affecting any other build. | ||
| name: pre-Haswell SIGILL check (qemu Nehalem) | ||
| runs-on: ubuntu-24.04 | ||
| timeout-minutes: 60 | ||
| env: | ||
| CC: clang | ||
| CXX: clang++ | ||
| RUSTFLAGS: "-C target-cpu=x86-64-v2" | ||
| CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: "qemu-x86_64 -cpu Nehalem" | ||
| steps: | ||
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | ||
| - name: Setup rust toolchain | ||
| run: | | ||
| rustup toolchain install stable | ||
| rustup default stable | ||
| - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Rust cache is enabled by default (cache poisoning risk).
Please confirm this job's triggers (e.g. whether it runs on 🧰 Tools🪛 zizmor (1.26.1)[error] 280-280: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): enables caching by default (cache-poisoning) 🤖 Prompt for AI Agents |
||
| - name: Install dependencies | ||
| run: | | ||
| sudo apt update | ||
| sudo apt install -y protobuf-compiler libssl-dev qemu-user | ||
| - name: Build lance-linalg lib tests in release mode | ||
| run: | | ||
| cargo test --release -p lance-linalg --lib --no-run | ||
| - name: Run lance-linalg lib tests under qemu Nehalem | ||
| run: | | ||
| cargo test --release -p lance-linalg --lib | ||
|
|
||
| msrv: | ||
| # Check the minimum supported Rust version | ||
| name: MSRV Check - Rust v${{ matrix.msrv }} | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -25,6 +25,16 @@ Currently Lance is implemented in Rust and comes with a Python wrapper. So you'l | |||||||||||||||||||||||||||
| a. Install pre-commit: https://pre-commit.com/#install | ||||||||||||||||||||||||||||
| b. Run `pre-commit install` in the root of the repo | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## Building for legacy x86_64 hosts (pre-Haswell) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| The default workspace build targets `haswell` (AVX2 + FMA + F16C), matching the published wheels. To build a binary that runs on pre-Haswell silicon (Sandy Bridge / Ivy Bridge / Westmere on Intel, Bulldozer / Piledriver / Steamroller on AMD — i.e. CPUs without AVX2), set the baseline yourself at build time: | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ```sh | ||||||||||||||||||||||||||||
| RUSTFLAGS="-C target-cpu=x86-64-v2" cargo build --release | ||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Runtime SIMD dispatch in `lance-linalg::distance` will then pick the appropriate tier (scalar / AVX / AVX+FMA / AVX2+FMA / AVX-512) based on the host. From Python, use `lance.simd_info()` to verify which tier was selected. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
Comment on lines
+28
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== CONTRIBUTING excerpt =="
sed -n '20,45p' CONTRIBUTING.md
echo
echo "== Search for target-cpu / haswell references =="
rg -n --hidden --glob '!**/target/**' --glob '!**/node_modules/**' 'target-cpu|x86-64-haswell|haswell' .Repository: lance-format/lance Length of output: 4511 Use Proposed fix-The default workspace build targets `x86-64-haswell` (AVX2 + FMA + F16C), matching the published wheels. To build a binary that runs on pre-Haswell silicon (Sandy Bridge / Ivy Bridge / Westmere on Intel, Bulldozer / Piledriver / Steamroller on AMD — i.e. CPUs without AVX2), set the baseline yourself at build time:
+The default workspace build targets `haswell` (AVX2 + FMA + F16C), matching the published wheels. To build a binary that runs on pre-Haswell silicon (Sandy Bridge / Ivy Bridge / Westmere on Intel, Bulldozer / Piledriver / Steamroller on AMD — i.e. CPUs without AVX2), set the baseline yourself at build time:📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| ## Sample Workflow | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| 1. Fork the repo | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -329,6 +329,7 @@ fn lance(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> { | |
| m.add_wrapped(wrap_pyfunction!(language_model_home))?; | ||
| m.add_wrapped(wrap_pyfunction!(bytes_read_counter))?; | ||
| m.add_wrapped(wrap_pyfunction!(iops_counter))?; | ||
| m.add_wrapped(wrap_pyfunction!(simd_info))?; | ||
| m.add_wrapped(wrap_pyfunction!(stable_version))?; | ||
| // Debug functions | ||
| m.add_wrapped(wrap_pyfunction!(debug::format_schema))?; | ||
|
|
@@ -347,6 +348,37 @@ fn iops_counter() -> PyResult<u64> { | |
| Ok(::lance::io::iops_counter()) | ||
| } | ||
|
|
||
| /// Returns a dict describing which SIMD tier the lance runtime dispatches to | ||
| /// on this host, plus the raw CPU feature flags it detected. | ||
| /// | ||
| /// Mirrors `pyarrow.runtime_info()`: a cheap, transparent way to verify that | ||
| /// the host is hitting the expected SIMD tier (e.g., `"avx512_fp16"`, | ||
| /// `"avx2"`) when debugging vector-search performance. | ||
| /// | ||
| /// Returns: | ||
| /// { | ||
| /// "tier": str, # e.g. "avx2", "avx_fma", "neon", "none" | ||
| /// "target_arch": str, # e.g. "x86_64", "aarch64", "loongarch64" | ||
| /// "host_features": list[str], # raw CPU feature flags (x86_64 only) | ||
| /// } | ||
|
Comment on lines
+354
to
+363
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. praise: I like this API.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thank you! |
||
| /// | ||
| /// Examples: | ||
| /// >>> import lance | ||
| /// >>> info = lance.simd_info() | ||
| /// >>> sorted(info) | ||
| /// ['host_features', 'target_arch', 'tier'] | ||
| /// >>> isinstance(info["tier"], str) | ||
| /// True | ||
| #[pyfunction] | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| pub fn simd_info(py: Python<'_>) -> PyResult<Py<PyAny>> { | ||
| let info = lance_core::utils::cpu::simd_info(); | ||
| let dict = pyo3::types::PyDict::new(py); | ||
| dict.set_item("tier", info.tier.to_string())?; | ||
| dict.set_item("target_arch", info.target_arch)?; | ||
| dict.set_item("host_features", info.host_features)?; | ||
| Ok(dict.into()) | ||
| } | ||
|
|
||
| #[pyfunction(name = "bytes_read_counter")] | ||
| fn bytes_read_counter() -> PyResult<u64> { | ||
| Ok(::lance::io::bytes_read_counter()) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
sed -n '250,320p' .github/workflows/rust.ymlRepository: lance-format/lance
Length of output: 3077
Disable persisted checkout credentials
.github/workflows/rust.yml:275—actions/checkoutleaves the repo token in git config by default, and this job runscargo test, so build scripts or tests can read it. Setpersist-credentials: falsehere.🧰 Tools
🪛 zizmor (1.26.1)
[warning] 275-275: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 Prompt for AI Agents
Source: Linters/SAST tools