Skip to content

Commit 0f1afef

Browse files
authored
Update API to leverage cuVS Spectral clustering (#5326)
This PR integrates cuVS spectral clustering from upstream into cuGraph while maintaining full backward compatibility. The integration deprecates the legacy balanced cut clustering C++ and Python APIs in favor of spectral_modularity_maximization. In fact, cuVS consolidated the spectral clustering API to assign vertices to clusters that by default maximizes the modularity score **Static Linking with Conda Fallback:** - cuGraph is configured to statically link libcuvs for optimal performance - The build system first attempts to use conda-installed libcuvs if available - If libcuvs is not present in the conda environment or static linking is required, the build system automatically clones the main cuVS repository (rapidsai/cuvs) and builds it from source - Uses the standard RAPIDS release branch (${rapids-cmake-checkout-tag}) ensuring version compatibility Note: The header files `raft/spectral/partition.cuh` and `raft/spectral/modularity_maximization.cuh` are still necessary in `spectraly_clustering.cu` because APIs (like `raft::spectral::analyzePartition`, `raft::spectral::analyzeModularity`) are still being called in cuGraph and are not supported in cuVS. This is not an issue because those APIs are not deprecated in raft in contrary to `kmeans` and `solvers` Authors: - Joseph Nke (https://github.com/jnke2016) Approvers: - Anupam (https://github.com/aamijar) - Chuck Hastings (https://github.com/ChuckHastings) - Rick Ratzel (https://github.com/rlratzel) - Robert Maynard (https://github.com/robertmaynard) - Bradley Dice (https://github.com/bdice) URL: #5326
1 parent fb4f8a1 commit 0f1afef

File tree

21 files changed

+280
-207
lines changed

21 files changed

+280
-207
lines changed

build.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ if buildDefault || hasArg libcugraph || hasArg all; then
240240
-DBUILD_CUGRAPH_MG_TESTS=${BUILD_CPP_MG_TESTS} \
241241
-DBUILD_CUGRAPH_MTMG_TESTS=${BUILD_CPP_MTMG_TESTS} \
242242
"${CMAKE_GENERATOR_OPTION[@]}" \
243-
"${CMAKE_VERBOSE_OPTION[@]}"
243+
"${CMAKE_VERBOSE_OPTION[@]}" \
244+
${EXTRA_CMAKE_ARGS}
244245

245246
cmake --build "${LIBCUGRAPH_BUILD_DIR}" "-j${PARALLEL_LEVEL}" "${INSTALL_TARGET[@]}" "${VERBOSE_FLAG}"
246247
fi

ci/release/update-version.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ DEPENDENCIES=(
110110
libcugraph
111111
libcugraph_etl
112112
libcugraph-tests
113+
libcuvs
113114
libraft
114115
librmm
115116
pylibcudf

conda/environments/all_cuda-129_arch-aarch64.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies:
3232
- libcurand-dev
3333
- libcusolver-dev
3434
- libcusparse-dev
35+
- libcuvs==25.12.*,>=0.0.0a0
3536
- libraft==25.12.*,>=0.0.0a0
3637
- librmm==25.12.*,>=0.0.0a0
3738
- nbsphinx

conda/environments/all_cuda-129_arch-x86_64.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies:
3232
- libcurand-dev
3333
- libcusolver-dev
3434
- libcusparse-dev
35+
- libcuvs==25.12.*,>=0.0.0a0
3536
- libraft==25.12.*,>=0.0.0a0
3637
- librmm==25.12.*,>=0.0.0a0
3738
- nbsphinx

conda/environments/all_cuda-130_arch-aarch64.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies:
3232
- libcurand-dev
3333
- libcusolver-dev
3434
- libcusparse-dev
35+
- libcuvs==25.12.*,>=0.0.0a0
3536
- libraft==25.12.*,>=0.0.0a0
3637
- librmm==25.12.*,>=0.0.0a0
3738
- nbsphinx

conda/environments/all_cuda-130_arch-x86_64.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies:
3232
- libcurand-dev
3333
- libcusolver-dev
3434
- libcusparse-dev
35+
- libcuvs==25.12.*,>=0.0.0a0
3536
- libraft==25.12.*,>=0.0.0a0
3637
- librmm==25.12.*,>=0.0.0a0
3738
- nbsphinx

conda/recipes/libcugraph/recipe.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ cache:
3838
CMAKE_CUDA_COMPILER_LAUNCHER: ${{ env.get("CMAKE_CUDA_COMPILER_LAUNCHER") }}
3939
CMAKE_CXX_COMPILER_LAUNCHER: ${{ env.get("CMAKE_CXX_COMPILER_LAUNCHER") }}
4040
CMAKE_GENERATOR: ${{ env.get("CMAKE_GENERATOR") }}
41+
EXTRA_CMAKE_ARGS: "-DCUGRAPH_COMPILE_CUVS=ON"
4142
PARALLEL_LEVEL: ${{ env.get("PARALLEL_LEVEL") }}
4243
SCCACHE_BUCKET: ${{ env.get("SCCACHE_BUCKET") }}
4344
SCCACHE_IDLE_TIMEOUT: ${{ env.get("SCCACHE_IDLE_TIMEOUT") }}

cpp/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#=============================================================================
2+
# cmake-format: off
23
# SPDX-FileCopyrightText: Copyright (c) 2018-2025, NVIDIA CORPORATION.
34
# SPDX-License-Identifier: Apache-2.0
5+
# cmake-format: on
46
#=============================================================================
57

68
cmake_minimum_required(VERSION 3.30.4 FATAL_ERROR)
@@ -11,6 +13,7 @@ include(rapids-cpm)
1113
include(rapids-cuda)
1214
include(rapids-export)
1315
include(rapids-find)
16+
include(CMakeDependentOption)
1417

1518
rapids_cuda_init_architectures(CUGRAPH)
1619

@@ -41,8 +44,14 @@ option(BUILD_TESTS "Configure CMake to build tests" ON)
4144
option(USE_RAFT_STATIC "Build raft as a static library" OFF)
4245
option(CUGRAPH_COMPILE_RAFT_LIB "Compile the raft library instead of using it header-only" ON)
4346
option(CUDA_STATIC_RUNTIME "Statically link the CUDA toolkit runtime and libraries" OFF)
47+
option(CUGRAPH_COMPILE_CUVS "Always compile cuVS from source" OFF)
48+
cmake_dependent_option(CUGRAPH_USE_CUVS_STATIC
49+
"Build and statically link the cuVS library" ON
50+
"CUGRAPH_COMPILE_CUVS" OFF)
4451

4552
message(VERBOSE "CUGRAPH: CUDA_STATIC_RUNTIME=${CUDA_STATIC_RUNTIME}")
53+
message(VERBOSE "CUGRAPH: CUGRAPH_COMPILE_CUVS=${CUGRAPH_COMPILE_CUVS}")
54+
message(VERBOSE "CUGRAPH: CUGRAPH_USE_CUVS_STATIC=${CUGRAPH_USE_CUVS_STATIC}")
4655

4756
################################################################################
4857
# - compiler options -----------------------------------------------------------
@@ -112,6 +121,9 @@ include(${rapids-cmake-dir}/cpm/cuco.cmake)
112121
rapids_cpm_cuco(BUILD_EXPORT_SET cugraph-exports INSTALL_EXPORT_SET cugraph-exports)
113122
include(cmake/thirdparty/get_raft.cmake)
114123

124+
# Always include cuVS for spectral clustering enhancements
125+
include(cmake/thirdparty/get_cuvs.cmake)
126+
115127
if (BUILD_CUGRAPH_MTMG_TESTS)
116128
if(NOT TARGET ucx::ucp)
117129
find_package(ucx REQUIRED)
@@ -474,6 +486,11 @@ if(CUGRAPH_COMPILE_RAFT_LIB)
474486
endif()
475487
endif()
476488

489+
set(CUVS_LIB cuvs::cuvs)
490+
if(CUGRAPH_USE_CUVS_STATIC)
491+
set(CUVS_LIB cuvs::cuvs_static)
492+
endif()
493+
477494
################################################################################
478495
# - link libraries -------------------------------------------------------------
479496
target_link_libraries(cugraph
@@ -483,6 +500,7 @@ target_link_libraries(cugraph
483500
$<BUILD_LOCAL_INTERFACE:CUDA::toolkit>
484501
PRIVATE
485502
${COMPILED_RAFT_LIB}
503+
${CUVS_LIB}
486504
cuco::cuco
487505
)
488506

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#=============================================================================
2+
# cmake-format: off
3+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# cmake-format: on
6+
#=============================================================================
7+
8+
set(CUGRAPH_MIN_VERSION_cuvs "${CUGRAPH_VERSION_MAJOR}.${CUGRAPH_VERSION_MINOR}.00")
9+
10+
function(find_and_configure_cuvs)
11+
set(oneValueArgs VERSION FORK PINNED_TAG EXCLUDE_FROM_ALL USE_CUVS_STATIC CLONE_ON_PIN)
12+
cmake_parse_arguments(PKG "${options}" "${oneValueArgs}"
13+
"${multiValueArgs}" ${ARGN} )
14+
15+
if(PKG_CLONE_ON_PIN AND NOT PKG_PINNED_TAG STREQUAL "${rapids-cmake-checkout-tag}")
16+
message(STATUS "CUGRAPH: Pinned tag found: ${PKG_PINNED_TAG}. Cloning cuVS locally.")
17+
set(CPM_DOWNLOAD_cuvs ON)
18+
elseif(PKG_USE_CUVS_STATIC AND (NOT CPM_cuvs_SOURCE))
19+
message(STATUS "CUGRAPH: Cloning cuVS locally to build static libraries.")
20+
set(CPM_DOWNLOAD_cuvs ON)
21+
endif()
22+
23+
# Disable multi-GPU algorithms to avoid NCCL dependency
24+
set(CUVS_BUILD_MG_ALGOS OFF)
25+
26+
rapids_cpm_find(cuvs ${PKG_VERSION}
27+
GLOBAL_TARGETS cuvs::cuvs
28+
CPM_ARGS
29+
GIT_REPOSITORY https://github.com/${PKG_FORK}/cuvs.git
30+
GIT_TAG ${PKG_PINNED_TAG}
31+
SOURCE_SUBDIR cpp
32+
EXCLUDE_FROM_ALL ${PKG_EXCLUDE_FROM_ALL}
33+
OPTIONS
34+
"BUILD_TESTS OFF"
35+
"BUILD_CAGRA_HNSWLIB OFF"
36+
"BUILD_CUVS_BENCH OFF"
37+
"BUILD_MG_ALGOS ${CUVS_BUILD_MG_ALGOS}"
38+
)
39+
40+
if(cuvs_ADDED)
41+
message(VERBOSE "CUGRAPH: Using cuVS located in ${cuvs_SOURCE_DIR}")
42+
else()
43+
message(VERBOSE "CUGRAPH: Using cuVS located in ${cuvs_DIR}")
44+
endif()
45+
46+
endfunction()
47+
48+
# Change pinned tag and fork here to test a commit in CI
49+
# To use a different cuVS locally, set the CMake variable
50+
# CPM_cuvs_SOURCE=/path/to/local/cuvs
51+
find_and_configure_cuvs(VERSION ${CUGRAPH_MIN_VERSION_cuvs}
52+
FORK rapidsai
53+
PINNED_TAG ${rapids-cmake-checkout-tag}
54+
55+
# When PINNED_TAG above doesn't match cugraph,
56+
# force local cuVS clone in build directory
57+
# even if it's already installed.
58+
CLONE_ON_PIN ON
59+
USE_CUVS_STATIC ${CUGRAPH_USE_CUVS_STATIC}
60+
EXCLUDE_FROM_ALL ON
61+
)

cpp/include/cugraph/algorithms.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,8 @@ std::unique_ptr<legacy::GraphCOO<VT, ET, WT>> extract_subgraph_vertex(
873873
* @ingroup community_cpp
874874
* @brief Wrapper function for Nvgraph balanced cut clustering
875875
*
876+
* @deprecated This API will be deprecated. Use spectralModularityMaximization instead.
877+
*
876878
* @throws cugraph::logic_error when an error occurs.
877879
*
878880
* @tparam VT Type of vertex identifiers. Supported value : int (signed,

0 commit comments

Comments
 (0)