mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-12 02:13:36 +00:00
Add Metal GPU backend for Apple Silicon (IndexFlat) (#5144)
Summary: ## Summary Adds a new Metal compute backend so FAISS can run GPU-accelerated similarity search on Apple Silicon (M1/M2/M3/M4/M5). This is just an initial pr, it introduces the build system integration, core Metal infrastructure, and a working `IndexFlat` with L2 and inner product search. I have some follow up prs with more functionality that I plan to submit. Addresses https://github.com/facebookresearch/faiss/issues/2386 — FAISS currently has no GPU acceleration path on Apple Silicon, forcing CPU-only execution. This Metal backend enables GPU-accelerated search on M-series chips, with follow-up PRs adding IVF indexes, Python bindings, and kernel optimizations. All Metal code lives in a new `faiss/gpu_metal/` directory, keeping `faiss/gpu/` (CUDA/ROCm) completely untouched. The backend is opt-in via `cmake -DFAISS_ENABLE_METAL=ON -DFAISS_ENABLE_GPU=OFF`. ### What's included - **Build system**: New `FAISS_ENABLE_METAL` CMake option. When enabled, requires Apple platform, links Metal/MetalKit/MPS/Foundation frameworks, and builds `libfaiss_metal.a`. Three small additions to root `CMakeLists.txt`. - **MetalResources**: Owns `MTLDevice`, `MTLCommandQueue`, and buffer allocation/deallocation. Mirrors `GpuResources` roles. - **MetalIndex**: Base class for Metal-backed indexes (mirrors `GpuIndex`). Single-device only (device 0). - **MetalIndexFlat**: Flat index storing vectors in an `MTLBuffer`. Supports `add`, `add_with_ids`, `reset`, `search` for both `METRIC_L2` and `METRIC_INNER_PRODUCT`. - **MSL compute kernels**: `l2_squared_matrix`, `ip_matrix` (distance computation), and `topk` (sorted insertion, k ≤ 256). Embedded as a compile-time string in `MetalFlatKernels.mm`. - **Backend abstraction**: `get_num_gpus()`, `index_cpu_to_metal_gpu()`, `index_metal_gpu_to_cpu()`, `StandardMetalResources`, and a `GpuIndexFlat` typedef for API parity. - **Tests**: 8 gtest cases in `TestMetalIndexFlat.mm` — L2/IP search correctness vs CPU `IndexFlat`, `add_with_ids`, reset, empty search, `get_num_gpus`, and CPU↔Metal cloning in both directions. All tests skip gracefully if no Metal device is available. - Python/SWIG bindings ### Planned follow up prs - Larger k support (tiling, heap-based top-k) - IVFFlat, IVFPQ, IVFSQ, BinaryFlat - Kernel optimizations (fused distance+top-k, GEMM-tiled distance, simdgroup/threadgroup parallel selection) ### Build and test ```bash mkdir -p build_metal && cd build_metal cmake .. -DFAISS_ENABLE_METAL=ON -DFAISS_ENABLE_GPU=OFF \ -DBUILD_TESTING=ON -DFAISS_ENABLE_PYTHON=OFF \ -DCMAKE_PREFIX_PATH="/opt/homebrew/opt/libomp;/opt/homebrew" cmake --build . --target faiss_metal TestMetalIndexFlat ctest -R TestMetalIndexFlat ``` > The `mkdir -p` avoids the error if the directory exists, and `-DFAISS_ENABLE_PYTHON=OFF` skips the Python dependency that isn't needed for this PR. Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5144 Reviewed By: alibeklfc Differential Revision: D102284936 Pulled By: mnorris11 fbshipit-source-id: 812fc6ceae251b7b33d25f6861fc37b8d7b475c1
This commit is contained in:
committed by
meta-codesync[bot]
parent
17fd3332c7
commit
66cea52433
@@ -20,6 +20,10 @@ inputs:
|
||||
description: 'Enable SVS support.'
|
||||
required: false
|
||||
default: OFF
|
||||
metal:
|
||||
description: 'Enable Metal GPU backend (macOS Apple Silicon).'
|
||||
required: false
|
||||
default: OFF
|
||||
setup_conda:
|
||||
description: 'Setup miniconda environment.'
|
||||
required: false
|
||||
@@ -32,7 +36,7 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Setup miniconda
|
||||
if: inputs.setup_conda == 'true'
|
||||
if: inputs.setup_conda == 'true' && inputs.metal != 'ON'
|
||||
uses: conda-incubator/setup-miniconda@v3
|
||||
with:
|
||||
python-version: '3.12'
|
||||
@@ -43,6 +47,7 @@ runs:
|
||||
# They are the same thing, just named differently.
|
||||
architecture: ${{ runner.arch == 'ARM64' && 'aarch64' || runner.arch }}
|
||||
- name: Configure build environment
|
||||
if: inputs.metal != 'ON'
|
||||
shell: bash
|
||||
run: |
|
||||
# initialize Conda
|
||||
@@ -165,7 +170,12 @@ runs:
|
||||
key: ${{ runner.os }}-${{ runner.arch }}-${{ inputs.opt_level }}-gpu${{ inputs.gpu }}-cuvs${{ inputs.cuvs }}-rocm${{ inputs.rocm }}-svs${{ inputs.svs }}
|
||||
max-size: 2G
|
||||
update-package-index: true
|
||||
- name: Setup macOS Metal environment
|
||||
if: inputs.metal == 'ON'
|
||||
shell: bash
|
||||
run: brew install cmake libomp gflags
|
||||
- name: Build all targets
|
||||
if: inputs.metal != 'ON'
|
||||
shell: bash
|
||||
run: |
|
||||
eval "$(conda shell.bash hook)"
|
||||
@@ -189,19 +199,38 @@ runs:
|
||||
-DCMAKE_CUDA_FLAGS=${{ runner.arch == 'X64' && '"-gencode arch=compute_75,code=sm_75"' || '' }} \
|
||||
.
|
||||
make -k -C build -j$(nproc)
|
||||
- name: Build Metal targets
|
||||
if: inputs.metal == 'ON'
|
||||
shell: bash
|
||||
run: |
|
||||
cmake -B build \
|
||||
-DFAISS_ENABLE_METAL=ON \
|
||||
-DFAISS_ENABLE_GPU=OFF \
|
||||
-DFAISS_ENABLE_PYTHON=OFF \
|
||||
-DBUILD_TESTING=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH="$(brew --prefix libomp)" \
|
||||
.
|
||||
cmake --build build --target faiss_metal TestMetalIndexFlat -j$(sysctl -n hw.logicalcpu)
|
||||
- name: C++ tests
|
||||
if: inputs.metal != 'ON'
|
||||
shell: bash
|
||||
run: |
|
||||
conda list --show-channel-urls
|
||||
export GTEST_OUTPUT="xml:$(realpath .)/test-results/googletest/"
|
||||
make -C build test
|
||||
- name: C++ tests (Metal)
|
||||
if: inputs.metal == 'ON'
|
||||
shell: bash
|
||||
run: cd build && ctest -R TestMetalIndexFlat --output-on-failure
|
||||
- name: C++ perf benchmarks
|
||||
if: inputs.rocm == 'OFF' && inputs.metal != 'ON'
|
||||
shell: bash
|
||||
if: inputs.rocm == 'OFF'
|
||||
run: |
|
||||
conda list --show-channel-urls
|
||||
find ./build/perf_tests/ -executable -type f -name "bench*" -exec '{}' -v \;
|
||||
- name: Install Python extension
|
||||
if: inputs.metal != 'ON'
|
||||
shell: bash
|
||||
working-directory: build/faiss/python
|
||||
run: |
|
||||
@@ -214,7 +243,7 @@ runs:
|
||||
conda list --show-channel-urls
|
||||
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.1
|
||||
- name: Python tests (CPU only)
|
||||
if: inputs.gpu == 'OFF'
|
||||
if: inputs.gpu == 'OFF' && inputs.metal != 'ON'
|
||||
shell: bash
|
||||
run: |
|
||||
conda list --show-channel-urls
|
||||
@@ -244,6 +273,7 @@ runs:
|
||||
name: test-results-arch=${{ runner.arch }}-opt=${{ inputs.opt_level }}-gpu=${{ inputs.gpu }}-cuvs=${{ inputs.cuvs }}-rocm=${{ inputs.rocm }}-svs=${{ inputs.svs }}
|
||||
path: test-results
|
||||
- name: Check installed packages channel
|
||||
if: inputs.metal != 'ON'
|
||||
shell: bash
|
||||
run: |
|
||||
# Shows that all installed packages are from conda-forge.
|
||||
|
||||
@@ -131,6 +131,19 @@ jobs:
|
||||
with:
|
||||
gpu: ON
|
||||
cuvs: ON
|
||||
macos-arm64-Metal-cmake:
|
||||
name: macOS arm64 Metal (cmake)
|
||||
needs: linux-x86_64-cmake
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Build and Test (cmake)
|
||||
uses: ./.github/actions/build_cmake
|
||||
with:
|
||||
metal: ON
|
||||
setup_conda: 'false'
|
||||
upload_artifacts: 'false'
|
||||
linux-arm64-SVE-cmake:
|
||||
name: Linux arm64 SVE (cmake)
|
||||
needs: linux-x86_64-cmake
|
||||
|
||||
Reference in New Issue
Block a user