Files
faiss/faiss/gpu_metal/CMakeLists.txt
T
Evandabest 66cea52433 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
2026-04-30 10:34:43 -07:00

47 lines
1.1 KiB
CMake

# @lint-ignore-every LICENSELINT
# Copyright (c) Meta Platforms, Inc. and its affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# Metal GPU backend for Apple Silicon.
# Only included when FAISS_ENABLE_METAL=ON and platform is Apple.
set(FAISS_METAL_SRC
MetalResources.mm
MetalIndex.mm
MetalFlatKernels.mm
MetalIndexFlat.mm
StandardMetalResources.mm
MetalCloner.mm
)
add_library(faiss_metal STATIC ${FAISS_METAL_SRC})
target_link_libraries(faiss_metal
PUBLIC
faiss
PRIVATE
"-framework Metal"
"-framework MetalKit"
"-framework MetalPerformanceShaders"
"-framework Foundation"
)
target_include_directories(faiss_metal
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/impl
${CMAKE_CURRENT_SOURCE_DIR}/utils
PRIVATE
${PROJECT_SOURCE_DIR}
)
target_compile_definitions(faiss_metal PRIVATE FAISS_METAL_ENABLED=1)
set_target_properties(faiss_metal PROPERTIES
OBJCXX_STANDARD 17
OBJCXX_STANDARD_REQUIRED ON
)