From 20ad11de6c8976956e53c0c27009fa81d97a67c2 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Thu, 16 Jul 2026 10:40:17 -0500 Subject: [PATCH 01/18] refactor(tests): link internal tests against cuopt_static Prerequisite structural work for enabling -fvisibility=hidden on libcuopt.so (issue #1213). - Introduce cuopt_objs OBJECT library so cuopt (shared) and cuopt_static (static, BUILD_TESTS only) share one compile step - Add STATIC_LIB option to ConfigureTest; when set, links cuopt_static and omits cuopttestutils to avoid transitive cuopt-shared pull-in - Route all tests with compiled internal symbol dependencies through STATIC_LIB: DUAL_SIMPLEX_TEST, LP_INTERNAL_TEST, PDLP_TEST, MPS_PARSER_TEST, most MIP tests, SOCP_TEST, ROUTING_INTERNAL_TEST - Create ROUTING_INTERNAL_TEST consolidating GES, scross, local-search candidate, and top-k tests; register previously unbuilt test files (l0_scross_test.cu, local_search_cand_test.cu, load_balancing_test.cu, feasibility_jump_tests.cu) - Add gRPC source files directly to GRPC_CLIENT_TEST and GRPC_INTEGRATION_TEST so they do not depend on internal symbols being exported from the shared library - Promote is_cusparse_runtime_mixed_precision_supported() to the public C API as cuOptIsCusparseRuntimeMixedPrecisionSupported(); update c_api_tests.cpp to use the public function Signed-off-by: Ramakrishna Prabhu --- cpp/CMakeLists.txt | 130 +++++++++++++----- .../cuopt/mathematical_optimization/cuopt_c.h | 8 ++ cpp/src/pdlp/cuopt_c.cpp | 8 ++ cpp/tests/CMakeLists.txt | 22 +-- cpp/tests/dual_simplex/CMakeLists.txt | 3 +- cpp/tests/linear_programming/CMakeLists.txt | 15 +- .../c_api_tests/c_api_tests.cpp | 7 +- .../linear_programming/grpc/CMakeLists.txt | 10 ++ cpp/tests/mip/CMakeLists.txt | 45 ++++-- cpp/tests/routing/CMakeLists.txt | 18 ++- cpp/tests/socp/CMakeLists.txt | 3 +- 11 files changed, 186 insertions(+), 83 deletions(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 61f6eb91df..e3f887dbe5 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -512,56 +512,41 @@ if (NOT SKIP_GRPC_BUILD) APPEND PROPERTY COMPILE_OPTIONS "-DNDEBUG") endif (NOT SKIP_GRPC_BUILD) -add_library(cuopt SHARED +add_library(cuopt_objs OBJECT ${CUOPT_SRC_FILES} ) -set_target_properties(cuopt - PROPERTIES BUILD_RPATH "\$ORIGIN" - INSTALL_RPATH "\$ORIGIN" - INTERFACE_POSITION_INDEPENDENT_CODE ON +set_target_properties(cuopt_objs + PROPERTIES POSITION_INDEPENDENT_CODE ON CXX_SCAN_FOR_MODULES OFF ) -target_compile_definitions(cuopt - PUBLIC "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}" - PUBLIC CUSPARSE_ENABLE_EXPERIMENTAL_API +target_compile_definitions(cuopt_objs + PUBLIC "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}" + PUBLIC CUSPARSE_ENABLE_EXPERIMENTAL_API ) -target_compile_options(cuopt +target_compile_options(cuopt_objs PRIVATE "$<$:${CUOPT_CXX_FLAGS}>" "$<$:${CUOPT_CUDA_FLAGS}>" ) -if (WRITE_FATBIN) - file(WRITE "${CUOPT_BINARY_DIR}/fatbin.ld" - [=[ - SECTIONS - { - .nvFatBinSegment : { *(.nvFatBinSegment) } - .nv_fatbin : { *(.nv_fatbin) } - } - ]=]) - target_link_options(cuopt PRIVATE "${CUOPT_BINARY_DIR}/fatbin.ld") -endif () - -add_library(cuopt::cuopt ALIAS cuopt) # ################################################################################################## # - include paths --------------------------------------------------------------------------------- message(STATUS "target include directories CUDSS_INCLUDES = ${CUDSS_INCLUDE}") # Adding Papilo as a system include messes up clang's include resolution if papilo is already installed as a conda package -target_include_directories(cuopt PRIVATE +target_include_directories(cuopt_objs PRIVATE "${papilo_SOURCE_DIR}/src" "${papilo_BINARY_DIR}" ) -target_include_directories(cuopt SYSTEM PRIVATE - "${pslp_SOURCE_DIR}/include" - "${dejavu_SOURCE_DIR}" +target_include_directories(cuopt_objs SYSTEM PRIVATE + "${pslp_SOURCE_DIR}/include" + "${dejavu_SOURCE_DIR}" ) -target_include_directories(cuopt +target_include_directories(cuopt_objs PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty" "${CMAKE_CURRENT_SOURCE_DIR}/src" @@ -581,8 +566,8 @@ target_include_directories(cuopt ) # Link PSLP by file to avoid export dependency tracking -target_link_libraries(cuopt PRIVATE $) -add_dependencies(cuopt PSLP) +target_link_libraries(cuopt_objs PRIVATE $) +add_dependencies(cuopt_objs PSLP) # ################################################################################################## # - link libraries -------------------------------------------------------------------------------- @@ -597,7 +582,7 @@ list(PREPEND CUOPT_PRIVATE_CUDA_LIBS CUDA::cublasLt) # Pass CUDSS_MT_LIB_FILE_NAME as a compile definition get_filename_component(CUDSS_MT_LIB_FILE_NAME "${CUDSS_MT_LIB_FILE}" NAME) -target_compile_definitions(cuopt PRIVATE CUDSS_MT_LIB_FILE_NAME="${CUDSS_MT_LIB_FILE_NAME}") +target_compile_definitions(cuopt_objs PRIVATE CUDSS_MT_LIB_FILE_NAME="${CUDSS_MT_LIB_FILE_NAME}") execute_process( COMMAND git rev-parse --short HEAD @@ -616,14 +601,14 @@ configure_file( ) # Add the generated include directory -target_include_directories(cuopt PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) +target_include_directories(cuopt_objs PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include) list(JOIN CMAKE_CUDA_ARCHITECTURES "," JOINED_CUDA_ARCHITECTURES) -target_compile_definitions(cuopt PUBLIC +target_compile_definitions(cuopt_objs PUBLIC CUOPT_CUDA_ARCHITECTURES="${JOINED_CUDA_ARCHITECTURES}" CUOPT_CPU_ARCHITECTURE="${CMAKE_SYSTEM_PROCESSOR}") -target_link_libraries(cuopt +target_link_libraries(cuopt_objs PUBLIC CUDA::cublas CUDA::cusparse @@ -634,9 +619,6 @@ target_link_libraries(cuopt ${CUDSS_LIB_FILE} PRIVATE ${CUOPT_PRIVATE_CUDA_LIBS} - simde::simde - OpenMP::OpenMP_CXX - OpenMP::OpenMP_CUDA $<$:protobuf::libprotobuf> $<$:gRPC::grpc++> ) @@ -645,9 +627,85 @@ target_link_libraries(cuopt # - generate tests -------------------------------------------------------------------------------- if (BUILD_TESTS) include(CTest) + add_library(cuopt_static STATIC $) + target_link_libraries(cuopt_static + PUBLIC + CUDA::cublas + CUDA::cusparse + rmm::rmm + rapids_logger::rapids_logger + CCCL::CCCL + raft::raft + ${CUDSS_LIB_FILE} + PRIVATE + ${CUOPT_PRIVATE_CUDA_LIBS} + $<$:protobuf::libprotobuf> + $<$:gRPC::grpc++> + ) + target_include_directories(cuopt_static + PUBLIC + "$" + "$" + "$" + ) + target_compile_definitions(cuopt_static PUBLIC + CUOPT_CUDA_ARCHITECTURES="${JOINED_CUDA_ARCHITECTURES}" + CUOPT_CPU_ARCHITECTURE="${CMAKE_SYSTEM_PROCESSOR}" + "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}" + CUSPARSE_ENABLE_EXPERIMENTAL_API + ) + target_link_libraries(cuopt_static PRIVATE $) + add_dependencies(cuopt_static PSLP) add_subdirectory(tests) endif (BUILD_TESTS) +add_library(cuopt SHARED $) +add_library(cuopt::cuopt ALIAS cuopt) +set_target_properties(cuopt + PROPERTIES BUILD_RPATH "\$ORIGIN" + INSTALL_RPATH "\$ORIGIN" + INTERFACE_POSITION_INDEPENDENT_CODE ON + CXX_SCAN_FOR_MODULES OFF + LINKER_LANGUAGE CUDA +) +# cuopt needs PUBLIC interface for consumers +target_include_directories(cuopt + PUBLIC + "$" + "$" + INTERFACE + "$" +) +target_link_libraries(cuopt + PUBLIC + CUDA::cublas + CUDA::cusparse + rmm::rmm + rapids_logger::rapids_logger + CCCL::CCCL + raft::raft + ${CUDSS_LIB_FILE} + PRIVATE + ${CUOPT_PRIVATE_CUDA_LIBS} + simde::simde + OpenMP::OpenMP_CXX + OpenMP::OpenMP_CUDA + $<$:protobuf::libprotobuf> + $<$:gRPC::grpc++> +) + +if (WRITE_FATBIN) + file(WRITE "${CUOPT_BINARY_DIR}/fatbin.ld" + [=[ + SECTIONS + { + .nvFatBinSegment : { *(.nvFatBinSegment) } + .nv_fatbin : { *(.nv_fatbin) } + } + ]=]) + target_link_options(cuopt PRIVATE "${CUOPT_BINARY_DIR}/fatbin.ld") +endif () + # ################################################################################################## # - install targets ------------------------------------------------------------------------------- diff --git a/cpp/include/cuopt/mathematical_optimization/cuopt_c.h b/cpp/include/cuopt/mathematical_optimization/cuopt_c.h index 218402a7ef..d66c908f1d 100644 --- a/cpp/include/cuopt/mathematical_optimization/cuopt_c.h +++ b/cpp/include/cuopt/mathematical_optimization/cuopt_c.h @@ -1055,6 +1055,14 @@ cuopt_int_t cuOptGetDualObjectiveValue(cuOptSolution solution, */ cuopt_int_t cuOptGetReducedCosts(cuOptSolution solution, cuopt_float_t* reduced_cost_ptr); +/** + * @brief Query whether the runtime cuSPARSE version supports mixed-precision SpMV + * (FP32 matrix × FP64 vector). Requires cuSPARSE >= 12.5 at runtime. + * + * @return 1 if supported, 0 otherwise. + */ +cuopt_int_t cuOptIsCusparseRuntimeMixedPrecisionSupported(); + #ifdef __cplusplus } #endif diff --git a/cpp/src/pdlp/cuopt_c.cpp b/cpp/src/pdlp/cuopt_c.cpp index 963bd6ada7..d07641cff6 100644 --- a/cpp/src/pdlp/cuopt_c.cpp +++ b/cpp/src/pdlp/cuopt_c.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -1296,3 +1297,10 @@ cuopt_int_t cuOptGetReducedCosts(cuOptSolution solution, cuopt_float_t* reduced_ return CUOPT_INVALID_ARGUMENT; } } + +cuopt_int_t cuOptIsCusparseRuntimeMixedPrecisionSupported() +{ + return cuopt::mathematical_optimization::pdlp::is_cusparse_runtime_mixed_precision_supported() + ? 1 + : 0; +} diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 27f6c94983..05c7e7a23a 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -37,11 +37,19 @@ endif() set(CUOPT_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # ################################################################ ------------------------------------------------------------------ -# ConfigureTest(NAME source1.cu source2.cu [LABELS label1 label2 ...]) +# ConfigureTest(NAME source1.cu source2.cu [STATIC_LIB] [LABELS label1 label2 ...]) # # LABELS sets CTest labels for selective local test execution via `ctest -L