mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-11 22:50:00 +00:00
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5401 `faiss/gpu/test/test_gpu_index_serialize.py` was timing out (10 min hard cap) on the GitHub `Linux x86_64 GPU w/ cuVS (cmake)` job, hanging inside `index_cpu_to_gpu` on the first cuVS GPU operation. Root cause: D106837134 bumped the conda cuVS toolkit from CUDA 12.9 to 13.3. The 13.3 `cudart` deadlocks cuVS GPU kernels on the T4 runner. The change's stated intent was only to pull `libnvJitLink` up to 13.3 — the conda `libcuvs=26.06` build links it and needs the `__nvJitLinkCreate_13_3` symbol — but `cuda-nvcc`, `cuda-cudart-dev`, `cuda-cupti`, and `cuda-nvtx` were bumped to 13.3 alongside it. CUDA 13.2 is already the version used by both the non-cuVS GPU job and the pip-wheel cuVS build (whose GPU smoke test passes on the same T4 runner class), and it matches the runner driver. Only `libnvJitLink` actually needs to be 13.3. Fix: pin the CUDA toolkit (`cuda-nvcc`/`cuda-cudart-dev`/`cuda-cupti`/`cuda-nvtx` and `cuda-version`) back to 13.2 for the cuVS cmake build, keeping the explicit `libnvjitlink>=13.3,<14` pin so `libcuvs` still loads. passed in https://github.com/facebookresearch/faiss/actions/runs/29109874975/job/86419354334?pr=5401 Reviewed By: alibeklfc Differential Revision: D111466548 fbshipit-source-id: 6eef20488605981f2326aaa2fb628b3315b9ed75
360 lines
16 KiB
YAML
360 lines
16 KiB
YAML
name: Build cmake
|
|
inputs:
|
|
opt_level:
|
|
description: 'Compile options / optimization level.'
|
|
required: false
|
|
default: generic
|
|
gpu:
|
|
description: 'Enable GPU support.'
|
|
required: false
|
|
default: OFF
|
|
cuvs:
|
|
description: 'Enable cuVS support.'
|
|
required: false
|
|
default: OFF
|
|
rocm:
|
|
description: 'Enable ROCm support.'
|
|
required: false
|
|
default: OFF
|
|
svs:
|
|
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
|
|
default: 'true'
|
|
upload_artifacts:
|
|
description: 'Upload test artifacts. Prevents collisions when multiple jobs need to run build_cmake.'
|
|
required: false
|
|
default: 'true'
|
|
runs:
|
|
using: composite
|
|
steps:
|
|
- name: Setup miniconda
|
|
if: inputs.setup_conda == 'true' && inputs.metal != 'ON'
|
|
uses: conda-incubator/setup-miniconda@v3
|
|
with:
|
|
python-version: '3.12'
|
|
miniforge-version: latest
|
|
channels: conda-forge
|
|
conda-remove-defaults: 'true'
|
|
# Set to aarch64 if we're on arm64 because there's no miniforge ARM64 package, just aarch64.
|
|
# 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: |
|
|
# Ensure starting packages are from conda-forge.
|
|
conda list --show-channel-urls
|
|
echo "$CONDA/bin" >> $GITHUB_PATH
|
|
|
|
conda install -y -q python=3.12 cmake=3.30.4 make=4.2 swig=4.0 "numpy>=2.0,<3.0" scipy=1.16 pytest=7.4 pytest-timeout gflags=2.2 setuptools
|
|
|
|
# install base packages for ARM64
|
|
if [ "${{ runner.arch }}" = "ARM64" ]; then
|
|
conda install -y -q -c conda-forge openblas=0.3.33 gxx_linux-aarch64=14.2 sysroot_linux-aarch64=2.17
|
|
fi
|
|
|
|
# install base packages for X86_64
|
|
if [ "${{ runner.arch }}" = "X64" ]; then
|
|
# TODO: merge this with ARM64
|
|
conda install -y -q -c conda-forge gxx_linux-64=14.2 sysroot_linux-64=2.17
|
|
conda install -y -q mkl=2024.2.2 mkl-devel=2024.2.2
|
|
fi
|
|
|
|
# no CUDA needed for ROCm so skip this
|
|
if [ "${{ inputs.rocm }}" = "ON" ]; then
|
|
:
|
|
# CUDA install for GPU builds
|
|
elif [ "${{ inputs.gpu }}" = "ON" ]; then
|
|
if [ "${{ inputs.cuvs }}" = "ON" ]; then
|
|
# Pin the CUDA toolkit (nvcc + cudart/cupti/nvtx) to 13.2, not 13.3:
|
|
# the 13.3 cudart deadlocks cuVS GPU kernels on the T4 runner (the
|
|
# first cuVS op in index_cpu_to_gpu hangs, timing out
|
|
# test_gpu_index_serialize). CUDA 13.2 matches both the non-cuVS GPU
|
|
# job and the pip-wheel cuVS build (whose GPU smoke test passes), and
|
|
# the T4 driver. Only libnvJitLink must be 13.3: the conda libcuvs
|
|
# 26.06 build links it (needs the __nvJitLinkCreate_13_3 symbol), and
|
|
# it is a standalone package that cuda-nvcc / cuda-cudart-dev /
|
|
# cuda-version do NOT pull to 13.3, so pin it explicitly — otherwise
|
|
# an older libnvJitLink.so.13 is left in the env and libcuvs fails to
|
|
# load at import. PyTorch via pip supports cu132, avoiding the
|
|
# conda-forge pytorch-gpu CUDA-12 limit.
|
|
conda install -y -q \
|
|
cuda-nvcc=13.2 cuda-nvtx=13.2 cuda-cupti=13.2 cuda-cudart-dev=13.2 \
|
|
'libnvjitlink>=13.3,<14' \
|
|
libcublas-dev libcusolver-dev libcusparse-dev \
|
|
gxx_linux-64=14.2 \
|
|
libcuvs=26.06 'cuda-version>=13.2,<14' sysroot_linux-64=2.34 \
|
|
-c rapidsai -c rapidsai-nightly -c conda-forge -c nvidia
|
|
conda clean --index-cache 2>/dev/null || true
|
|
else
|
|
conda install -y -q cuda-libraries-dev=13.2 cuda-nvcc=13.2 cuda-nvtx=13.2 cuda-cupti=13.2 cuda-cudart-dev=13.2 gxx_linux-64=14.2 -c "nvidia/label/cuda-13.2"
|
|
fi
|
|
fi
|
|
|
|
# install SVS runtime for SVS builds
|
|
if [ "${{ inputs.svs }}" = "ON" ]; then
|
|
conda install -y -q libsvs-runtime=0.4.0 -c conda-forge
|
|
fi
|
|
|
|
# install test packages
|
|
if [ "${{ inputs.rocm }}" = "ON" ]; then
|
|
: # skip torch install via conda, we need to install via pip to get
|
|
# ROCm-enabled version until it's supported in conda by PyTorch
|
|
elif [ "${{ inputs.gpu }}" = "ON" ]; then
|
|
# PyTorch deprecated its official Anaconda channel (pytorch/pytorch#138506),
|
|
# so we install via pip for CUDA builds. --break-system-packages is needed
|
|
# because the CI runner's Python is PEP 668 externally-managed.
|
|
# Use cu132 wheels for both cuVS and non-cuVS paths now that cuVS builds
|
|
# use CUDA 13.2 toolkit.
|
|
pip install "torch>=2.7" --break-system-packages --index-url https://download.pytorch.org/whl/cu132
|
|
# cuVS builds previously got pytorch-gpu from conda, now unified to pip.
|
|
# torch's cu132 wheels bundle a CUDA 13.2 nvidia-nvjitlink; when torch is
|
|
# imported it dlopens that libnvJitLink.so.13 RTLD_GLOBAL and shadows the
|
|
# conda 13.3 lib that cuVS 26.06 needs, so faiss then fails to load with
|
|
# "undefined symbol __nvJitLinkCreate_13_3". No torch cu133 build exists,
|
|
# so upgrade the pip nvjitlink to 13.3 (symbol-complete, CUDA-13 forward
|
|
# compatible). cuVS-only: the non-cuVS GPU path does not use libcuvs.
|
|
if [ "${{ inputs.cuvs }}" = "ON" ]; then
|
|
pip install --break-system-packages --upgrade "nvidia-nvjitlink>=13.3,<14"
|
|
fi
|
|
else
|
|
# TestLowLevelIVF.IVFRQ hangs on pytorch>=2.7, so left it as <2.5 for now.
|
|
conda install -y -q "pytorch<2.5" -c pytorch
|
|
fi
|
|
- name: ROCm - Install dependencies
|
|
if: inputs.rocm == 'ON'
|
|
shell: bash
|
|
run: |
|
|
# Update repos and install kmod, wget, gpg
|
|
sudo apt-get -qq update >/dev/null
|
|
sudo apt-get -qq install -y kmod wget gpg >/dev/null
|
|
|
|
# Download, prepare, and install the package signing key
|
|
mkdir --parents --mode=0755 /etc/apt/keyrings
|
|
wget https://repo.radeon.com/rocm/rocm.gpg.key -O - | gpg --dearmor | sudo tee /etc/apt/keyrings/rocm.gpg > /dev/null
|
|
|
|
- name: Add rocm repository
|
|
if: inputs.rocm == 'ON'
|
|
shell: bash
|
|
run: |
|
|
# Get UBUNTU version name
|
|
UBUNTU_VERSION_NAME=`cat /etc/os-release | grep UBUNTU_CODENAME | awk -F= '{print $2}'`
|
|
|
|
# Set ROCm version
|
|
ROCM_VERSION="7.2"
|
|
|
|
sudo mkdir -p /etc/apt/keyrings
|
|
wget -qO /tmp/rocm.gpg.key https://repo.radeon.com/rocm/rocm.gpg.key
|
|
echo "2de99e2354646a90d9903e2a669fc4e36b02c1bbff7075c481e12d7edab2c88b /tmp/rocm.gpg.key" | sha256sum --check
|
|
|
|
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/rocm.gpg] https://repo.radeon.com/rocm/apt/${ROCM_VERSION} ${UBUNTU_VERSION_NAME} main" | sudo tee /etc/apt/sources.list.d/rocm.list
|
|
|
|
# Pin ROCm packages to avoid conflicts with other packages
|
|
sudo printf '%s\n' 'Package: *' 'Pin: release o=repo.radeon.com' 'Pin-Priority: 600' | sudo tee /etc/apt/preferences.d/rocm-pin-600 >/dev/null
|
|
|
|
sudo apt-get -qq update >/dev/null
|
|
sudo apt-get -qq install -y rocm rocm-hip-sdk rocm-dev >/dev/null
|
|
|
|
echo "/opt/rocm/bin" >> "$GITHUB_PATH"
|
|
|
|
- name: Pin BLAS/LAPACK versions
|
|
if: inputs.rocm == 'ON'
|
|
shell: bash
|
|
run: |
|
|
conda install -y \
|
|
"libblas=3.9.0=35_*" \
|
|
"libcblas=3.9.0=35_*" \
|
|
"liblapack=3.9.0=35_*"
|
|
|
|
# Fake presence of MI325X-class accelerators
|
|
echo "gfx942" | sudo tee /opt/rocm/bin/target.lst
|
|
|
|
# Cleanup
|
|
sudo apt-get -qq autoclean >/dev/null
|
|
sudo apt-get -qq clean >/dev/null
|
|
sudo rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
|
- name: Symblink system dependencies
|
|
if: inputs.rocm == 'ON'
|
|
shell: bash
|
|
run: |
|
|
# symblink system libraries for HIP compiler
|
|
sudo ln -s /lib/x86_64-linux-gnu/libc.so.6 /lib64/libc.so.6
|
|
sudo ln -s /lib/x86_64-linux-gnu/libc_nonshared.a /usr/lib64/libc_nonshared.a
|
|
sudo ln -s /usr/lib/x86_64-linux-gnu/libpthread.so.0 /lib64/libpthread.so.0
|
|
sudo ln -s $HOME/miniconda3/x86_64-conda-linux-gnu/sysroot/usr/lib64/libpthread_nonshared.a /usr/lib64/libpthread_nonshared.a
|
|
- name: Print NVIDIA GPU info
|
|
if: inputs.gpu == 'ON' && inputs.rocm != 'ON'
|
|
shell: bash
|
|
run: nvidia-smi
|
|
- name: Print AMD GPU info
|
|
if: inputs.gpu == 'ON' && inputs.rocm == 'ON'
|
|
shell: bash
|
|
run: rocm-smi
|
|
- name: Setup ccache
|
|
uses: hendrikmuhs/ccache-action@v1
|
|
with:
|
|
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 swig
|
|
pip3 install --break-system-packages numpy pytest
|
|
- name: Build all targets
|
|
if: inputs.metal != 'ON'
|
|
shell: bash
|
|
run: |
|
|
eval "$(conda shell.bash hook)"
|
|
conda activate
|
|
conda list --show-channel-urls
|
|
cmake -B build \
|
|
-DBUILD_TESTING=ON \
|
|
-DBUILD_SHARED_LIBS=ON \
|
|
-DFAISS_ENABLE_GPU=${{ inputs.gpu }} \
|
|
-DFAISS_ENABLE_CUVS=${{ inputs.cuvs }} \
|
|
-DFAISS_ENABLE_ROCM=${{ inputs.rocm }} \
|
|
-DFAISS_OPT_LEVEL=${{ inputs.opt_level }} \
|
|
-DFAISS_ENABLE_SVS=${{ inputs.svs }} \
|
|
-DFAISS_ENABLE_C_API=ON \
|
|
-DPYTHON_EXECUTABLE=$CONDA/bin/python \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
|
-DCMAKE_CUDA_COMPILER_LAUNCHER=ccache \
|
|
-DBLA_VENDOR=${{ runner.arch == 'X64' && 'Intel10_64_dyn' || '' }} \
|
|
-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=ON \
|
|
-DBUILD_TESTING=ON \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DCMAKE_PREFIX_PATH="$(brew --prefix libomp)" \
|
|
.
|
|
cmake --build build --target faiss faiss_metal swigfaiss TestMetalIndexFlat TestMetalIndexIVFFlat -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 TestMetalIndex --output-on-failure
|
|
- name: Install Python extension (Metal)
|
|
if: inputs.metal == 'ON'
|
|
shell: bash
|
|
working-directory: build/faiss/python
|
|
run: pip3 install --break-system-packages .
|
|
- name: Python tests (Metal)
|
|
if: inputs.metal == 'ON'
|
|
shell: bash
|
|
run: python3 -m pytest faiss/gpu_metal/test/test_metal_python.py -v
|
|
- name: C++ perf benchmarks
|
|
if: inputs.rocm == 'OFF' && inputs.metal != 'ON'
|
|
shell: bash
|
|
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: |
|
|
conda list --show-channel-urls
|
|
$CONDA/bin/python setup.py install
|
|
- name: ROCm - install ROCm-enabled torch via pip
|
|
if: inputs.rocm == 'ON'
|
|
shell: bash
|
|
run: |
|
|
conda list --show-channel-urls
|
|
conda install -y -q "pip<26"
|
|
|
|
# Install AMD's torch wheels built against the exact system ROCm (7.2.0,
|
|
# from apt/7.2). The PyTorch Foundation whl/rocm7.2 wheels float and bundle
|
|
# an older ROCr that lacks hsa_amd_memory_get_preferred_copy_engine (ROCr
|
|
# 1.18.0, added in ROCm 7.0.0), which collides with the system 7.2.0
|
|
# libamdhip64. Matching both sides to 7.2.0 avoids the dual-runtime
|
|
# undefined-symbol/segfault failures.
|
|
BASE="https://repo.radeon.com/rocm/manylinux/rocm-rel-7.2"
|
|
HTML="$(wget -qO- "${BASE}/")"
|
|
pick() {
|
|
printf '%s\n' "$HTML" \
|
|
| grep -oE "$1-[0-9][^\"]*rocm7\.2\.0[^\"]*cp312-cp312-linux_x86_64\.whl" \
|
|
| sort -V | tail -1
|
|
}
|
|
TORCH_WHL="$(pick torch)"
|
|
TVISION_WHL="$(pick torchvision)"
|
|
TAUDIO_WHL="$(pick torchaudio)"
|
|
echo "Selected: ${TORCH_WHL} ${TVISION_WHL} ${TAUDIO_WHL}"
|
|
if [ -z "${TORCH_WHL}" ] || [ -z "${TVISION_WHL}" ] || [ -z "${TAUDIO_WHL}" ]; then
|
|
echo "Could not locate +rocm7.2.0 cp312 wheels at ${BASE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# --no-deps avoids pulling triton/pytorch-triton-rocm (only on AMD's index,
|
|
# not PyPI); install torch's import-time deps explicitly instead.
|
|
pip3 install --no-deps \
|
|
"${BASE}/${TORCH_WHL}" "${BASE}/${TVISION_WHL}" "${BASE}/${TAUDIO_WHL}"
|
|
pip3 install numpy pillow filelock typing-extensions sympy networkx jinja2 fsspec
|
|
|
|
# Confirm torch links against ROCm 7.2 (matches the system /opt/rocm-7.2.0).
|
|
python -c "import torch; print('torch', torch.__version__, 'hip', torch.version.hip)"
|
|
- name: Python tests (CPU only)
|
|
if: inputs.gpu == 'OFF' && inputs.metal != 'ON'
|
|
shell: bash
|
|
run: |
|
|
conda list --show-channel-urls
|
|
pytest --junitxml=test-results/pytest/results.xml tests/test_*.py
|
|
pytest --junitxml=test-results/pytest/results-torch.xml tests/torch_*.py
|
|
- name: Python tests (CPU + GPU)
|
|
if: inputs.gpu == 'ON'
|
|
shell: bash
|
|
run: |
|
|
conda list --show-channel-urls
|
|
pytest --junitxml=test-results/pytest/results.xml tests/test_*.py
|
|
pytest --junitxml=test-results/pytest/results-torch.xml tests/torch_*.py
|
|
cp tests/common_faiss_tests.py faiss/gpu/test
|
|
# --timeout guards against a hung GPU test burning the full 6h CI
|
|
# budget (see the binary-CAGRA IDMap deadlock skipped in
|
|
# test_binary_cagra.py) instead of failing fast.
|
|
pytest --timeout=600 --timeout-method=thread --junitxml=test-results/pytest/results-gpu.xml faiss/gpu/test/test_*.py
|
|
pytest --junitxml=test-results/pytest/results-gpu-torch.xml faiss/gpu/test/torch_*.py
|
|
- name: Test avx2 loading
|
|
if: inputs.opt_level == 'avx2'
|
|
shell: bash
|
|
run: |
|
|
conda list --show-channel-urls
|
|
FAISS_DISABLE_CPU_FEATURES=AVX2 LD_DEBUG=libs $CONDA/bin/python -c "import faiss" 2>&1 | grep faiss.so
|
|
LD_DEBUG=libs $CONDA/bin/python -c "import faiss" 2>&1 | grep faiss_avx2.so
|
|
- name: Upload test results
|
|
if: inputs.upload_artifacts == 'true'
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
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.
|
|
conda list --show-channel-urls
|