diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dc4fafec..0f3c3e99 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,6 +100,52 @@ jobs: BUILD_RESULT: ${{ needs.linux-wheel-build.result }} run: test "$BUILD_RESULT" = success + linux-arm64-wheel-build: + name: Linux ARM64 ${{ matrix.abi }} wheel + needs: [prepare, changes] + if: >- + !cancelled() && needs.prepare.result == 'success' && + needs.prepare.outputs.build == 'true' && + (needs.changes.result != 'success' || needs.changes.outputs.wheels == 'true') + runs-on: ubuntu-24.04-arm + timeout-minutes: 90 + strategy: + fail-fast: false + matrix: + abi: ${{ fromJSON(github.event_name == 'pull_request' && '["cp311","cp314"]' || '["cp311","cp312","cp313","cp314"]') }} + steps: + - uses: actions/checkout@v7 + with: + ref: ${{ needs.prepare.outputs.sha }} + - uses: actions/setup-python@v7 + with: + python-version: "3.14" + - name: Verify native ARM64 runner + run: test "$(uname -m)" = aarch64 + - name: Build and test repaired wheel + uses: pypa/cibuildwheel@v4.2.0 + env: + CIBW_BUILD: ${{ matrix.abi }}-manylinux_aarch64 + with: + output-dir: wheelhouse + - name: Store wheel artifact + uses: actions/upload-artifact@v7 + with: + name: linux-arm64-${{ matrix.abi }}-wheels + path: wheelhouse/*.whl + if-no-files-found: error + + linux-arm64-wheels: + name: Linux ARM64 wheels (CPython 3.11–3.14) + needs: linux-arm64-wheel-build + if: ${{ always() && !cancelled() && needs.linux-arm64-wheel-build.result != 'skipped' }} + runs-on: ubuntu-latest + steps: + - name: Require all selected wheels + env: + BUILD_RESULT: ${{ needs.linux-arm64-wheel-build.result }} + run: test "$BUILD_RESULT" = success + windows-wheel-build: name: Windows x86-64 ${{ matrix.abi }} wheel needs: [prepare, changes] @@ -193,7 +239,7 @@ jobs: release-tag: name: Create version tag - needs: [prepare, linux-wheels, windows-wheels, macos-wheels] + needs: [prepare, linux-wheels, linux-arm64-wheels, windows-wheels, macos-wheels] if: >- (github.event_name == 'push' || github.event_name == 'workflow_run') && needs.prepare.outputs.publish == 'true' @@ -222,7 +268,7 @@ jobs: if: >- (github.event_name == 'push' || github.event_name == 'workflow_run') && needs.prepare.outputs.publish == 'true' - needs: [prepare, linux-wheels, windows-wheels, macos-wheels, release-tag] + needs: [prepare, linux-wheels, linux-arm64-wheels, windows-wheels, macos-wheels, release-tag] runs-on: ubuntu-latest environment: name: pypi @@ -249,7 +295,7 @@ jobs: if: >- (github.event_name == 'push' || github.event_name == 'workflow_run') && needs.prepare.outputs.publish == 'true' - needs: [prepare, linux-wheels, windows-wheels, macos-wheels, pypi-publish] + needs: [prepare, linux-wheels, linux-arm64-wheels, windows-wheels, macos-wheels, pypi-publish] runs-on: ubuntu-latest permissions: contents: write diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f7f043cb..a77b368f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -182,6 +182,37 @@ jobs: - name: Test downstream consumer run: ctest --test-dir build-consumer --output-on-failure + linux-arm64: + name: Native Linux ARM64 C++ + needs: changes + if: ${{ !cancelled() && (needs.changes.result != 'success' || needs.changes.outputs.cpp == 'true') }} + runs-on: ubuntu-24.04-arm + timeout-minutes: 45 + env: + OMP_NUM_THREADS: "2" + steps: + - uses: actions/checkout@v7 + - name: Install build tools + run: sudo apt-get update -qq && sudo apt-get install -y cmake ninja-build + - name: Configure portable ARM64 build + run: | + test "$(uname -m)" = aarch64 + cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \ + -DRABITQ_BUILD_TESTS=ON -DRABITQ_BUILD_SAMPLES=OFF \ + -DRABITQ_ENABLE_NATIVE_OPTIMIZATION=OFF + ! grep -E -- '-mavx|_avx[25].*\.cpp' build/compile_commands.json + - name: Build and run C++ tests + run: | + cmake --build build --parallel 2 + ctest --test-dir build --output-on-failure + - name: Test installed CMake package + run: | + cmake --install build --prefix "$RUNNER_TEMP/rabitq-install" + cmake -S tests/consumer -B build-consumer -G Ninja \ + -DCMAKE_PREFIX_PATH="$RUNNER_TEMP/rabitq-install" + cmake --build build-consumer --parallel 2 + ctest --test-dir build-consumer --output-on-failure + macos-arm64: name: Native Apple Silicon C++ needs: changes diff --git a/AGENTS.md b/AGENTS.md index c055059e..22aef9fe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,7 +8,8 @@ where present. Keep this file current when the paths, commands, or contracts bel RaBitQ-Library is a C++17 library with Python bindings (`rabitqlib`) for compact vector quantization and approximate nearest-neighbor search. It provides one-bit and multi-bit RaBitQ encoding and IVF, HNSW, and SymphonyQG indexes. It targets x86-64 with runtime AVX2/AVX-512 -dispatch and macOS ARM64 with NEON and portable scalar kernels. Linux AArch64 requires separate platform validation. +dispatch and Linux/macOS ARM64 with NEON and portable scalar kernels. Native Linux AArch64 +C++ and installed-wheel CI validate that platform. RaBitQ rotates vectors and quantizes residuals relative to centroids; compact codes and correction factors estimate L2 distance or inner product. diff --git a/CMakeLists.txt b/CMakeLists.txt index 3664b3ae..d39a376e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) -project(RaBitQLib VERSION 0.3.9 LANGUAGES CXX) +project(RaBitQLib VERSION 0.3.10 LANGUAGES CXX) include(CMakePackageConfigHelpers) include(GNUInstallDirs) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 405692d1..efe9f676 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -317,9 +317,9 @@ covers its arithmetic kernels, not every scalar loop in construction and search. Portable wheels disable `RABITQ_ENABLE_NATIVE_OPTIMIZATION`. ARM64 builds exclude all x86 source groups and use standard AArch64 NEON intrinsics, without Apple-only APIs. -macOS ARM64 has native C++ and installed-wheel CI. Linux ARM64 still requires separate -platform verification. The reference suites also exercise portable scalar kernels on x86, including -byte-for-byte packing parity with the selected x86 backend. +macOS and Linux ARM64 have native C++ and installed-wheel CI. The reference suites +also exercise portable scalar kernels on x86, including byte-for-byte packing parity +with the selected x86 backend. ### Change quantization or packing diff --git a/README.md b/README.md index 7d0fcfe1..5f2f6c1e 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,10 @@ ## News +- **September 2026 — Linux ARM64 support:** Native AArch64 C++ tests and + CPython 3.11–3.14 wheel builds cover NEON kernels and all three indexes. + See the [platform requirements](docs/docs/quick_start.md#requirements). + - **September 2026 — Apple Silicon support:** macOS ARM64 joins Linux and Windows x86-64, with NEON kernels and CPython 3.11–3.14 wheel builds for macOS 14+. See the [platform requirements](docs/docs/quick_start.md#requirements). @@ -58,10 +62,12 @@ python -m pip install --upgrade rabitqlib ``` -Wheels: CPython 3.11–3.14 on Linux and Windows x86-64, and macOS 14+ ARM64 -(Apple Silicon). x86-64 uses AVX2/FMA with optional AVX-512 acceleration; -ARM64 uses NEON and portable scalar kernels. macOS wheels bundle OpenMP; -Intel Mac and universal2 wheels are not provided. +Wheels: CPython 3.11–3.14 on Linux x86-64 and ARM64, Windows x86-64, and +macOS 14+ ARM64 (Apple Silicon). x86-64 uses AVX2/FMA with optional AVX-512 +acceleration; ARM64 uses NEON and portable scalar kernels. Linux ARM64 and +macOS wheels bundle OpenMP. Linux ARM64 wheels use a `manylinux_2_28` build +image; check each wheel's tags for its glibc compatibility. Intel Mac and +universal2 wheels are not provided. ## Python quick start @@ -237,7 +243,7 @@ and HNSW implementations, with links to the source code. - CMake 3.20 or newer - a C++17 compiler with OpenMP support -- an x86-64 CPU with AVX2 and FMA, or an Apple Silicon Mac +- an x86-64 CPU with AVX2 and FMA, or an ARM64 CPU on Linux or macOS Clone and build the library and example programs: @@ -250,9 +256,8 @@ cmake --build build --parallel ``` For MSVC, follow the [Windows build instructions](tests/README.md#prerequisites). -For Apple Silicon source builds, see the [macOS ARM64 instructions](tests/README.md#macos-arm64). -The ARM kernel sources use portable AArch64 intrinsics, but macOS tests do not -establish Linux ARM64 support. +For ARM64 source builds, see the [Linux ARM64](tests/README.md#linux-arm64) +and [macOS ARM64](tests/README.md#macos-arm64) instructions. Local GCC/Clang builds enable `-march=native` by default; set `-DRABITQ_ENABLE_NATIVE_OPTIMIZATION=OFF` for portable binaries, as release wheels do. See [CPU dispatch details](DEVELOPMENT.md#dispatch-conventions-and-coverage) diff --git a/docs/docs/index.md b/docs/docs/index.md index 7ecf087f..88ea6395 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -6,7 +6,8 @@ accurate vector quantization and approximate nearest-neighbor search. Build with the low-level quantizer or use complete IVF, HNSW, and SymphonyQG -indexes on Linux and Windows x86-64, or macOS ARM64 (Apple Silicon). +indexes on Linux x86-64 and ARM64, Windows x86-64, or macOS ARM64 +(Apple Silicon). [Get started](quick_start.md){ .md-button .md-button--primary } [View on GitHub](https://github.com/VectorDB-NTU/RaBitQ-Library){ .md-button } @@ -23,7 +24,7 @@ indexes on Linux and Windows x86-64, or macOS ARM64 (Apple Silicon).
Use AVX2/AVX-512 kernels on x86-64 and NEON on Apple Silicon. IVF and +
Use AVX2/AVX-512 kernels on x86-64 and NEON on ARM64. IVF and SymphonyQG use FastScan for batched distance estimation.