Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
03f3c2a
Add EVLOSER sparse solver scaffold
tamar-dewilde Jun 17, 2026
6a5b291
Add EVLOSER sparse solver option
tamar-dewilde Jun 17, 2026
a06e10b
Wire EVLOSER through sparse KKT systems
tamar-dewilde Jun 17, 2026
68f99f0
Add EVLOSER sparse solver coverage
tamar-dewilde Jun 17, 2026
bde1eed
Add EVLOSER sparse driver option
tamar-dewilde Jun 17, 2026
fef13b1
Clean EVLOSER sparse solver wrapper
tamar-dewilde Jun 17, 2026
dfe6c71
Add EVLOSER sparse driver tests
tamar-dewilde Jun 17, 2026
5e91f10
Add isolated EVLOSER embedded backend
tamar-dewilde Jun 17, 2026
5904032
Add EVLOSER matrix validation guards
tamar-dewilde Jun 17, 2026
70588e9
Make EVLOSER CSR ownership explicit
tamar-dewilde Jun 17, 2026
6e5e8d0
Refactor EVLOSER KLU factor setup
tamar-dewilde Jun 17, 2026
ac37203
Separate EVLOSER RF setup from matrix conversion
tamar-dewilde Jun 17, 2026
03c35a6
Make EVLOSER iterative refinement optional
tamar-dewilde Jun 17, 2026
25c0e63
Clean EVLOSER backend naming
tamar-dewilde Jun 17, 2026
d9f57cf
Add HIP EVLOSER sparse RAJA driver option
tamar-dewilde Jun 17, 2026
79b50d3
Allow EVLOSER option in HIP builds
tamar-dewilde Jun 17, 2026
2fe20bd
Use GPU backend wrappers in EVLOSER matrix storage
tamar-dewilde Jun 17, 2026
c8d981c
Add HIP EVLOSER RF backend support
tamar-dewilde Jun 17, 2026
c26f56b
Clean up EVLOSER sparse solver integration
tamar-dewilde Jun 17, 2026
2fa4e83
Enable CPU-only EVLOSER builds
tamar-dewilde Jun 24, 2026
59cb532
Add EVLOSER execution mode selection
tamar-dewilde Jun 24, 2026
b554dc7
Add KLU CPU execution to EVLOSER
tamar-dewilde Jun 24, 2026
18a7213
Add KLU refactorization recovery
tamar-dewilde Jun 24, 2026
0b993b5
Route HiOp CPU solves through EVLOSER
tamar-dewilde Jun 24, 2026
6d64eb0
Add EVLOSER CPU integration tests
tamar-dewilde Jun 25, 2026
240786a
Isolate EVLOSER from embedded ReSolve
tamar-dewilde Jun 25, 2026
3c54f72
Remove BLAS header include from EVLOSER MatrixCsr
tamar-dewilde Jun 26, 2026
fb29652
Fix EVLOSER CPU test include path
tamar-dewilde Jun 26, 2026
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
30 changes: 25 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,15 @@ cmake_dependent_option(
cmake_dependent_option(
HIOP_USE_MAGMA "Use Magma linear algebra" ON "HIOP_USE_GPU" OFF
)

cmake_dependent_option(
HIOP_USE_RESOLVE "Build with cuSolver LU support" ON "HIOP_USE_CUDA" OFF
HIOP_USE_RESOLVE "Build with ReSolve sparse solver support" ON "HIOP_USE_CUDA" OFF
)

option(
HIOP_USE_EVLOSER
"Enable the experimental EVLOSER sparse solver"
OFF
)

add_library(hiop_tpl INTERFACE)
Expand Down Expand Up @@ -357,12 +364,17 @@ if(HIOP_SPARSE)
endif()
endif(HIOP_USE_STRUMPACK)

if (HIOP_USE_RESOLVE)
if (HIOP_USE_RESOLVE OR HIOP_USE_EVLOSER)
set(HIOP_KLU_DIR CACHE PATH "Path to KLU directory")
include(FindKLU)
if(NOT KLU_LIBRARY)
message(STATUS "Cannot find KLU, disabling cuSOLVER LU module ...")
set(HIOP_USE_RESOLVE OFF CACHE BOOL "Build without cuSOLVER LU module." FORCE)
if(HIOP_USE_RESOLVE)
set(HIOP_USE_RESOLVE OFF CACHE BOOL "Build without cuSOLVER LU module." FORCE)
endif()
if(HIOP_USE_EVLOSER)
set(HIOP_USE_EVLOSER OFF CACHE BOOL "Build without EVLOSER." FORCE)
endif()
else()
target_link_libraries(hiop_tpl INTERFACE KLU)
endif()
Expand Down Expand Up @@ -394,14 +406,15 @@ if(HIOP_SPARSE)
endif()
endif(HIOP_USE_GINKGO)

if(NOT HIOP_USE_COINHSL AND NOT HIOP_USE_STRUMPACK AND NOT HIOP_USE_PARDISO AND NOT HIOP_USE_GINKGO)
if(NOT HIOP_USE_COINHSL AND NOT HIOP_USE_STRUMPACK AND NOT HIOP_USE_PARDISO AND NOT HIOP_USE_GINKGO AND NOT HIOP_USE_EVLOSER)
set(HIOP_SPARSE OFF CACHE BOOL "Build without sparse linear algebra" FORCE)
message(STATUS "Cannot find COINHSL, STRUMPACK, PARDISO nor GINKGO for sparse linear algebra, and the option HIOP_SPARSE will be disabled")
endif(NOT HIOP_USE_COINHSL AND NOT HIOP_USE_STRUMPACK AND NOT HIOP_USE_PARDISO AND NOT HIOP_USE_GINKGO)
endif()
else(HIOP_SPARSE)
set(HIOP_USE_COINHSL OFF CACHE BOOL "Build without COINHSL" FORCE)
set(HIOP_USE_STRUMPACK OFF CACHE BOOL "Build without STRUMPACK" FORCE)
set(HIOP_USE_RESOLVE OFF CACHE BOOL "Build without cuSOLVER LU module" FORCE)
set(HIOP_USE_EVLOSER OFF CACHE BOOL "Build without EVLOSER" FORCE)
set(HIOP_USE_PARDISO OFF CACHE BOOL "Build without PARDISO" FORCE)
set(HIOP_USE_GINKGO OFF CACHE BOOL "Build without GINKGO" FORCE)
endif(HIOP_SPARSE)
Expand Down Expand Up @@ -528,6 +541,13 @@ if (HIOP_WITH_MAKETEST)
add_test(NAME SparseMatrixTest COMMAND ${RUNCMD} "$<TARGET_FILE:testMatrixSparse>")
add_test(NAME SymmetricSparseMatrixTest COMMAND ${RUNCMD} "$<TARGET_FILE:testMatrixSymSparse>")

if(HIOP_USE_EVLOSER AND NOT HIOP_USE_GPU)
add_test(
NAME EVLOSERKLUCPU
COMMAND ${RUNCMD} "$<TARGET_FILE:testEVLOSERKLUCPU>"
)
endif()

# Test drivers in the form of user applications
add_subdirectory(src/Drivers)
endif(HIOP_WITH_MAKETEST)
54 changes: 45 additions & 9 deletions src/Drivers/Sparse/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@ target_link_libraries(NlpSparseEx3.exe HiOp::HiOp)
add_executable(NlpSparseEx4.exe NlpSparseEx4.cpp NlpSparseEx4Driver.cpp)
target_link_libraries(NlpSparseEx4.exe HiOp::HiOp)

if(HIOP_USE_RAJA)
if(HIOP_USE_GPU AND HIOP_USE_CUDA AND HIOP_USE_RESOLVE)
set_source_files_properties(
NlpSparseRajaEx2.cpp
NlpSparseRajaEx2Driver.cpp
PROPERTIES LANGUAGE CUDA
)

add_executable(NlpSparseRajaEx2.exe NlpSparseRajaEx2Driver.cpp NlpSparseRajaEx2.cpp)
# This driver used to be CUDA/ReSolve-only; EVLOSER adds the HIP path here too.
if(HIOP_USE_RAJA AND HIOP_USE_GPU AND (HIOP_USE_RESOLVE OR HIOP_USE_EVLOSER))
if(HIOP_USE_CUDA OR HIOP_USE_HIP)
if(HIOP_USE_CUDA)
set_source_files_properties(
NlpSparseRajaEx2.cpp
NlpSparseRajaEx2Driver.cpp
PROPERTIES LANGUAGE CUDA
)
endif()

add_executable(NlpSparseRajaEx2.exe NlpSparseRajaEx2Driver.cpp NlpSparseRajaEx2.cpp)
target_link_libraries(NlpSparseRajaEx2.exe HiOp::HiOp)
install(TARGETS NlpSparseRajaEx2.exe DESTINATION bin)
list(APPEND hiopSparseEx_INTERFACE_HEADERS NlpSparseRajaEx2.hpp)
Expand Down Expand Up @@ -56,6 +59,17 @@ add_test(NAME NlpSparse1_2 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseEx1.exe>" "
if(HIOP_USE_CUDA)
add_test(NAME NlpSparse1_3 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseEx1.exe>" "500" "-cusolver" "-selfcheck")
endif(HIOP_USE_CUDA)
# CPU-only EVLOSER integration test.
if(HIOP_USE_EVLOSER AND NOT HIOP_USE_GPU)
add_test(
NAME NlpSparse1_EVLOSER_CPU
COMMAND ${RUNCMD}
"$<TARGET_FILE:NlpSparseEx1.exe>"
"500"
"-evloser"
"-selfcheck"
)
endif()
if(HIOP_USE_PARDISO)
add_test(NAME NlpSparse1_4 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseEx1.exe>" "500" "-pardiso" "-selfcheck")
endif(HIOP_USE_PARDISO)
Expand All @@ -73,6 +87,18 @@ add_test(NAME NlpSparse2_2 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseEx2.exe>" "
if(HIOP_USE_CUDA)
add_test(NAME NlpSparse2_3 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseEx2.exe>" "500" "-cusolver" "-inertiafree" "-selfcheck")
endif(HIOP_USE_CUDA)
# CPU-only EVLOSER integration test with the required inertia-free configuration.
if(HIOP_USE_EVLOSER AND NOT HIOP_USE_GPU)
add_test(
NAME NlpSparse2_EVLOSER_CPU
COMMAND ${RUNCMD}
"$<TARGET_FILE:NlpSparseEx2.exe>"
"500"
"-evloser"
"-inertiafree"
"-selfcheck"
)
endif()
if(HIOP_USE_GINKGO)
add_test(NAME NlpSparse2_4 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseEx2.exe>" "500" "-ginkgo" "-inertiafree" "-selfcheck")
if(HIOP_USE_CUDA)
Expand All @@ -88,6 +114,16 @@ if(HIOP_USE_RAJA AND HIOP_USE_GPU AND HIOP_USE_CUDA AND HIOP_USE_RESOLVE)
add_test(NAME NlpSparseRaja2_2 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseRajaEx2.exe>" "500" "-inertiafree" "-selfcheck" "-resolve_cuda_rf")
endif()

# CUDA EVLOSER RF uses the same RAJA sparse driver as the ReSolve RF test.
if(HIOP_USE_RAJA AND HIOP_USE_GPU AND HIOP_USE_CUDA AND HIOP_USE_EVLOSER)
add_test(NAME NlpSparseRaja2_3 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseRajaEx2.exe>" "500" "-inertiafree" "-selfcheck" "-evloser_cuda_rf")
endif()

# HIP EVLOSER RF needs a separate test guard because ReSolve remains CUDA-only.
if(HIOP_USE_RAJA AND HIOP_USE_GPU AND HIOP_USE_HIP AND HIOP_USE_EVLOSER)
add_test(NAME NlpSparseRaja2_4 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseRajaEx2.exe>" "500" "-inertiafree" "-selfcheck" "-evloser_hip_rf")
endif()

add_test(NAME NlpSparse3_1 COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseEx3.exe>" "500" "-selfcheck")
if(HIOP_BUILD_SHARED AND NOT HIOP_USE_GPU )
add_test(NAME NlpSparseCinterface COMMAND ${RUNCMD} "$<TARGET_FILE:NlpSparseCEx1.exe>")
Expand Down
38 changes: 34 additions & 4 deletions src/Drivers/Sparse/NlpSparseEx1Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ static bool parse_arguments(int argc,
bool& self_check,
bool& use_pardiso,
bool& use_cusolver,
bool& use_evloser,
bool& use_ginkgo,
bool& use_ginkgo_cuda,
bool& use_ginkgo_hip,
bool& force_fr)
{
self_check = false;
use_pardiso = false;
use_evloser = false;
use_ginkgo = false;
use_ginkgo_cuda = false;
use_ginkgo_cuda = false;
use_ginkgo_hip = false;
force_fr = false;
n = 3;
scal = 1.0;
Expand All @@ -50,6 +52,8 @@ static bool parse_arguments(int argc,
use_pardiso = true;
} else if(std::string(argv[4]) == "-cusolver") {
use_cusolver = true;
} else if(std::string(argv[4]) == "-evloser") {
use_evloser = true;
} else if(std::string(argv[4]) == "-ginkgo") {
use_ginkgo = true;
} else if(std::string(argv[4]) == "-ginkgo_cuda") {
Expand All @@ -70,6 +74,8 @@ static bool parse_arguments(int argc,
use_pardiso = true;
} else if(std::string(argv[3]) == "-cusolver") {
use_cusolver = true;
} else if(std::string(argv[3]) == "-evloser") {
use_evloser = true;
} else if(std::string(argv[3]) == "-ginkgo") {
use_ginkgo = true;
} else if(std::string(argv[3]) == "-ginkgo_cuda") {
Expand All @@ -90,6 +96,8 @@ static bool parse_arguments(int argc,
use_pardiso = true;
} else if(std::string(argv[2]) == "-cusolver") {
use_cusolver = true;
} else if(std::string(argv[2]) == "-evloser") {
use_evloser = true;
} else if(std::string(argv[2]) == "-ginkgo") {
use_ginkgo = true;
} else if(std::string(argv[2]) == "-ginkgo_cuda") {
Expand All @@ -116,7 +124,8 @@ static bool parse_arguments(int argc,
scal = 1.0;
}

if(use_cusolver && use_pardiso) {
// EVLOSER follows the same sparse-LU driver path as cuSOLVER here.
if((use_cusolver || use_evloser) && use_pardiso) {
printf("Selected both, cuSOLVER and Pardiso. ");
printf("You can select only one linear solver.\n\n");
return false;
Expand Down Expand Up @@ -147,6 +156,15 @@ static bool parse_arguments(int argc,
}
#endif

// If EVLOSER is not available, de-select it.
#ifndef HIOP_USE_EVLOSER
if(use_evloser) {
printf("HiOp built without support for EVLOSER. ");
printf("Using default linear solver ...\n");
use_evloser = false;
}
#endif

return true;
};

Expand All @@ -164,6 +182,7 @@ static void usage(const char* exeName)
" '-pardiso' or '-cusolver': use Pardiso or cuSOLVER "
"as the linear solver [optional]\n");
printf(" '-cusolver': use cuSOLVER as the linear solver [optional]\n");
printf(" '-evloser': use EVLOSER as the linear solver [optional]\n");
printf(" '-fr': force to reset feasibility in the 1st iteration [optional]\n");
printf(
" '-selfcheck': compares the optimal objective with a previously saved value for the "
Expand All @@ -189,6 +208,7 @@ int main(int argc, char** argv)
bool selfCheck = false;
bool use_pardiso = false;
bool use_cusolver = false;
bool use_evloser = false;
bool use_ginkgo = false;
bool use_ginkgo_cuda = false;
bool use_ginkgo_hip = false;
Expand All @@ -203,6 +223,7 @@ int main(int argc, char** argv)
selfCheck,
use_pardiso,
use_cusolver,
use_evloser,
use_ginkgo,
use_ginkgo_cuda,
use_ginkgo_hip,
Expand Down Expand Up @@ -230,17 +251,26 @@ int main(int argc, char** argv)
if(use_pardiso) {
nlp.options->SetStringValue("linear_solver_sparse", "pardiso");
}
if(use_cusolver) {
// EVLOSER keeps the ReSolve RF settings below but selects the EVLOSER solver name.
if(use_cusolver || use_evloser) {
nlp.options->SetStringValue("duals_init", "zero");
nlp.options->SetStringValue("linsol_mode", "speculative");
nlp.options->SetStringValue("linear_solver_sparse", "resolve");
if(use_evloser) {
nlp.options->SetStringValue("linear_solver_sparse", "evloser");
} else {
nlp.options->SetStringValue("linear_solver_sparse", "resolve");
}

#if defined(HIOP_USE_CUDA) || defined(HIOP_USE_HIP)
// Device ReSolve and EVLOSER configurations use RF and hybrid execution.
nlp.options->SetStringValue("resolve_refactorization", "rf");
nlp.options->SetIntegerValue("ir_inner_maxit", 100);
nlp.options->SetNumericValue("ir_inner_tol", 1e-8);
nlp.options->SetIntegerValue("ir_inner_restart", 20);
nlp.options->SetIntegerValue("ir_inner_conv_cond", 2);
nlp.options->SetStringValue("ir_inner_gs_scheme", "cgs2");
nlp.options->SetStringValue("compute_mode", "hybrid");
#endif
// LU solver needs to use inertia free approach
nlp.options->SetStringValue("fact_acceptor", "inertia_free");
nlp.options->SetIntegerValue("ir_outer_maxit", 0);
Expand Down
Loading
Loading