Skip to content

feat(wheels): publish lancedb-compat for pre-Haswell x86_64 hosts#3327

Merged
wjones127 merged 6 commits into
lancedb:mainfrom
tobocop2:upstream/document-pre-haswell-build
Jul 16, 2026
Merged

feat(wheels): publish lancedb-compat for pre-Haswell x86_64 hosts#3327
wjones127 merged 6 commits into
lancedb:mainfrom
tobocop2:upstream/document-pre-haswell-build

Conversation

@tobocop2

@tobocop2 tobocop2 commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Tracks #3324. On x86_64 CPUs without AVX2 (Sandy Bridge / Ivy Bridge / Westmere on Intel; Bulldozer / Piledriver / Steamroller on AMD), import lancedb SIGILLs because the wheel bakes AVX2 + FMA into every compiled function. Per westonpace's review, the default lancedb wheel stays fast; pre-Haswell users get a separately-published lancedb-compat wheel.

Summary

  • Adds a lancedb-compat matrix entry to pypi-publish.yml that builds with RUSTFLAGS="-C target-cpu=x86-64-v2" (Nehalem-class baseline). Same Python API (import lancedb works) — files install to the same namespace, so the two wheels conflict at install time and users pick one. Same pattern as psycopg2 / psycopg2-binary and tensorflow / tensorflow-cpu.
  • Generalizes build_linux_wheel and upload_wheel composites with optional package-name and rustflags inputs (defaults preserve the existing 4 lancedb matrix entries verbatim).
  • Documents the choice in python/README.md: pip install lancedb-compat for pre-Haswell hosts.

The default .cargo/config.toml baseline is unchanged.

Sequencing

  1. feat(lance-linalg): runtime SIMD dispatch for pre-Haswell x86_64 from-source builds lance-format/lance#6630 merges → runtime SIMD dispatch lands in lance. Done — merged.
  2. lancedb's lance dep is bumped to a release that includes it (separate PR / normal cadence).
  3. This PR's lancedb-compat wheel build path starts producing a wheel that runs on pre-Haswell hardware. Maintainer setup: register lancedb-compat on PyPI and configure trusted publishing.

Verified end-to-end on Sandy Bridge Xeon E5-2609

Verification was done locally against a fork-pinned lance dep that includes the runtime dispatch implementation, using the same RUSTFLAGS="-C target-cpu=x86-64-v2" flags this PR uses in CI:

$ RUSTFLAGS="-C target-cpu=x86-64-v2" maturin build --release
$ pip install ./target/wheels/lancedb-*.whl
$ python verify.py
PASS: import + simd dispatch + table create + vector search all work.

Pre-fix on the same CPU (default pip install lancedb): Illegal instruction (core dumped). Full reproducer (deps + clone + build + verification): https://gist.github.com/tobocop2/2e341358b55c143527416edfdb1e37df. Fork-internal verification PR with the dep bump and full logs: tobocop2/lancedb#2.

Benchmarks — no regressions on modern CPUs from the lance-side change

These are the numbers I ran for the lance PR, confirming the runtime dispatch doesn't slow down the default (target-cpu=haswell) wheel that existing users install. Criterion, one machine, one session, base → PR, no RUSTFLAGS override. Full methodology, null experiments, and logs: lance-format/lance#6630 benchmark comment and the logs gist.

benchmark EPYC 7B13 (avx2, fma, no avx512f) Xeon Cascade Lake (avx512f)
Cosine(f32, scalar) (control) +0.04% +0.09%
Cosine(f64, scalar) −0.34% −1.94%
Cosine(u8, SIMD) +2.30% +3.63%
Dot(f16, SIMD) −0.58% +0.61%
Dot(f32, SIMD) +0.34% −6.08%
Dot(f32, arrow_arity) +0.02% −0.00%
L2(f32, scalar) −0.10% −0.02%
L2(f32, simd) (dim 1024) +2.63% −0.53%
L2(simd,f32x8) (dim 8) −45.9% −25.1%
L2(u8, SIMD) +0.42% −3.11%
NormL2(f32, SIMD) −1.02% −4.17%
NormL2(f64, SIMD) +3.51% −0.58%

Nothing regresses beyond the noise floor. Dim 8 — the PQ sub-vector width — improves 25–46%.


To be transparent: this isn't my domain of expertise and the lance-side implementation is AI-generated. I verified it works end-to-end on the failing hardware. Happy to roll in feedback.

@github-actions github-actions Bot added enhancement New feature or request Python Python SDK labels Apr 28, 2026
@tobocop2
tobocop2 force-pushed the upstream/document-pre-haswell-build branch from 5bee0e4 to 778c15a Compare April 28, 2026 05:01
The default lancedb wheel targets target-cpu=haswell (AVX2 + FMA + F16C)
and SIGILLs at import on pre-Haswell silicon (Sandy Bridge / Ivy Bridge /
Westmere on Intel; Bulldozer / Piledriver / Steamroller on AMD). Per
westonpace's review on lancedb#3324 (fast by default, extra steps to work on
legacy), the default wheel baseline stays fast for modern users;
pre-Haswell users get a separately-published 'lancedb-compat' wheel.

