Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,10 @@ include(cmake/AddCUDSS.cmake)
include(cmake/BundleStaticDeps.cmake)

add_spdlog()
option(LOCAL_CUDSS_BUILD "Build cuDSS locally" ON)
set(CUDSS_BUILD_PATH "${PROJECT_SOURCE_DIR}/libs/cudss")

if(NOT LOCAL_CUDSS_BUILD)
set(CUDSS_BUILD_PATH "")
endif()
add_cudss(CUDSS_BUILD_PATH "${CUDSS_BUILD_PATH}")
# cuDSS is fetched as a prebuilt archive. Default to 0.8.0.10; 0.7.1.4 is still
# supported via -DCUDSS_VERSION=0.7.1.4.
set(CUDSS_VERSION "0.8.0.10" CACHE STRING "cuDSS version to download")
add_cudss(VERSION "${CUDSS_VERSION}")

set(CUNLS_LIBS spdlog::spdlog CUDA::cusparse CUDA::cublas CUDA::cusolver cudss)

Expand Down Expand Up @@ -60,7 +57,7 @@ add_library(cunls
$<TARGET_OBJECTS:cunls_robustifier>
)

target_link_libraries(cunls
target_link_libraries(cunls
PUBLIC CUDA::cudart
PRIVATE ${CUNLS_LIBS}
)
Expand Down
109 changes: 51 additions & 58 deletions cmake/AddCUDSS.cmake
Original file line number Diff line number Diff line change
@@ -1,78 +1,71 @@
# Function to add cuDSS library to the project
#
# Usage:
# add_cudss(CUDSS_BUILD_PATH "/path/to/cudss/build")
# add_cudss(VERSION "0.8.0.10")
#
# This function will:
# - Check if a local cuDSS build exists at CUDSS_BUILD_PATH
# - If found, use the local build (sets CUDSS_NEW_API compile definition)
# - If not found, download a prebuilt version using FetchContent
# - Create an imported target 'cudss' that can be linked against
# This function downloads a prebuilt cuDSS archive (matching the host
# architecture and the CUDA major version) using FetchContent and creates an
# imported target 'cudss' that can be linked against.
#
# Supported versions: 0.8.0.10 (default) and 0.7.1.4. The cuDSS API differs
# between 0.7.x and 0.8.x; the C++ sources select the right API based on the
# CUDSS_VERSION macro from the cuDSS header, so no extra compile definition is
# needed here.
#
# Parameters:
# CUDSS_BUILD_PATH - Path to the cuDSS build directory (optional, defaults to empty)
# VERSION - cuDSS version to download (optional, defaults to 0.8.0.10)
function(add_cudss)
# Parse arguments
set(options "")
set(oneValueArgs CUDSS_BUILD_PATH)
set(oneValueArgs VERSION)
set(multiValueArgs "")
cmake_parse_arguments(CUDSS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

if(NOT ARG_VERSION)
set(ARG_VERSION "0.8.0.10")
endif()

# Create imported target
add_library(cudss STATIC IMPORTED)

# Check if local build path was provided and exists
set(LOCAL_CUDSS_BUILD OFF)
if(CUDSS_CUDSS_BUILD_PATH)
set(CUDSS_LIB_PATH "${CUDSS_CUDSS_BUILD_PATH}/libcudss_static.a")
set(CUDSS_INCLUDE_PATH "${CUDSS_CUDSS_BUILD_PATH}/include")

if(EXISTS "${CUDSS_LIB_PATH}" AND EXISTS "${CUDSS_INCLUDE_PATH}")
set(LOCAL_CUDSS_BUILD ON)
message(STATUS "Using local cuDSS build from ${CUDSS_CUDSS_BUILD_PATH}")
set_target_properties(cudss PROPERTIES
IMPORTED_LOCATION "${CUDSS_LIB_PATH}"
INTERFACE_INCLUDE_DIRECTORIES "${CUDSS_INCLUDE_PATH}"
)
endif()
message(STATUS "Using prebuilt cuDSS ${ARG_VERSION}")
set(CUDSS_URL_PREFIX "https://developer.download.nvidia.com/compute/cudss/redist/libcudss/")
message(STATUS "CUDA Compiler Version: ${CMAKE_CUDA_COMPILER_VERSION}")

# Archive flavor follows the CUDA major version.
if(${CMAKE_CUDA_COMPILER_VERSION} VERSION_GREATER_EQUAL 13.0)
set(CUDSS_CUDA_TAG "cuda13")
message(STATUS "Using CUDA 13.0 or newer")
else()
set(CUDSS_CUDA_TAG "cuda12")
message(STATUS "Using CUDA 12.0 or older")
endif()

# If local build not found, use prebuilt version
if(NOT LOCAL_CUDSS_BUILD)
message(STATUS "Using prebuilt cuDSS")
set(CUDSS_URL_PREFIX "https://developer.download.nvidia.com/compute/cudss/redist/libcudss/")
message(STATUS "CUDA Compiler Version: ${CMAKE_CUDA_COMPILER_VERSION}")

if(${CMAKE_CUDA_COMPILER_VERSION} VERSION_GREATER_EQUAL 13.0)
set(CUDSS_URL_AARCH64 ${CUDSS_URL_PREFIX}linux-aarch64/libcudss-linux-aarch64-0.7.1.4_cuda13-archive.tar.xz)
set(CUDSS_URL_X86_64 ${CUDSS_URL_PREFIX}linux-x86_64/libcudss-linux-x86_64-0.7.1.4_cuda13-archive.tar.xz)
message(STATUS "Using CUDA 13.0 or newer")
else()
set(CUDSS_URL_AARCH64 ${CUDSS_URL_PREFIX}linux-aarch64/libcudss-linux-aarch64-0.7.1.4_cuda12-archive.tar.xz)
set(CUDSS_URL_X86_64 ${CUDSS_URL_PREFIX}linux-x86_64/libcudss-linux-x86_64-0.7.1.4_cuda12-archive.tar.xz)
message(STATUS "Using CUDA 12.0 or older")
endif()
# The aarch64 archive naming changed between releases: 0.7.x ships as
# "linux-aarch64", while 0.8+ ships as "linux-sbsa".
if(${ARG_VERSION} VERSION_GREATER_EQUAL 0.8.0)
set(CUDSS_AARCH64_NAME "linux-sbsa")
else()
set(CUDSS_AARCH64_NAME "linux-aarch64")
endif()

if(CMAKE_SYSTEM_PROCESSOR MATCHES "(aarch64)|(AARCH64)")
set(CUDSS_URL ${CUDSS_URL_AARCH64})
else()
set(CUDSS_URL ${CUDSS_URL_X86_64})
endif()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "(aarch64)|(AARCH64)")
set(CUDSS_URL "${CUDSS_URL_PREFIX}${CUDSS_AARCH64_NAME}/libcudss-${CUDSS_AARCH64_NAME}-${ARG_VERSION}_${CUDSS_CUDA_TAG}-archive.tar.xz")
else()
set(CUDSS_URL "${CUDSS_URL_PREFIX}linux-x86_64/libcudss-linux-x86_64-${ARG_VERSION}_${CUDSS_CUDA_TAG}-archive.tar.xz")
endif()

include(FetchContent)
FetchContent_Declare(
cudss
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
URL ${CUDSS_URL}
)
FetchContent_Populate(cudss)
message(STATUS "cuDSS download URL: ${CUDSS_URL}")

set_target_properties(cudss PROPERTIES
IMPORTED_LOCATION "${cudss_SOURCE_DIR}/lib/libcudss_static.a"
INTERFACE_INCLUDE_DIRECTORIES "${cudss_SOURCE_DIR}/include"
)
endif()
include(FetchContent)
FetchContent_Declare(
cudss
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
URL ${CUDSS_URL}
)
FetchContent_MakeAvailable(cudss)
Comment thread
alexkorovko marked this conversation as resolved.

# Set parent scope variable to indicate if local build is used
set(LOCAL_CUDSS_BUILD ${LOCAL_CUDSS_BUILD} PARENT_SCOPE)
set_target_properties(cudss PROPERTIES
IMPORTED_LOCATION "${cudss_SOURCE_DIR}/lib/libcudss_static.a"
INTERFACE_INCLUDE_DIRECTORIES "${cudss_SOURCE_DIR}/include"
)
endfunction()
4 changes: 0 additions & 4 deletions cunls/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ add_library(cunls_common OBJECT

target_link_libraries(cunls_common PRIVATE spdlog::spdlog cudss)

if(LOCAL_CUDSS_BUILD)
target_compile_definitions(cunls_common PRIVATE CUDSS_NEW_API)
endif()

if(ENABLE_PROFILING)
target_link_libraries(cunls_common PRIVATE nvtx3-cpp)
target_compile_definitions(cunls_common PRIVATE ENABLE_PROFILING)
Expand Down
79 changes: 39 additions & 40 deletions cunls/common/cudss_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,20 @@

#include "cunls/common/cudss_helper.h"

#include <cudss.h>

#include <cassert>
#include <cstring>

#include "cunls/common/log.h"
#include <cudss.h>

// cuDSS 0.8 reworked the matrix descriptor and config API (new reordering enums,
// hybrid execute mode, separate offset/index/value types in cudssMatrixCreateCsr).
// Releases <= 0.7.x still use the legacy API. Gate on the version reported by the
// cuDSS header so both prebuilt 0.7.1 and 0.8 builds compile.
#if CUDSS_VERSION_MAJOR > 0 || CUDSS_VERSION_MINOR >= 8
#define CUDSS_NEW_API
#endif

namespace cunls {

Expand Down Expand Up @@ -128,25 +137,21 @@ int cuDSSDeviceMemPool::Dealloc(void *ptr, size_t size, cudaStream_t stream) {
return cudaErrorInvalidDevicePointer;
}

int cuDSSDeviceMemPoolAlloc(void *ctx, void **ptr, size_t size,
cudaStream_t stream) {
int cuDSSDeviceMemPoolAlloc(void *ctx, void **ptr, size_t size, cudaStream_t stream) {
if (ctx == nullptr) {
return cudaErrorInvalidResourceHandle;
}
return reinterpret_cast<cuDSSDeviceMemPool *>(ctx)->Alloc(ptr, size, stream);
}

int cuDSSDeviceMemPoolDealloc(void *ctx, void *ptr, size_t size,
cudaStream_t stream) {
int cuDSSDeviceMemPoolDealloc(void *ctx, void *ptr, size_t size, cudaStream_t stream) {
if (ctx == nullptr) {
return cudaErrorInvalidResourceHandle;
}
return reinterpret_cast<cuDSSDeviceMemPool *>(ctx)->Dealloc(ptr, size,
stream);
return reinterpret_cast<cuDSSDeviceMemPool *>(ctx)->Dealloc(ptr, size, stream);
}

void SetcuDSSDeviceMemHandler(void *handle, cuDSSDeviceMemPool &pool,
const char *handler_name) {
void SetcuDSSDeviceMemHandler(void *handle, cuDSSDeviceMemPool &pool, const char *handler_name) {
if (handle == nullptr) {
return;
}
Expand All @@ -155,25 +160,22 @@ void SetcuDSSDeviceMemHandler(void *handle, cuDSSDeviceMemPool &pool,
handler.ctx = reinterpret_cast<void *>(&pool);
handler.device_alloc = cuDSSDeviceMemPoolAlloc;
handler.device_free = cuDSSDeviceMemPoolDealloc;
std::strncpy(handler.name,
(handler_name == nullptr || handler_name[0] == '\0')
? "cunls device pool"
: handler_name,
CUDSS_ALLOCATOR_NAME_LEN);
std::strncpy(
handler.name,
(handler_name == nullptr || handler_name[0] == '\0') ? "cunls device pool" : handler_name,
CUDSS_ALLOCATOR_NAME_LEN);
handler.name[CUDSS_ALLOCATOR_NAME_LEN - 1] = '\0';

DetachcuDSSDeviceMemHandler(handle);

THROW_ON_CUDSS_ERROR(cudssSetDeviceMemHandler(
reinterpret_cast<cudssHandle_t>(handle), &handler));
THROW_ON_CUDSS_ERROR(cudssSetDeviceMemHandler(reinterpret_cast<cudssHandle_t>(handle), &handler));
}

void DetachcuDSSDeviceMemHandler(void *handle) {
if (handle == nullptr) {
return;
}
THROW_ON_CUDSS_ERROR(cudssSetDeviceMemHandler(
reinterpret_cast<cudssHandle_t>(handle), nullptr));
THROW_ON_CUDSS_ERROR(cudssSetDeviceMemHandler(reinterpret_cast<cudssHandle_t>(handle), nullptr));
}

/**
Expand Down Expand Up @@ -241,15 +243,14 @@ cuDSSDescription::cuDSSDescription(const CSRSparseMatrix &symmetric_matrix) {
// Create cuDSS CSR matrix descriptor
// Parameters: symmetric matrix, full view, zero-based indexing
#ifdef CUDSS_NEW_API
THROW_ON_CUDSS_ERROR(cudssMatrixCreateCsr(
&mat, matrix_size, matrix_size, num_nonzeros, rows_ptr, NULL, cols_ptr,
values_ptr, CUDSS_R_32I, CUDSS_R_32I, CUDSS_R_32F, CUDSS_MTYPE_SYMMETRIC,
CUDSS_MVIEW_FULL, CUDSS_BASE_ZERO));
THROW_ON_CUDSS_ERROR(cudssMatrixCreateCsr(&mat, matrix_size, matrix_size, num_nonzeros, rows_ptr,
NULL, cols_ptr, values_ptr, CUDSS_R_32I, CUDSS_R_32I,
CUDSS_R_32F, CUDSS_MTYPE_SYMMETRIC, CUDSS_MVIEW_FULL,
CUDSS_BASE_ZERO));
#else
THROW_ON_CUDSS_ERROR(cudssMatrixCreateCsr(
&mat, matrix_size, matrix_size, num_nonzeros, rows_ptr, NULL, cols_ptr,
values_ptr, CUDA_R_32I, CUDA_R_32F, CUDSS_MTYPE_SYMMETRIC,
CUDSS_MVIEW_FULL, CUDSS_BASE_ZERO));
&mat, matrix_size, matrix_size, num_nonzeros, rows_ptr, NULL, cols_ptr, values_ptr,
CUDA_R_32I, CUDA_R_32F, CUDSS_MTYPE_SYMMETRIC, CUDSS_MVIEW_FULL, CUDSS_BASE_ZERO));
#endif
Comment thread
alexkorovko marked this conversation as resolved.

matrix_ = reinterpret_cast<void *>(mat);
Expand All @@ -274,11 +275,11 @@ cuDSSDescription::cuDSSDescription(const dvector<float> &vector) {

cudssMatrix_t mat = nullptr;
#ifdef CUDSS_NEW_API
THROW_ON_CUDSS_ERROR(cudssMatrixCreateDn(&mat, size, 1, size, ptr, CUDSS_R_32F,
CUDSS_LAYOUT_COL_MAJOR));
THROW_ON_CUDSS_ERROR(
cudssMatrixCreateDn(&mat, size, 1, size, ptr, CUDSS_R_32F, CUDSS_LAYOUT_COL_MAJOR));
#else
THROW_ON_CUDSS_ERROR(cudssMatrixCreateDn(&mat, size, 1, size, ptr, CUDA_R_32F,
CUDSS_LAYOUT_COL_MAJOR));
THROW_ON_CUDSS_ERROR(
cudssMatrixCreateDn(&mat, size, 1, size, ptr, CUDA_R_32F, CUDSS_LAYOUT_COL_MAJOR));
#endif
matrix_ = reinterpret_cast<void *>(mat);
}
Expand Down Expand Up @@ -318,8 +319,8 @@ cuDSSConfig::cuDSSConfig(int reordering_algorithm, int nthreads) {

auto alg = (cudssReorderingAlg_t)reordering_algorithm;

THROW_ON_CUDSS_ERROR(cudssConfigSet(cfg, CUDSS_CONFIG_REORDERING_ALG, &alg,
sizeof(cudssReorderingAlg_t)));
THROW_ON_CUDSS_ERROR(
cudssConfigSet(cfg, CUDSS_CONFIG_REORDERING_ALG, &alg, sizeof(cudssReorderingAlg_t)));
#else
// Validate algorithm is within expected range
if (reordering_algorithm < static_cast<int>(CUDSS_ALG_DEFAULT) ||
Expand All @@ -331,23 +332,21 @@ cuDSSConfig::cuDSSConfig(int reordering_algorithm, int nthreads) {

auto alg = (cudssAlgType_t)reordering_algorithm;

THROW_ON_CUDSS_ERROR(cudssConfigSet(cfg, CUDSS_CONFIG_REORDERING_ALG, &alg,
sizeof(cudssAlgType_t)));
THROW_ON_CUDSS_ERROR(
cudssConfigSet(cfg, CUDSS_CONFIG_REORDERING_ALG, &alg, sizeof(cudssAlgType_t)));
#endif

THROW_ON_CUDSS_ERROR(
cudssConfigSet(cfg, CUDSS_CONFIG_HOST_NTHREADS, &nthreads, sizeof(int)));
THROW_ON_CUDSS_ERROR(cudssConfigSet(cfg, CUDSS_CONFIG_HOST_NTHREADS, &nthreads, sizeof(int)));

#ifdef CUDSS_NEW_API
// Hybrid execute mode is incompatible with the BTF_COLAMD/COLAMD reordering
// paths in cuDSS — those algorithms return CUDSS_STATUS_NOT_SUPPORTED during
// analysis when hybrid execution is on. Enable hybrid mode only for the
// remaining reordering algorithms.
if (alg != CUDSS_REORDERING_ALG_BTF_COLAMD &&
alg != CUDSS_REORDERING_ALG_COLAMD) {
if (alg != CUDSS_REORDERING_ALG_BTF_COLAMD && alg != CUDSS_REORDERING_ALG_COLAMD) {
int hybrid_execute_mode = 16;
THROW_ON_CUDSS_ERROR(cudssConfigSet(cfg, CUDSS_CONFIG_HYBRID_EXECUTE_MODE,
&hybrid_execute_mode, sizeof(int)));
THROW_ON_CUDSS_ERROR(
cudssConfigSet(cfg, CUDSS_CONFIG_HYBRID_EXECUTE_MODE, &hybrid_execute_mode, sizeof(int)));
}
#endif

Expand Down Expand Up @@ -401,4 +400,4 @@ cuDSSData::~cuDSSData() {
}
}

} // namespace cunls
} // namespace cunls
4 changes: 0 additions & 4 deletions cunls/linear_solver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,3 @@ add_library(cunls_linear_solver OBJECT
)

target_link_libraries(cunls_linear_solver PRIVATE cudss)

if(LOCAL_CUDSS_BUILD)
target_compile_definitions(cunls_linear_solver PRIVATE CUDSS_NEW_API)
endif()
Loading