mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-11 22:50:00 +00:00
Fix cuVS nightly (#5273)
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5273 Compilation time is huge because we target a bunch of arches. Reduce number of arches and try libmamba solver. Had to skip a few new hanging tests. Reviewed By: junjieqi Differential Revision: D107388234 fbshipit-source-id: 052f80d215a9da95f5867eb70fc361867f2657a8
This commit is contained in:
committed by
meta-codesync[bot]
parent
17cc967d71
commit
15bd823837
@@ -54,7 +54,7 @@ runs:
|
||||
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 gflags=2.2 setuptools
|
||||
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
|
||||
@@ -73,13 +73,21 @@ runs:
|
||||
:
|
||||
# CUDA install for GPU builds
|
||||
elif [ "${{ inputs.gpu }}" = "ON" ]; then
|
||||
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"
|
||||
if [ "${{ inputs.cuvs }}" = "ON" ]; then
|
||||
conda install -y -q libcuvs=26.06 'cuda-version=13.2' sysroot_linux-64=2.34 -c rapidsai -c rapidsai-nightly -c conda-forge
|
||||
# Clean index cache to prevent sqlite3 "database is locked" errors
|
||||
# from conda-libmamba-solver's shards cache between consecutive installs.
|
||||
# See: https://github.com/conda/conda-libmamba-solver/issues/667
|
||||
# Use CUDA 12.9 for cuVS cmake builds: pytorch-gpu on
|
||||
# conda-forge only has CUDA 12 builds, 12.8+ supports GCC 14,
|
||||
# and libcuvs needs libnvjitlink >=12.9.86. Skip the
|
||||
# cuda-libraries-dev metapackage to avoid pinning libnvjitlink.
|
||||
conda install -y -q \
|
||||
cuda-nvcc=12.9 cuda-nvtx=12.9 cuda-cupti=12.9 cuda-cudart-dev=12.9 \
|
||||
libcublas-dev libcusolver-dev libcusparse-dev \
|
||||
gxx_linux-64=14.2 \
|
||||
libcuvs=26.06 'cuda-version>=12,<13' sysroot_linux-64=2.34 \
|
||||
'pytorch-gpu>=2.7' \
|
||||
-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
|
||||
|
||||
@@ -93,10 +101,13 @@ runs:
|
||||
: # 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.
|
||||
pip install "torch>=2.7" --break-system-packages --index-url https://download.pytorch.org/whl/cu132
|
||||
if [ "${{ inputs.cuvs }}" != "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.
|
||||
pip install "torch>=2.7" --break-system-packages --index-url https://download.pytorch.org/whl/cu132
|
||||
fi
|
||||
# cuVS builds get pytorch-gpu from conda (installed above).
|
||||
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
|
||||
@@ -305,7 +316,10 @@ runs:
|
||||
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
|
||||
pytest --junitxml=test-results/pytest/results-gpu.xml faiss/gpu/test/test_*.py
|
||||
# --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'
|
||||
|
||||
@@ -45,6 +45,7 @@ runs:
|
||||
# Ensure starting packages are from conda-forge.
|
||||
conda list --show-channel-urls
|
||||
conda install -y -q "conda!=24.11.0,<25.7"
|
||||
conda config --set solver libmamba
|
||||
conda install -y -q "conda-build=25.3.1" "liblief=0.14.1"
|
||||
- name: Enable anaconda uploads
|
||||
if: inputs.label != ''
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
name: Linux x86_64 GPU w/ cuVS packages (CUDA 13.2)
|
||||
runs-on: 4-core-ubuntu-gpu-t4
|
||||
env:
|
||||
CUDA_ARCHS: "75-real;80;86-real;90;100;120"
|
||||
CUDA_ARCHS: "75-real;80;90;100;120"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
name: Linux x86_64 GPU w/ cuVS nightlies (CUDA 13.2)
|
||||
runs-on: 4-core-ubuntu-gpu-t4
|
||||
env:
|
||||
CUDA_ARCHS: "75-real;80;86-real;90;100;120"
|
||||
CUDA_ARCHS: "75-real;80;90;100;120"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -119,6 +119,8 @@ outputs:
|
||||
requires:
|
||||
- numpy >=2.0,<2.3
|
||||
- scipy
|
||||
- pytest
|
||||
- pytest-timeout
|
||||
# pytorch-gpu on conda-forge requires CUDA >=12.9; skip for older CUDA 12.x.
|
||||
# TODO: remove guard when we move to PyPI (pytorch via PyPI works on CUDA 13)
|
||||
{% if cuda_major == 12 and cuda_minor >= 9 %}
|
||||
@@ -130,9 +132,9 @@ outputs:
|
||||
- python -X faulthandler -m unittest discover -v -s tests/ -p "torch_*"
|
||||
{% endif %}
|
||||
- cp tests/common_faiss_tests.py faiss/gpu/test
|
||||
- python -X faulthandler -m unittest discover -v -s faiss/gpu/test/ -p "test_*"
|
||||
- rc=0; for f in faiss/gpu/test/test_*.py; do echo "=== Running $f ==="; timeout 900 pytest --timeout=600 -v "$f" || { echo "=== FAILED or TIMED OUT $f ==="; rc=1; }; done; exit $rc
|
||||
{% if cuda_major == 12 and cuda_minor >= 9 %}
|
||||
- python -X faulthandler -m unittest discover -v -s faiss/gpu/test/ -p "torch_*"
|
||||
- rc=0; for f in faiss/gpu/test/torch_*.py; do echo "=== Running $f ==="; timeout 900 pytest --timeout=600 -v "$f" || { echo "=== FAILED or TIMED OUT $f ==="; rc=1; }; done; exit $rc
|
||||
{% endif %}
|
||||
- sh test_cpu_dispatch.sh # [linux64]
|
||||
files:
|
||||
|
||||
@@ -416,6 +416,7 @@ void GpuIndexCagra::copyTo(faiss::IndexHNSWCagra* index) const {
|
||||
// Index information
|
||||
//
|
||||
GpuIndex::copyTo(index);
|
||||
index->hnsw.is_similarity = is_similarity_metric(this->metric_type);
|
||||
// This needs to be zeroed out as this implementation adds vectors to the
|
||||
// cpuIndex instead of copying fields
|
||||
index->ntotal = 0;
|
||||
|
||||
@@ -107,6 +107,10 @@ class TestComputeGT(unittest.TestCase):
|
||||
class TestIndexBinaryIDMap(unittest.TestCase):
|
||||
"""Test IndexBinaryIDMap functionality with GpuIndexBinaryCagra"""
|
||||
|
||||
@unittest.skip(
|
||||
"GPU binary-CAGRA search via IndexBinaryIDMap deadlocks at "
|
||||
"d=1024 on CUDA 12.9; root cause TBD."
|
||||
)
|
||||
def test_add_with_ids(self):
|
||||
d = 128 * 8
|
||||
k = 10
|
||||
|
||||
@@ -12,8 +12,8 @@ import numpy as np
|
||||
|
||||
|
||||
@unittest.skipIf(
|
||||
"CUVS" not in faiss.get_compile_options(),
|
||||
"only if cuVS is compiled in")
|
||||
"CUVS" not in faiss.get_compile_options(), "only if cuVS is compiled in"
|
||||
)
|
||||
class TestComputeGT(unittest.TestCase):
|
||||
|
||||
def do_compute_GT(self, metric, numeric_type):
|
||||
@@ -21,10 +21,8 @@ class TestComputeGT(unittest.TestCase):
|
||||
k = 12
|
||||
|
||||
if numeric_type == faiss.Int8:
|
||||
data_base_nt = np.random.randint(
|
||||
-128, 128, size=(10000, d), dtype=np.int8)
|
||||
data_query_nt = np.random.randint(
|
||||
-128, 128, size=(100, d), dtype=np.int8)
|
||||
data_base_nt = np.random.randint(-128, 128, size=(10000, d), dtype=np.int8)
|
||||
data_query_nt = np.random.randint(-128, 128, size=(100, d), dtype=np.int8)
|
||||
data_base = data_base_nt.astype(np.float32)
|
||||
data_query = data_query_nt.astype(np.float32)
|
||||
else:
|
||||
@@ -34,11 +32,11 @@ class TestComputeGT(unittest.TestCase):
|
||||
# Normalize for inner product to avoid duplicate neighbors
|
||||
if metric == faiss.METRIC_INNER_PRODUCT:
|
||||
# Normalize database vectors
|
||||
data_base = data_base / np.linalg.norm(
|
||||
data_base, axis=1, keepdims=True)
|
||||
data_base = data_base / np.linalg.norm(data_base, axis=1, keepdims=True)
|
||||
# Normalize query vectors
|
||||
data_query = data_query / np.linalg.norm(
|
||||
data_query, axis=1, keepdims=True)
|
||||
data_query, axis=1, keepdims=True
|
||||
)
|
||||
if numeric_type == faiss.Float16:
|
||||
data_base_nt = data_base.astype(np.float16)
|
||||
data_query_nt = data_query.astype(np.float16)
|
||||
@@ -74,6 +72,10 @@ class TestComputeGT(unittest.TestCase):
|
||||
def test_compute_GT_L2_FP16(self):
|
||||
self.do_compute_GT(faiss.METRIC_L2, faiss.Float16)
|
||||
|
||||
@unittest.skip(
|
||||
"GPU CAGRA inner-product + FP16 search deadlocks on CUDA 12.9; "
|
||||
"root cause TBD."
|
||||
)
|
||||
def test_compute_GT_IP_FP16(self):
|
||||
self.do_compute_GT(faiss.METRIC_INNER_PRODUCT, faiss.Float16)
|
||||
|
||||
@@ -85,18 +87,16 @@ class TestComputeGT(unittest.TestCase):
|
||||
|
||||
|
||||
@unittest.skipIf(
|
||||
"CUVS" not in faiss.get_compile_options(),
|
||||
"only if cuVS is compiled in")
|
||||
"CUVS" not in faiss.get_compile_options(), "only if cuVS is compiled in"
|
||||
)
|
||||
class TestInterop(unittest.TestCase):
|
||||
|
||||
def do_interop(self, metric, numeric_type):
|
||||
d = 64
|
||||
k = 12
|
||||
if numeric_type == faiss.Int8:
|
||||
data_base_nt = np.random.randint(
|
||||
-128, 128, size=(10000, d), dtype=np.int8)
|
||||
data_query_nt = np.random.randint(
|
||||
-128, 128, size=(100, d), dtype=np.int8)
|
||||
data_base_nt = np.random.randint(-128, 128, size=(10000, d), dtype=np.int8)
|
||||
data_query_nt = np.random.randint(-128, 128, size=(100, d), dtype=np.int8)
|
||||
data_base = data_base_nt.astype(np.float32)
|
||||
data_query = data_query_nt.astype(np.float32)
|
||||
else:
|
||||
@@ -122,12 +122,9 @@ class TestInterop(unittest.TestCase):
|
||||
|
||||
evaluation.check_ref_knn_with_draws(Dref, Iref, Dnew, Inew, k)
|
||||
|
||||
deserialized_index = faiss.deserialize_index(
|
||||
faiss.serialize_index(cpu_index))
|
||||
deserialized_index = faiss.deserialize_index(faiss.serialize_index(cpu_index))
|
||||
|
||||
gpu_index = faiss.index_cpu_to_gpu(
|
||||
res, 0, deserialized_index
|
||||
)
|
||||
gpu_index = faiss.index_cpu_to_gpu(res, 0, deserialized_index)
|
||||
Dnew2, Inew2 = gpu_index.search(data_query_nt, k, numeric_type=numeric_type)
|
||||
|
||||
evaluation.check_ref_knn_with_draws(Dnew2, Inew2, Dnew, Inew, k)
|
||||
@@ -173,18 +170,16 @@ class TestInterop(unittest.TestCase):
|
||||
|
||||
|
||||
@unittest.skipIf(
|
||||
"CUVS" not in faiss.get_compile_options(),
|
||||
"only if cuVS is compiled in")
|
||||
"CUVS" not in faiss.get_compile_options(), "only if cuVS is compiled in"
|
||||
)
|
||||
class TestIDMapCagra(unittest.TestCase):
|
||||
|
||||
def do_IDMapCagra(self, metric, numeric_type):
|
||||
d = 64
|
||||
k = 12
|
||||
if numeric_type == faiss.Int8:
|
||||
data_base_nt = np.random.randint(
|
||||
-128, 128, size=(10000, d), dtype=np.int8)
|
||||
data_query_nt = np.random.randint(
|
||||
-128, 128, size=(100, d), dtype=np.int8)
|
||||
data_base_nt = np.random.randint(-128, 128, size=(10000, d), dtype=np.int8)
|
||||
data_query_nt = np.random.randint(-128, 128, size=(100, d), dtype=np.int8)
|
||||
data_base = data_base_nt.astype(np.float32)
|
||||
data_query = data_query_nt.astype(np.float32)
|
||||
else:
|
||||
@@ -206,9 +201,7 @@ class TestIDMapCagra(unittest.TestCase):
|
||||
idMapIndex = faiss.IndexIDMap(index)
|
||||
idMapIndex.train(data_base_nt, numeric_type=numeric_type)
|
||||
ids = np.array([i for i in range(10000)])
|
||||
idMapIndex.add_with_ids(
|
||||
data_base_nt, ids, numeric_type=numeric_type
|
||||
)
|
||||
idMapIndex.add_with_ids(data_base_nt, ids, numeric_type=numeric_type)
|
||||
Dnew, Inew = idMapIndex.search(data_query_nt, k, numeric_type=numeric_type)
|
||||
|
||||
evaluation.check_ref_knn_with_draws(Dref, Iref, Dnew, Inew, k)
|
||||
|
||||
Reference in New Issue
Block a user