Adds a 'lancedb-compat' matrix entry to pypi-publish.yml that builds
with RUSTFLAGS=-C target-cpu=x86-64-v2 (Nehalem-class baseline). The
compat wheel relies on runtime SIMD dispatch in the embedded lance crate
(landing via lance-format/lance#6630) to pick the appropriate kernel
tier at load time, so it still goes fast on modern hardware.

Generalizes build_linux_wheel and upload_wheel composites with optional
package-name and rustflags inputs (defaults preserve current behavior
for the existing 4 lancedb matrix entries). Documents the choice in
python/README.md: pip install lancedb-compat for pre-Haswell hosts;
same import lancedb API.

Maintainer setup required before this can ship: register lancedb-compat
on PyPI and configure trusted publishing.

Blocked on lance-format/lance#6630.
…re-haswell-build

# Conflicts:
#	.github/workflows/build_linux_wheel/action.yml
@tobocop2
tobocop2 marked this pull request as ready for review July 14, 2026 16:29
@tobocop2

tobocop2 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

friendly bump @wjones127 @westonpacelance-format/lance#6630 has been merged so this is now ready for review and I'm taking it out of draft.

I updated the PR description to now have the benchmarks from the lance work as well

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Comment thread .github/workflows/pypi-publish.yml Outdated
# / AVX-512) at load time. Same import as `lancedb` -- conflicts
# at install time, so users pick one.
- platform: x86_64
manylinux: "2_17"

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.

suggestion: we dropped support for 2_17, as have most projects. Can we use 2_28 instead? (Might need to change the name of the job too to prevent collisions.) The purposes of this is to support outdated hardware, not software, right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

that's right, I'll update it now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated in 2b7be76.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Also, this exposed a bug.

I updated the compat wheel artifact name. it was wheels-linux-{platform}-{manylinux}, which collides with the default.

It now includes the package name, same as the job name.

Also found an issue where beta tags would have built the compat wheel but skipped publishing it.

The compat wheel targeted manylinux 2_17, which lancedb no longer
supports. The variant exists to support outdated hardware, not outdated
glibc, so it now builds on 2_28 like the other wheels.

Since all three linux matrix entries are now x86_64/aarch64 on 2_28, the
job name and wheel artifact name no longer uniquely identify an entry.
Both now include the package name.

Also widen the Fury upload glob, which matched lancedb-*.whl and so
would have skipped the compat wheel -- its distribution filename
normalizes to lancedb_compat-*.whl.
@tobocop2
tobocop2 marked this pull request as draft July 14, 2026 21:42
The rustflags input was interpolated unconditionally into docker-options,
which broke both wheels.

For the default lancedb builds the input is empty, so the container got
'-e RUSTFLAGS='. Cargo treats RUSTFLAGS as an override whenever it is set --
even to the empty string -- so it discarded the per-target rustflags in
.cargo/config.toml and silently dropped -Ctarget-cpu=haswell and
+avx2,+fma,+f16c from the released x86_64 wheel. The same input default made
this true of the CI wheel built by python.yml.

For the compat build the value contained a space. maturin-action argv-splits
docker-options (string-argv), so '-e RUSTFLAGS=-C target-cpu=x86-64-v2' tore
into 'RUSTFLAGS=-C' plus a stray 'target-cpu=x86-64-v2' argument to docker run.

The '-e RUSTFLAGS=...' argument is now emitted only when the input is
non-empty, and the value is a single whitespace-free token.
@tobocop2

tobocop2 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

One thing here needs maintainer setup: lancedb-compat needs a PyPI trusted publisher before the first release tag after this lands: a pending publisher

Without it the tag publishes the lancedb wheels normally and then 403s on the compat wheel: a red release job, nothing broken for users. Fury needs nothing extra.

I also fixed a bug of my own in 7277917: the empty rustflags default was reaching the container as -e RUSTFLAGS=, and cargo treats RUSTFLAGS as an override even when it is empty, so it was quietly dropping -Ctarget-cpu=haswell from the defaul wheel. It is now only set when non-empty, so the stock wheels build exactly as they do on main.

@tobocop2
tobocop2 marked this pull request as ready for review July 14, 2026 21:48
@tobocop2
tobocop2 requested a review from wjones127 July 14, 2026 22:11
@wjones127
wjones127 merged commit 7b6ee0d into lancedb:main Jul 16, 2026
20 checks passed
@mintlify

mintlify Bot commented Jul 16, 2026

Copy link
Copy Markdown

Docs PR opened: lancedb/docs#311

Added a Quickstart section explaining when and how to install the new lancedb-compat wheel on pre-Haswell x86_64 CPUs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Python Python SDK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants