Skip to content

Commit 96b70ff

Browse files
committed
Implement CUDA backend with cuDSS solver
1 parent a0092dd commit 96b70ff

File tree

17 files changed

+2079
-41
lines changed

17 files changed

+2079
-41
lines changed

CMakeLists.txt

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
cmake_minimum_required(VERSION 3.18)
22

3+
# Set CUDA flags early for compiler ID test
4+
# Check if cuda backend is requested before project() call
5+
if(DEFINED QOCO_ALGEBRA_BACKEND AND QOCO_ALGEBRA_BACKEND STREQUAL "cuda")
6+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -allow-unsupported-compiler")
7+
set(CMAKE_CUDA_FLAGS_INIT "${CMAKE_CUDA_FLAGS_INIT} -allow-unsupported-compiler")
8+
# Also set via cache to ensure it's picked up during compiler detection
9+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -allow-unsupported-compiler" CACHE STRING "Flags for CUDA compiler")
10+
endif()
11+
312
set(QOCO_VERSION_MAJOR "0")
413
set(QOCO_VERSION_MINOR "1")
514
set(QOCO_VERSION_PATCH "6")
615
set(QOCO_VERSION ${QOCO_VERSION_MAJOR}.${QOCO_VERSION_MINOR}.${QOCO_VERSION_PATCH})
716

817
# Project name
9-
project(qoco VERSION ${QOCO_VERSION})
18+
project(qoco VERSION ${QOCO_VERSION} LANGUAGES C CXX)
1019
message(STATUS "Building QOCO v${QOCO_VERSION}")
1120

1221
# Detect operating system.
@@ -112,15 +121,21 @@ endif()
112121
set(QOCO_ALGEBRA_BACKEND
113122
"builtin"
114123
CACHE STRING "The Algebra to use")
124+
125+
# CUDA flags are set early if needed
115126
add_subdirectory(algebra)
116127

117128
get_property(qoco_sources GLOBAL PROPERTY QOCO_SOURCES)
118129
get_property(qoco_headers GLOBAL PROPERTY QOCO_HEADERS)
119130
get_property(qoco_include GLOBAL PROPERTY QOCO_INCLUDE)
120131

132+
# Get CUDA libraries if using CUDA backend
133+
get_property(qoco_cuda_libs GLOBAL PROPERTY QOCO_CUDA_LIBS)
134+
121135
# Build qoco shared library.
122136
add_library(qoco SHARED)
123137
target_link_libraries(qoco qdldlobject amd)
138+
target_link_libraries(qoco ${qoco_cuda_libs})
124139

125140
if(IS_LINUX OR IS_MACOS)
126141
target_link_libraries(qoco m)
@@ -129,9 +144,25 @@ endif()
129144
target_include_directories(qoco PUBLIC ${qoco_include})
130145
target_sources(qoco PRIVATE ${qoco_sources})
131146

147+
# Enable CUDA if using CUDA backend
148+
if(${QOCO_ALGEBRA_BACKEND} STREQUAL "cuda")
149+
enable_language(CUDA)
150+
set_target_properties(qoco PROPERTIES
151+
CUDA_SEPARABLE_COMPILATION ON
152+
CUDA_RESOLVE_DEVICE_SYMBOLS ON
153+
)
154+
# Add HAVE_CUDSS definition if cuDSS library was found
155+
get_property(qoco_cuda_libs GLOBAL PROPERTY QOCO_CUDA_LIBS)
156+
if("${qoco_cuda_libs}" MATCHES "cudss")
157+
target_compile_definitions(qoco PRIVATE HAVE_CUDSS)
158+
message(STATUS "Added HAVE_CUDSS to qoco target")
159+
endif()
160+
endif()
161+
132162
# Build qoco static library.
133163
add_library(qocostatic STATIC)
134164
target_link_libraries(qocostatic qdldlobject amd)
165+
target_link_libraries(qocostatic ${qoco_cuda_libs})
135166

136167
if(IS_LINUX OR IS_MACOS)
137168
target_link_libraries(qocostatic m)
@@ -140,6 +171,22 @@ endif()
140171
target_include_directories(qocostatic PUBLIC ${qoco_include})
141172
target_sources(qocostatic PRIVATE ${qoco_sources})
142173

174+
# Enable CUDA if using CUDA backend
175+
if(${QOCO_ALGEBRA_BACKEND} STREQUAL "cuda")
176+
set_target_properties(qocostatic PROPERTIES
177+
CUDA_SEPARABLE_COMPILATION ON
178+
CUDA_RESOLVE_DEVICE_SYMBOLS ON
179+
)
180+
# Add HAVE_CUDSS definition if cuDSS library was found
181+
get_property(qoco_cuda_libs GLOBAL PROPERTY QOCO_CUDA_LIBS)
182+
if("${qoco_cuda_libs}" MATCHES "cudss")
183+
target_compile_definitions(qocostatic PRIVATE HAVE_CUDSS)
184+
endif()
185+
endif()
186+
187+
target_include_directories(qocostatic PUBLIC ${qoco_include})
188+
target_sources(qocostatic PRIVATE ${qoco_sources})
189+
143190
# Build qoco demo.
144191
if(BUILD_QOCO_DEMO)
145192
add_executable(qoco_demo ${PROJECT_SOURCE_DIR}/examples/qoco_demo.c)

algebra/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,13 @@ if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${QOCO_ALGEBRA_BACKEND})
33
endif()
44

55
set_property(GLOBAL APPEND PROPERTY QOCO_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/${QOCO_ALGEBRA_BACKEND})
6+
set_property(GLOBAL APPEND PROPERTY QOCO_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR})
7+
8+
# Set backend define
9+
if(${QOCO_ALGEBRA_BACKEND} STREQUAL "cuda")
10+
add_compile_definitions(QOCO_ALGEBRA_BACKEND_CUDA)
11+
else()
12+
add_compile_definitions(QOCO_ALGEBRA_BACKEND_BUILTIN)
13+
endif()
14+
615
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${QOCO_ALGEBRA_BACKEND})

algebra/backend.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @file backend.h
3+
* @author Govind M. Chari <govindchari1@gmail.com>
4+
*
5+
* @section LICENSE
6+
*
7+
* Copyright (c) 2025, Govind M. Chari
8+
* This source code is licensed under the BSD 3-Clause License
9+
*
10+
* @section DESCRIPTION
11+
*
12+
* Includes the appropriate backend header based on QOCO_ALGEBRA_BACKEND.
13+
*/
14+
15+
#ifndef QOCO_BACKEND_H
16+
#define QOCO_BACKEND_H
17+
18+
#if defined(QOCO_ALGEBRA_BACKEND_BUILTIN) || !defined(QOCO_ALGEBRA_BACKEND_CUDA)
19+
#include "builtin/qdldl_backend.h"
20+
#elif defined(QOCO_ALGEBRA_BACKEND_CUDA)
21+
#include "cuda/cudss_backend.h"
22+
#else
23+
#error "Unknown algebra backend. Define QOCO_ALGEBRA_BACKEND_BUILTIN or QOCO_ALGEBRA_BACKEND_CUDA"
24+
#endif
25+
26+
#endif /* #ifndef QOCO_BACKEND_H */
27+

algebra/builtin/builtin_linalg.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,32 @@ QOCOInt get_length_vectorf(const QOCOVectorf* x)
102102
return x->len;
103103
}
104104

105+
void sync_vector_to_device_if_needed(QOCOVectorf* v)
106+
{
107+
// No-op for builtin backend (no device memory)
108+
(void)v;
109+
}
110+
111+
void set_solve_phase(int active)
112+
{
113+
// No-op for builtin backend (no device memory)
114+
(void)active;
115+
}
116+
117+
int get_solve_phase(void)
118+
{
119+
// Always return 0 for builtin backend (no device memory)
120+
return 0;
121+
}
122+
123+
void copy_vector_from_device(QOCOVectorf* src, QOCOFloat* dst, QOCOInt n)
124+
{
125+
// For builtin backend, just copy from host memory
126+
if (src && dst) {
127+
copy_arrayf(src->data, dst, n);
128+
}
129+
}
130+
105131
QOCOCscMatrix* get_csc_matrix(const QOCOMatrix* M)
106132
{
107133
return M->csc;

algebra/cuda/CMakeLists.txt

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Set CUDA flags before enabling language to allow unsupported GCC
2+
# Set CMAKE_CUDA_FLAGS_INIT before enable_language so it's used during compiler ID test
3+
set(CMAKE_CUDA_FLAGS_INIT "-allow-unsupported-compiler")
4+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -allow-unsupported-compiler")
5+
set(CMAKE_CUDA_STANDARD 14)
6+
set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
7+
8+
# Set environment variable as fallback for compiler ID test
9+
set(ENV{CMAKE_CUDA_FLAGS} "${CMAKE_CUDA_FLAGS} -allow-unsupported-compiler")
10+
11+
enable_language(CUDA)
12+
13+
find_package(CUDAToolkit REQUIRED)
14+
find_library(CUBLAS_LIB cublas PATHS ${CUDAToolkit_LIBRARY_DIR})
15+
find_library(CUSPARSE_LIB cusparse PATHS ${CUDAToolkit_LIBRARY_DIR})
16+
# Search for cuDSS in CU_DSS_ROOT first, then system paths
17+
if(DEFINED ENV{CU_DSS_ROOT})
18+
find_library(CUDSS_LIB cudss PATHS "$ENV{CU_DSS_ROOT}/lib" NO_DEFAULT_PATH)
19+
endif()
20+
if(NOT CUDSS_LIB)
21+
find_library(CUDSS_LIB cudss PATHS ${CUDAToolkit_LIBRARY_DIR})
22+
endif()
23+
24+
if(NOT CUDSS_LIB)
25+
message(WARNING "cuDSS library not found. You may need to install cuDSS separately.")
26+
message(STATUS "cuDSS can be obtained from NVIDIA Developer website")
27+
message(STATUS "Building with cuDSS stubs - full functionality requires cuDSS installation")
28+
# Create a dummy library variable to avoid errors
29+
set(CUDSS_LIB "")
30+
else()
31+
# Add HAVE_CUDSS definition - use CMAKE_CUDA_FLAGS to ensure it's passed to CUDA compiler
32+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -DHAVE_CUDSS")
33+
add_compile_definitions(HAVE_CUDSS)
34+
# Add include directory for cuDSS headers
35+
if(DEFINED ENV{CU_DSS_ROOT})
36+
include_directories("$ENV{CU_DSS_ROOT}/include")
37+
endif()
38+
message(STATUS "Found cuDSS library: ${CUDSS_LIB}")
39+
message(STATUS "Added HAVE_CUDSS definition to CUDA flags")
40+
endif()
41+
42+
set_property(GLOBAL APPEND PROPERTY QOCO_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cudss_backend.cu ${CMAKE_CURRENT_SOURCE_DIR}/cuda_linalg.cu)
43+
set_property(GLOBAL APPEND PROPERTY QOCO_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/cudss_backend.h)
44+
45+
# Add CUDA libraries to global property (will be used in main CMakeLists.txt)
46+
set_property(GLOBAL APPEND PROPERTY QOCO_CUDA_LIBS
47+
${CUBLAS_LIB}
48+
${CUSPARSE_LIB}
49+
)
50+
51+
if(CUDSS_LIB)
52+
set_property(GLOBAL APPEND PROPERTY QOCO_CUDA_LIBS ${CUDSS_LIB})
53+
endif()
54+

0 commit comments

Comments
 (0)