diff --git a/.github/actions/build_cmake/action.yml b/.github/actions/build_cmake/action.yml index e313d5666..358f94e3e 100644 --- a/.github/actions/build_cmake/action.yml +++ b/.github/actions/build_cmake/action.yml @@ -74,7 +74,7 @@ runs: conda install -y -q cuda-toolkit=12.6 gxx_linux-64=12.4 -c "nvidia/label/cuda-12.6" # and CUDA from cuVS channel for cuVS builds elif [ "${{ inputs.cuvs }}" = "ON" ]; then - conda install -y -q libcuvs=26.02 'cuda-version=12.9' cuda-toolkit=12.9 sysroot_linux-64=2.34 -c rapidsai -c rapidsai-nightly -c conda-forge + conda install -y -q libcuvs=25.10 'cuda-version=12.6' cuda-toolkit=12.6 gxx_linux-64=13.4.0 -c rapidsai -c rapidsai-nightly -c conda-forge fi # install SVS runtime for SVS builds @@ -87,7 +87,7 @@ 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 - conda install -y -q "pytorch>=2.7" "pytorch-gpu>=2.7" -c pytorch -c "nvidia/label/12.9" + conda install -y -q "pytorch>=2.7" "pytorch-gpu>=2.7" -c pytorch -c "nvidia/label/12.6" 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 diff --git a/INSTALL.md b/INSTALL.md index 29c430adf..ae638aea3 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -6,7 +6,7 @@ pre-release nightly builds. - The CPU-only faiss-cpu conda package is currently available on Linux (x86-64 and aarch64), OSX (arm64 only), and Windows (x86-64) - faiss-gpu, containing both CPU and GPU indices, is available on Linux (x86-64 only) for CUDA 11.4 and 12.1 -- faiss-gpu-cuvs package containing GPU indices provided by [NVIDIA cuVS](https://github.com/rapidsai/cuvs/) version 26.02, is available on Linux (x86-64 only) for CUDA 12.4. +- faiss-gpu-cuvs package containing GPU indices provided by [NVIDIA cuVS](https://github.com/rapidsai/cuvs/) version 25.10, is available on Linux (x86-64 only) for CUDA 12.4. To install the latest stable release: @@ -72,7 +72,7 @@ The optional requirements are: - for AMD GPUs: - AMD ROCm, - for using NVIDIA cuVS implementations: - - libcuvs=26.02 + - libcuvs=25.10 - for the python bindings: - python 3, - numpy, @@ -87,9 +87,9 @@ section of the wiki](https://github.com/facebookresearch/faiss/wiki/Troubleshoot The libcuvs dependency should be installed via conda: ``` -conda install -c rapidsai -c conda-forge -c nvidia libcuvs=26.02 'cuda-version=12.6' +conda install -c rapidsai -c conda-forge -c nvidia libcuvs=25.10 'cuda-version=12.6' ``` -For more ways to install cuVS 26.02, refer to the [RAPIDS Installation Guide](https://docs.rapids.ai/install). +For more ways to install cuVS 25.10, refer to the [RAPIDS Installation Guide](https://docs.rapids.ai/install). ### Building with Intel(R) SVS diff --git a/cmake/thirdparty/fetch_rapids.cmake b/cmake/thirdparty/fetch_rapids.cmake index b57634650..43d052805 100644 --- a/cmake/thirdparty/fetch_rapids.cmake +++ b/cmake/thirdparty/fetch_rapids.cmake @@ -15,11 +15,11 @@ # or implied. See the License for the specific language governing permissions and limitations under # the License. # ============================================================================= -set(RAPIDS_VERSION "26.02") +set(RAPIDS_VERSION "25.10") set(rapids-cmake-version ${RAPIDS_VERSION}) if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/FAISS_RAPIDS.cmake) - file(DOWNLOAD https://raw.githubusercontent.com/rapidsai/rapids-cmake/release/${RAPIDS_VERSION}/RAPIDS.cmake + file(DOWNLOAD https://raw.githubusercontent.com/rapidsai/rapids-cmake/branch-${RAPIDS_VERSION}/RAPIDS.cmake ${CMAKE_CURRENT_BINARY_DIR}/FAISS_RAPIDS.cmake) endif() include(${CMAKE_CURRENT_BINARY_DIR}/FAISS_RAPIDS.cmake) diff --git a/conda/faiss-gpu-cuvs/meta.yaml b/conda/faiss-gpu-cuvs/meta.yaml index 7ead5ea5a..febf5fd6f 100644 --- a/conda/faiss-gpu-cuvs/meta.yaml +++ b/conda/faiss-gpu-cuvs/meta.yaml @@ -6,9 +6,9 @@ {% set version = environ.get('GIT_DESCRIBE_TAG').lstrip('v') %} {% set suffix = "_nightly" if environ.get('PACKAGE_TYPE') == 'nightly' else "" %} {% set number = GIT_DESCRIBE_NUMBER %} -{% set cuda_constraints=">=12.9,<13.0" %} -{% set libcublas_constraints=">=12.9,<13.0" %} -{% set cudart_constraints=">=12.9,<13.0" %} +{% set cuda_constraints=">=12.6,<12.7" %} +{% set libcublas_constraints=">=12.6,<12.7" %} +{% set cudart_constraints=">=12.6,<12.7" %} package: name: faiss-pkg @@ -60,7 +60,7 @@ outputs: - _openmp_mutex =4.5=2_kmp_llvm # [x86_64] - mkl >=2024.2.2 # [x86_64] - openblas =0.3.30 # [not x86_64] - - libcuvs =26.02 + - libcuvs =25.10 - cuda-version {{ cuda_constraints }} - libsvs-runtime =0.2.0 # [x86_64 and linux] run: @@ -69,7 +69,7 @@ outputs: - openblas =0.3.30 # [not x86_64] - cuda-cudart {{ cuda_constraints }} - libcublas {{ libcublas_constraints }} - - libcuvs =26.02 + - libcuvs =25.10 - cuda-version {{ cuda_constraints }} - libnvjitlink - libsvs-runtime =0.2.0 # [x86_64 and linux] @@ -91,10 +91,10 @@ outputs: string: "py{{ PY_VER }}_h{{ PKG_HASH }}_{{ number }}_cuda{{ cudatoolkit }}{{ suffix }}" requirements: build: - - {{ compiler('cxx') }} =14.2 - - sysroot_linux-64 =2.34 # [linux64] + - {{ compiler('cxx') }} =12.4 + - sysroot_linux-64 =2.17 # [linux64] - swig =4.0 - - cmake >=3.30.4 + - cmake >=3.26.4 - make =4.2 # [not win] - _openmp_mutex =4.5=2_kmp_llvm # [x86_64] - mkl >=2024.2.2 # [x86_64] diff --git a/faiss/gpu/GpuDistance.cu b/faiss/gpu/GpuDistance.cu index 2f330b523..65ed8a1d4 100644 --- a/faiss/gpu/GpuDistance.cu +++ b/faiss/gpu/GpuDistance.cu @@ -238,7 +238,7 @@ void bfKnn(GpuResourcesProvider* prov, const GpuDistanceParams& args) { if (should_use_cuvs(args) && args.queriesRowMajor == args.vectorsRowMajor && args.outIndicesType == IndicesDataType::I64 && args.vectorType == DistanceDataType::F32 && args.k > 0) { - auto distance = metricFaissToCuvs(args.metric, false); + cuvsDistanceType distance = metricFaissToCuvs(args.metric, false); auto resImpl = prov->getResources(); auto res = resImpl.get(); diff --git a/faiss/gpu/GpuIndexCagra.h b/faiss/gpu/GpuIndexCagra.h index 33d14553a..a004337bf 100644 --- a/faiss/gpu/GpuIndexCagra.h +++ b/faiss/gpu/GpuIndexCagra.h @@ -193,14 +193,14 @@ struct GpuIndexCagraConfig : public GpuIndexConfig { enum class search_algo { /// For large batch sizes. - SINGLE_CTA = 0, + SINGLE_CTA, /// For small batch sizes. - MULTI_CTA = 1, - MULTI_KERNEL = 2, - AUTO = 100 + MULTI_CTA, + MULTI_KERNEL, + AUTO }; -enum class hash_mode { HASH = 0, SMALL = 1, AUTO = 100 }; +enum class hash_mode { HASH, SMALL, AUTO }; struct SearchParametersCagra : SearchParameters { /// Maximum number of queries to search at the same time (batch size). Auto diff --git a/faiss/gpu/GpuResources.h b/faiss/gpu/GpuResources.h index 61d9d4dbe..c0c851a89 100644 --- a/faiss/gpu/GpuResources.h +++ b/faiss/gpu/GpuResources.h @@ -33,7 +33,7 @@ #if defined USE_NVIDIA_CUVS #include -#include +#include #endif namespace faiss { diff --git a/faiss/gpu/StandardGpuResources.cpp b/faiss/gpu/StandardGpuResources.cpp index 548618262..cbb29af43 100644 --- a/faiss/gpu/StandardGpuResources.cpp +++ b/faiss/gpu/StandardGpuResources.cpp @@ -23,9 +23,9 @@ #if defined USE_NVIDIA_CUVS #include -#include -#include -#include +#include +#include +#include #include #endif @@ -93,7 +93,7 @@ StandardGpuResourcesImpl::StandardGpuResourcesImpl() : #if defined USE_NVIDIA_CUVS mmr_(new rmm::mr::managed_memory_resource), - pmr_(new rmm::mr::pinned_host_memory_resource), + pmr_(new rmm::mr::pinned_memory_resource), #endif pinnedMemAlloc_(nullptr), pinnedMemAllocSize_(0), @@ -164,7 +164,7 @@ StandardGpuResourcesImpl::~StandardGpuResourcesImpl() { if (pinnedMemAlloc_) { #if defined USE_NVIDIA_CUVS - pmr_->deallocate_sync(pinnedMemAlloc_, pinnedMemAllocSize_); + pmr_->deallocate(pinnedMemAlloc_, pinnedMemAllocSize_); #else auto err = cudaFreeHost(pinnedMemAlloc_); FAISS_ASSERT_FMT( @@ -350,7 +350,7 @@ void StandardGpuResourcesImpl::initializeForDevice(int device) { // pinned memory allocation if (defaultStreams_.empty() && pinnedMemSize_ > 0) { try { - pinnedMemAlloc_ = pmr_->allocate_sync(pinnedMemSize_); + pinnedMemAlloc_ = pmr_->allocate(pinnedMemSize_); } catch (const std::bad_alloc& rmm_ex) { FAISS_THROW_MSG("CUDA memory allocation error"); } @@ -549,7 +549,7 @@ void* StandardGpuResourcesImpl::allocMemory(const AllocRequest& req) { rmm::mr::device_memory_resource* current_mr = rmm::mr::get_per_device_resource( rmm::cuda_device_id{adjReq.device}); - p = current_mr->allocate(adjReq.stream, adjReq.size); + p = current_mr->allocate_async(adjReq.size, adjReq.stream); adjReq.mr = current_mr; } catch (const std::bad_alloc& rmm_ex) { FAISS_THROW_MSG("CUDA memory allocation error"); @@ -584,7 +584,7 @@ void* StandardGpuResourcesImpl::allocMemory(const AllocRequest& req) { // TODO: change this to use the current device resource once RMM has // a way to retrieve a "guaranteed" managed memory resource for a // device. - p = mmr_->allocate(adjReq.stream, adjReq.size); + p = mmr_->allocate_async(adjReq.size, adjReq.stream); adjReq.mr = mmr_.get(); } catch (const std::bad_alloc& rmm_ex) { FAISS_THROW_MSG("CUDA memory allocation error"); @@ -648,7 +648,7 @@ void StandardGpuResourcesImpl::deallocMemory(int device, void* p) { req.space == MemorySpace::Device || req.space == MemorySpace::Unified) { #if defined USE_NVIDIA_CUVS - req.mr->deallocate(req.stream, p, req.size); + req.mr->deallocate_async(p, req.size, req.stream); #else auto err = cudaFree(p); FAISS_ASSERT_FMT( diff --git a/faiss/gpu/StandardGpuResources.h b/faiss/gpu/StandardGpuResources.h index 3ba606606..f23ca19d8 100644 --- a/faiss/gpu/StandardGpuResources.h +++ b/faiss/gpu/StandardGpuResources.h @@ -25,8 +25,7 @@ #if defined USE_NVIDIA_CUVS #include -#include -#include +#include #endif #include @@ -173,8 +172,8 @@ class StandardGpuResourcesImpl : public GpuResources { // managed_memory_resource std::unique_ptr mmr_; - // pinned_host_memory_resource - std::unique_ptr pmr_; + // pinned_memory_resource + std::unique_ptr pmr_; #endif /// Pinned memory allocation for use with this GPU diff --git a/faiss/gpu/impl/BinaryCuvsCagra.cu b/faiss/gpu/impl/BinaryCuvsCagra.cu index 60cbe53fa..b331fdc8f 100644 --- a/faiss/gpu/impl/BinaryCuvsCagra.cu +++ b/faiss/gpu/impl/BinaryCuvsCagra.cu @@ -49,9 +49,9 @@ BinaryCuvsCagra::BinaryCuvsCagra( IndicesOptions indicesOptions) : resources_(resources), dim_(dim), - store_dataset_(store_dataset), graph_build_algo_(graph_build_algo), - nn_descent_niter_(nn_descent_niter) { + nn_descent_niter_(nn_descent_niter), + store_dataset_(store_dataset) { FAISS_THROW_IF_NOT_MSG( indicesOptions == faiss::gpu::INDICES_64_BIT, "only INDICES_64_BIT is supported for cuVS CAGRA index"); @@ -161,11 +161,6 @@ void BinaryCuvsCagra::train(idx_t n, const uint8_t* x) { cuvs::neighbors::cagra::graph_build_params::iterative_search_params graph_build_params; index_params_.graph_build_params = graph_build_params; - if (index_params_.graph_degree == - index_params_.intermediate_graph_degree) { - index_params_.intermediate_graph_degree = - 1.5 * index_params_.graph_degree; - } } if (getDeviceForAddress(x) >= 0) { diff --git a/faiss/gpu/impl/CuvsCagra.cuh b/faiss/gpu/impl/CuvsCagra.cuh index 224f5585a..a10e9fba6 100644 --- a/faiss/gpu/impl/CuvsCagra.cuh +++ b/faiss/gpu/impl/CuvsCagra.cuh @@ -39,14 +39,9 @@ namespace faiss { /// Algorithm used to build underlying CAGRA graph enum class cagra_build_algo { IVF_PQ, NN_DESCENT }; -enum class cagra_search_algo { - SINGLE_CTA = 0, - MULTI_CTA = 1, - MULTI_KERNEL = 2, - AUTO = 100 -}; +enum class cagra_search_algo { SINGLE_CTA, MULTI_CTA }; -enum class cagra_hash_mode { HASH = 0, SMALL = 1, AUTO = 100 }; +enum class cagra_hash_mode { HASH, SMALL, AUTO }; namespace gpu { diff --git a/faiss/gpu/impl/CuvsFlatIndex.cu b/faiss/gpu/impl/CuvsFlatIndex.cu index d1669831c..efc66ea94 100644 --- a/faiss/gpu/impl/CuvsFlatIndex.cu +++ b/faiss/gpu/impl/CuvsFlatIndex.cu @@ -91,7 +91,7 @@ void CuvsFlatIndex::query( outDistances.getSize(0), outDistances.getSize(1)); - auto distance = metricFaissToCuvs(metric, exactDistance); + cuvsDistanceType distance = metricFaissToCuvs(metric, exactDistance); std::optional> norms_view = raft::make_device_vector_view( diff --git a/faiss/gpu/impl/CuvsIVFPQ.cu b/faiss/gpu/impl/CuvsIVFPQ.cu index f2f293026..1e2fef225 100644 --- a/faiss/gpu/impl/CuvsIVFPQ.cu +++ b/faiss/gpu/impl/CuvsIVFPQ.cu @@ -129,14 +129,8 @@ void CuvsIVFPQ::updateQuantizer(Index* quantizer) { cuvs::neighbors::ivf_pq::helpers::reset_index( raft_handle, cuvs_index.get()); - auto mutable_rotation_matrix_view = - raft::make_device_matrix_view( - const_cast( - cuvs_index->rotation_matrix().data_handle()), - cuvs_index->rotation_matrix().extent(0), - cuvs_index->rotation_matrix().extent(1)); cuvs::neighbors::ivf_pq::helpers::make_rotation_matrix( - raft_handle, mutable_rotation_matrix_view, false); + raft_handle, cuvs_index.get(), false); // If the index instance is a GpuIndexFlat, then we can use direct access to // the centroids within. @@ -155,60 +149,22 @@ void CuvsIVFPQ::updateQuantizer(Index* quantizer) { // as float32 and store locally gpuData->reconstruct(0, gpuData->getSize(), centroids); - auto mutable_centers_view = - raft::make_device_matrix_view( - const_cast( - cuvs_index->centers().data_handle()), - numLists_, - cuvs_index->centers().extent(1)); - auto mutable_centers_rot_view = - raft::make_device_matrix_view( - const_cast( - cuvs_index->centers_rot().data_handle()), - cuvs_index->centers_rot().extent(0), - cuvs_index->centers_rot().extent(1)); - - cuvs::neighbors::ivf_pq::helpers::pad_centers_with_norms( + cuvs::neighbors::ivf_pq::helpers::set_centers( raft_handle, - raft::make_const_mdspan( - raft::make_device_matrix_view( - centroids.data(), numLists_, dim_)), - mutable_centers_view); - cuvs::neighbors::ivf_pq::helpers::rotate_padded_centers( - raft_handle, - cuvs_index->centers(), - cuvs_index->rotation_matrix(), - mutable_centers_rot_view); + cuvs_index.get(), + raft::make_device_matrix_view( + centroids.data(), numLists_, dim_)); } else { /// No reconstruct needed since the centers are already in float32 // The FlatIndex keeps its data in float32, so we can merely // reference it auto centroids = gpuData->getVectorsFloat32Ref(); - auto mutable_centers_view = - raft::make_device_matrix_view( - const_cast( - cuvs_index->centers().data_handle()), - numLists_, - cuvs_index->centers().extent(1)); - auto mutable_centers_rot_view = - raft::make_device_matrix_view( - const_cast( - cuvs_index->centers_rot().data_handle()), - cuvs_index->centers_rot().extent(0), - cuvs_index->centers_rot().extent(1)); - - cuvs::neighbors::ivf_pq::helpers::pad_centers_with_norms( + cuvs::neighbors::ivf_pq::helpers::set_centers( raft_handle, - raft::make_const_mdspan( - raft::make_device_matrix_view( - centroids.data(), numLists_, dim_)), - mutable_centers_view); - cuvs::neighbors::ivf_pq::helpers::rotate_padded_centers( - raft_handle, - cuvs_index->centers(), - cuvs_index->rotation_matrix(), - mutable_centers_rot_view); + cuvs_index.get(), + raft::make_device_matrix_view( + centroids.data(), numLists_, dim_)); } } else { DeviceTensor centroids( @@ -224,30 +180,11 @@ void CuvsIVFPQ::updateQuantizer(Index* quantizer) { centroids.copyFrom(vecs, stream); - // Create mutable views for output parameters - auto mutable_centers_view = - raft::make_device_matrix_view( - const_cast(cuvs_index->centers().data_handle()), - numLists_, - cuvs_index->centers().extent(1)); - auto mutable_centers_rot_view = - raft::make_device_matrix_view( - const_cast( - cuvs_index->centers_rot().data_handle()), - cuvs_index->centers_rot().extent(0), - cuvs_index->centers_rot().extent(1)); - - cuvs::neighbors::ivf_pq::helpers::pad_centers_with_norms( + cuvs::neighbors::ivf_pq::helpers::set_centers( raft_handle, - raft::make_const_mdspan( - raft::make_device_matrix_view( - centroids.data(), numLists_, dim_)), - mutable_centers_view); - cuvs::neighbors::ivf_pq::helpers::rotate_padded_centers( - raft_handle, - cuvs_index->centers(), - cuvs_index->rotation_matrix(), - mutable_centers_rot_view); + cuvs_index.get(), + raft::make_device_matrix_view( + centroids.data(), numLists_, dim_)); } setPQCentroids_(); @@ -467,11 +404,10 @@ void CuvsIVFPQ::copyInvertedListsFrom(const InvertedLists* ivf) { auto& cuvs_index_lists = cuvs_index->lists(); // conservative memory alloc for cloning cpu inverted lists - cuvs::neighbors::ivf_pq::list_spec_interleaved - ivf_list_spec{ - static_cast(bitsPerSubQuantizer_), - static_cast(numSubQuantizers_), - true}; + cuvs::neighbors::ivf_pq::list_spec ivf_list_spec{ + static_cast(bitsPerSubQuantizer_), + static_cast(numSubQuantizers_), + true}; for (size_t i = 0; i < nlist; ++i) { size_t listSize = ivf->list_size(i); @@ -490,7 +426,7 @@ void CuvsIVFPQ::copyInvertedListsFrom(const InvertedLists* ivf) { // This cuVS list must currently be empty FAISS_ASSERT(getListLength(i) == 0); - cuvs::neighbors::ivf_pq::helpers::resize_list( + cuvs::neighbors::ivf::resize_list( raft_handle, cuvs_index_lists[i], ivf_list_spec, @@ -584,7 +520,7 @@ void CuvsIVFPQ::setPQCentroids_() { auto stream = resources_->getDefaultStreamCurrentDevice(); raft::copy( - const_cast(cuvs_index->pq_centers().data_handle()), + cuvs_index->pq_centers().data_handle(), pqCentroidsInnermostCode_.data(), pqCentroidsInnermostCode_.numElements(), stream); diff --git a/faiss/gpu/utils/CuvsUtils.cu b/faiss/gpu/utils/CuvsUtils.cu index 3751dfa62..1ec32179c 100644 --- a/faiss/gpu/utils/CuvsUtils.cu +++ b/faiss/gpu/utils/CuvsUtils.cu @@ -31,7 +31,6 @@ #include #include -#include #include namespace faiss { diff --git a/faiss/gpu/utils/CuvsUtils.h b/faiss/gpu/utils/CuvsUtils.h index 42fe8ca48..e44e5f12d 100644 --- a/faiss/gpu/utils/CuvsUtils.h +++ b/faiss/gpu/utils/CuvsUtils.h @@ -27,32 +27,32 @@ #include #include -#include +#include #pragma GCC visibility push(default) namespace faiss { namespace gpu { -inline cuvs::distance::DistanceType metricFaissToCuvs( +inline cuvsDistanceType metricFaissToCuvs( MetricType metric, bool exactDistance) { switch (metric) { case MetricType::METRIC_INNER_PRODUCT: - return cuvs::distance::DistanceType::InnerProduct; + return cuvsDistanceType::InnerProduct; case MetricType::METRIC_L2: - return cuvs::distance::DistanceType::L2Expanded; + return cuvsDistanceType::L2Expanded; case MetricType::METRIC_L1: - return cuvs::distance::DistanceType::L1; + return cuvsDistanceType::L1; case MetricType::METRIC_Linf: - return cuvs::distance::DistanceType::Linf; + return cuvsDistanceType::Linf; case MetricType::METRIC_Lp: - return cuvs::distance::DistanceType::LpUnexpanded; + return cuvsDistanceType::LpUnexpanded; case MetricType::METRIC_Canberra: - return cuvs::distance::DistanceType::Canberra; + return cuvsDistanceType::Canberra; case MetricType::METRIC_BrayCurtis: - return cuvs::distance::DistanceType::BrayCurtis; + return cuvsDistanceType::BrayCurtis; case MetricType::METRIC_JensenShannon: - return cuvs::distance::DistanceType::JensenShannon; + return cuvsDistanceType::JensenShannon; default: RAFT_FAIL("Distance type not supported"); } diff --git a/faiss/python/CMakeLists.txt b/faiss/python/CMakeLists.txt index 472945502..ad963a2c8 100644 --- a/faiss/python/CMakeLists.txt +++ b/faiss/python/CMakeLists.txt @@ -230,6 +230,9 @@ if(FAISS_ENABLE_GPU) target_link_libraries(faiss_example_external_module PRIVATE hip::host) else() find_package(CUDAToolkit REQUIRED) + if(FAISS_ENABLE_CUVS) + find_package(cuvs) + endif() target_link_libraries(swigfaiss PRIVATE CUDA::cudart $<$:cuvs::cuvs>) target_link_libraries(swigfaiss_avx2 PRIVATE CUDA::cudart $<$:cuvs::cuvs>) target_link_libraries(swigfaiss_avx512 PRIVATE CUDA::cudart $<$:cuvs::cuvs>)