Skip to content

Commit bc7380c

Browse files
Merge origin/main into docs-fern-native-api
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
2 parents 332162c + 6e1241a commit bc7380c

72 files changed

Lines changed: 10947 additions & 1077 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,7 @@ fi
418418
if buildAll || hasArg cuopt; then
419419
cd "${REPODIR}"/python/cuopt
420420

421-
# $EXTRA_CMAKE_ARGS gets concatenated into a string with [*] and then we find/replace spaces with semi-colons
422-
SKBUILD_CMAKE_ARGS="-DCMAKE_PREFIX_PATH=${INSTALL_PREFIX};-DCMAKE_LIBRARY_PATH=${LIBCUOPT_BUILD_DIR};-DCMAKE_CUDA_ARCHITECTURES=${CUOPT_CMAKE_CUDA_ARCHITECTURES};${EXTRA_CMAKE_ARGS[*]// /;}" \
421+
SKBUILD_CMAKE_ARGS="-DCMAKE_PREFIX_PATH=${INSTALL_PREFIX};-DCMAKE_LIBRARY_PATH=${LIBCUOPT_BUILD_DIR};-DCMAKE_CUDA_ARCHITECTURES=${CUOPT_CMAKE_CUDA_ARCHITECTURES};$(IFS=';'; echo "${EXTRA_CMAKE_ARGS[*]}")" \
423422
python "${PYTHON_ARGS_FOR_INSTALL[@]}" .
424423
fi
425424

ci/build_wheel_libcuopt.sh

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,34 @@ fi
1717
# Install Boost and TBB
1818
bash ci/utils/install_boost_tbb.sh
1919

20-
# Install libuuid (needed by cuopt_grpc_server)
20+
# Install libuuid and LLVM's OpenMP runtime
2121
if command -v dnf &> /dev/null; then
22-
dnf install -y libuuid-devel
22+
# LLVM Toolset is distributed as a module on Rocky/RHEL 8.
23+
dnf module install -y llvm-toolset
24+
dnf install -y libuuid-devel libomp-devel
2325
elif command -v apt-get &> /dev/null; then
24-
apt-get update && apt-get install -y uuid-dev
26+
apt-get update
27+
apt-get install -y uuid-dev libomp-dev
2528
fi
2629

2730
# Install Protobuf + gRPC (protoc + grpc_cpp_plugin)
2831
bash ci/utils/install_protobuf_grpc.sh
2932

30-
export SKBUILD_CMAKE_ARGS="-DCUOPT_BUILD_WHEELS=ON;-DDISABLE_DEPRECATION_WARNING=ON"
33+
# Compile with GCC, but use LLVM libomp as the OpenMP runtime bundled in the wheel. Resolve the
34+
# versioned ELF library rather than an unversioned linker script or compiler-toolset indirection.
35+
LIBOMP_LIBRARY="$(
36+
ldconfig -p |
37+
awk '$1 ~ /^libomp\.so(\.[0-9]+)*$/ && !library { library = $NF }
38+
END { print library }'
39+
)"
40+
if [[ "${LIBOMP_LIBRARY}" != /* || ! -f "${LIBOMP_LIBRARY}" ]]; then
41+
echo "Could not resolve the LLVM OpenMP runtime: '${LIBOMP_LIBRARY}'" >&2
42+
exit 1
43+
fi
44+
45+
echo "Using LLVM OpenMP runtime: ${LIBOMP_LIBRARY}"
46+
47+
export SKBUILD_CMAKE_ARGS="-DOpenMP_gomp_LIBRARY:FILEPATH=${LIBOMP_LIBRARY}"
3148

3249
# OpenSSL 3 hints for libcuopt's own find_package(OpenSSL).
3350
#

cpp/CMakeLists.txt

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ list(APPEND CUOPT_CUDA_FLAGS -Xfatbin=-compress-all)
186186
if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.9 AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 13.0)
187187
list(APPEND CUOPT_CUDA_FLAGS -Xfatbin=--compress-level=3)
188188
endif ()
189-
list(APPEND CUOPT_CUDA_FLAGS -fopenmp)
190189

191190
# Add jobserver flags for parallel compilation if PARALLEL_LEVEL is set
192191
if (PARALLEL_LEVEL AND NOT "${PARALLEL_LEVEL}" STREQUAL "")
@@ -198,13 +197,14 @@ if (PARALLEL_LEVEL AND NOT "${PARALLEL_LEVEL}" STREQUAL "")
198197
endif ()
199198
endif ()
200199

201-
# The MIP solver requires OpenMP to work
202-
find_package(OpenMP REQUIRED)
200+
# The MIP solver requires OpenMP for both C++ and CUDA host code.
201+
find_package(OpenMP REQUIRED COMPONENTS CXX CUDA)
203202
message(VERBOSE "cuOpt: OpenMP found in ${OpenMP_CXX_INCLUDE_DIRS}")
204203

205-
# MPS/QPS parser supports compressed inputs via bzip2 and zlib
204+
# MPS/QPS parser supports compressed inputs via bzip2, zlib and lz4
206205
option(CUOPT_PARSER_WITH_BZIP2 "Build MPS parser with bzip2 decompression" ON)
207206
option(CUOPT_PARSER_WITH_ZLIB "Build MPS parser with zlib decompression" ON)
207+
option(CUOPT_PARSER_WITH_LZ4 "Build experimental fast MPS parser with LZ4 decompression" ON)
208208
if (CUOPT_PARSER_WITH_BZIP2)
209209
find_package(BZip2 REQUIRED)
210210
add_compile_definitions(MPS_PARSER_WITH_BZIP2)
@@ -213,6 +213,10 @@ if (CUOPT_PARSER_WITH_ZLIB)
213213
find_package(ZLIB REQUIRED)
214214
add_compile_definitions(MPS_PARSER_WITH_ZLIB)
215215
endif ()
216+
if (CUOPT_PARSER_WITH_LZ4)
217+
# No headers or link target needed; the experimental reader loads one liblz4 symbol at runtime.
218+
add_compile_definitions(MPS_PARSER_WITH_LZ4)
219+
endif ()
216220

217221
# Debug options
218222
if (CMAKE_BUILD_TYPE MATCHES Debug)
@@ -250,16 +254,30 @@ else ()
250254
find_package(RAFT REQUIRED)
251255
endif ()
252256

257+
rapids_cpm_find(simde 0.8.2
258+
CPM_ARGS
259+
GIT_REPOSITORY https://github.com/simd-everywhere/simde.git
260+
GIT_TAG v0.8.2
261+
GIT_SHALLOW TRUE
262+
DOWNLOAD_ONLY TRUE
263+
)
264+
265+
if (NOT TARGET simde::simde)
266+
add_library(simde::simde INTERFACE IMPORTED GLOBAL)
267+
set_target_properties(simde::simde
268+
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${simde_SOURCE_DIR}")
269+
endif ()
270+
253271
FetchContent_Declare(
254272
papilo
255-
GIT_REPOSITORY "https://github.com/scipopt/papilo.git"
273+
GIT_REPOSITORY "https://github.com/nguidotti/papilo.git"
256274
# We would want to get the main branch. However, the main branch
257275
# does not have some of the presolvers and settings that we need
258276
# Mainly, probing and clique merging.
259277
# This is the reason we are using the development branch
260278
# from Oct 12, 2025. Once these changes are merged into the main branch,
261279
#we can switch to the main branch.
262-
GIT_TAG "741a2b9c8155b249d6df574d758b4d97d4417520"
280+
GIT_TAG "0cfea20c5655249174dbd04f0fb7bd6b1f6e9a0c"
263281
GIT_PROGRESS TRUE
264282
EXCLUDE_FROM_ALL
265283
SYSTEM
@@ -293,13 +311,13 @@ set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_SAVED})
293311
# dejavu - header-only graph automorphism library for MIP symmetry detection
294312
# https://github.com/markusa4/dejavu (header-only, skip its CMakeLists.txt)
295313
FetchContent_Declare(
296-
dejavu
297-
GIT_REPOSITORY "https://github.com/markusa4/dejavu.git"
298-
GIT_TAG "v2.1"
299-
GIT_PROGRESS TRUE
300-
EXCLUDE_FROM_ALL
301-
SYSTEM
302-
SOURCE_SUBDIR _nonexistent
314+
dejavu
315+
GIT_REPOSITORY "https://github.com/markusa4/dejavu.git"
316+
GIT_TAG "v2.1"
317+
GIT_PROGRESS TRUE
318+
EXCLUDE_FROM_ALL
319+
SYSTEM
320+
SOURCE_SUBDIR _nonexistent
303321
)
304322
FetchContent_MakeAvailable(dejavu)
305323
message(STATUS "dejavu (graph automorphism): ${dejavu_SOURCE_DIR}")
@@ -369,7 +387,7 @@ if (NOT SKIP_GRPC_BUILD)
369387

370388
# Proto search paths: manual protos in src/grpc, generated data proto in src/grpc/codegen/generated
371389
set(PROTO_PATH_MANUAL "${CMAKE_CURRENT_SOURCE_DIR}/src/grpc")
372-
set(PROTO_PATH_GEN "${CMAKE_CURRENT_SOURCE_DIR}/src/grpc/codegen/generated")
390+
set(PROTO_PATH_GEN "${CMAKE_CURRENT_SOURCE_DIR}/src/grpc/codegen/generated")
373391

374392
# Generate C++ code from cuopt_remote_data.proto (auto-generated data definitions)
375393
set(DATA_PROTO_FILE "${PROTO_PATH_GEN}/cuopt_remote_data.proto")
@@ -436,23 +454,34 @@ if (BUILD_TESTS)
436454
endif ()
437455

438456
set(CUOPT_SRC_FILES)
457+
set(MPS_FAST_SRC_FILES)
439458
add_subdirectory(src)
440459

441460
# nvcc 13.0.3 ICE (signal 11) compiling sliding_window.cu with 7 GPU architectures;
442461
# --split-compile breaks the codegen into per-arch sub-jobs to avoid the crash
443462
set_source_files_properties(
444-
${CMAKE_CURRENT_SOURCE_DIR}/src/routing/local_search/sliding_window.cu
445-
PROPERTIES COMPILE_OPTIONS "--split-compile=0")
463+
${CMAKE_CURRENT_SOURCE_DIR}/src/routing/local_search/sliding_window.cu
464+
PROPERTIES COMPILE_OPTIONS "--split-compile=0")
446465

447466
if (HOST_LINEINFO)
448-
set_source_files_properties(${CUOPT_SRC_FILES} DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTIES COMPILE_OPTIONS "-g1")
467+
set_source_files_properties(${CUOPT_SRC_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTIES COMPILE_OPTIONS "-g1")
449468
endif ()
450469

470+
# Needed for the fast MPS parser, available on all x86-64-v3 compliant x86 CPUs (essentially since Haswell ~2013)
471+
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64|amd64)$" AND
472+
CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$")
473+
set_property(SOURCE ${MPS_FAST_SRC_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
474+
APPEND PROPERTY COMPILE_OPTIONS "-mbmi2;-mavx2;-msse4.2")
475+
endif ()
476+
477+
# TODO: figure out a set of flags for ARM that fits the range of CPUs we wish to support (neoverse?)
478+
# NEON should be universal on aarch64 and enough for our purposes (parsing) though
479+
451480
# Apply -UNDEBUG only to solver source files (not gRPC infrastructure).
452481
# Must happen before gRPC files are appended to CUOPT_SRC_FILES.
453482
# Uses APPEND to preserve any existing per-file options (e.g. -g1 from HOST_LINEINFO).
454483
if (DEFINE_ASSERT)
455-
set_property(SOURCE ${CUOPT_SRC_FILES} DIRECTORY ${CMAKE_SOURCE_DIR}
484+
set_property(SOURCE ${CUOPT_SRC_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
456485
APPEND PROPERTY COMPILE_OPTIONS "-UNDEBUG")
457486
endif ()
458487

@@ -479,7 +508,7 @@ if (NOT SKIP_GRPC_BUILD)
479508
# The conda-forge abseil shared library is built with NDEBUG and does not
480509
# export that symbol (abseil-cpp#1624). Without this, Debug builds fail
481510
# at runtime with "undefined symbol: absl::…::Mutex::Dtor".
482-
set_property(SOURCE ${GRPC_INFRA_FILES} DIRECTORY ${CMAKE_SOURCE_DIR}
511+
set_property(SOURCE ${GRPC_INFRA_FILES} DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
483512
APPEND PROPERTY COMPILE_OPTIONS "-DNDEBUG")
484513
endif (NOT SKIP_GRPC_BUILD)
485514

@@ -495,8 +524,8 @@ set_target_properties(cuopt
495524
)
496525

497526
target_compile_definitions(cuopt
498-
PUBLIC "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}"
499-
PUBLIC CUSPARSE_ENABLE_EXPERIMENTAL_API
527+
PUBLIC "CUOPT_LOG_ACTIVE_LEVEL=RAPIDS_LOGGER_LOG_LEVEL_${LIBCUOPT_LOGGING_LEVEL}"
528+
PUBLIC CUSPARSE_ENABLE_EXPERIMENTAL_API
500529
)
501530

502531
target_compile_options(cuopt
@@ -528,8 +557,8 @@ target_include_directories(cuopt PRIVATE
528557
)
529558

530559
target_include_directories(cuopt SYSTEM PRIVATE
531-
"${pslp_SOURCE_DIR}/include"
532-
"${dejavu_SOURCE_DIR}"
560+
"${pslp_SOURCE_DIR}/include"
561+
"${dejavu_SOURCE_DIR}"
533562
)
534563

535564
target_include_directories(cuopt
@@ -605,11 +634,13 @@ target_link_libraries(cuopt
605634
${CUDSS_LIB_FILE}
606635
PRIVATE
607636
${CUOPT_PRIVATE_CUDA_LIBS}
637+
simde::simde
638+
OpenMP::OpenMP_CXX
639+
OpenMP::OpenMP_CUDA
608640
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:protobuf::libprotobuf>
609641
$<$<BOOL:${CUOPT_ENABLE_GRPC}>:gRPC::grpc++>
610642
)
611643

612-
613644
# ##################################################################################################
614645
# - generate tests --------------------------------------------------------------------------------
615646
if (BUILD_TESTS)

cpp/cuopt_cli.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,13 @@ inline cuopt::init_logger_t dummy_logger(
9090
* .mps/.qps and their .gz/.bz2 variants → MPS parser;
9191
* anything else is rejected.
9292
* @param initial_solution_file Path to initial solution file in SOL format
93+
* @param mps_reader MPS reader implementation selected by the CLI
9394
* @param settings Merged solver settings (config file loaded in main, then CLI overrides applied)
9495
*/
9596
int run_single_file(const std::string& file_path,
9697
const std::string& initial_solution_file,
9798
bool solve_relaxation,
99+
cuopt::mathematical_optimization::io::mps_reader_type_t mps_reader,
98100
cuopt::mathematical_optimization::solver_settings_t<int, double>& settings)
99101
{
100102
cuopt::init_logger_t log(settings.get_parameter<std::string>(CUOPT_LOG_FILE),
@@ -108,7 +110,8 @@ int run_single_file(const std::string& file_path,
108110
{
109111
CUOPT_LOG_INFO("Reading file %s", base_filename.c_str());
110112
try {
111-
mps_data_model = cuopt::mathematical_optimization::io::read<int, double>(file_path);
113+
mps_data_model =
114+
cuopt::mathematical_optimization::io::read<int, double>(file_path, mps_reader);
112115
} catch (const std::logic_error& e) {
113116
CUOPT_LOG_ERROR("Parser exception: %s", e.what());
114117
parsing_failed = true;
@@ -287,8 +290,8 @@ int main(int argc, char* argv[])
287290
program.add_argument("filename")
288291
.help(
289292
"input problem file; format dispatched by extension (case-insensitive). "
290-
"Supported: .lp, .mps, .qps and their .gz / .bz2 compressed variants "
291-
"(e.g. .lp.gz, .mps.bz2, .qps.gz)")
293+
"Supported: .lp, .mps, .qps and their .gz / .bz2 / .lz4 compressed variants "
294+
"(e.g. .lp.gz, .mps.bz2, .qps.lz4).")
292295
.nargs(1)
293296
.required();
294297

@@ -306,6 +309,14 @@ int main(int argc, char* argv[])
306309
.help("path to parameter config file (key = value format, supports all parameters)")
307310
.default_value(std::string(""));
308311

312+
program.add_argument("--mps-reader")
313+
.help(
314+
"MPS reader implementation: default uses the production parser; experimental-fast uses the "
315+
"experimental SIMD parser for free-format LP/MIP/QP/QCQP (SOCP) .mps/.qps files and their "
316+
".gz/.bz2/.lz4 compressed variants")
317+
.default_value(std::string("default"))
318+
.choices("default", "experimental-fast");
319+
309320
program.add_argument("--dump-hyper-params")
310321
.help("print hyper-parameters only in config file format and exit")
311322
.default_value(false)
@@ -406,6 +417,12 @@ int main(int argc, char* argv[])
406417
const auto initial_solution_file = program.get<std::string>("--initial-solution");
407418
const auto solve_relaxation = program.get<bool>("--relaxation");
408419
const auto params_file = program.get<std::string>("--params-file");
420+
const auto mps_reader_arg = program.get<std::string>("--mps-reader");
421+
422+
auto mps_reader = cuopt::mathematical_optimization::io::mps_reader_type_t::default_reader;
423+
if (mps_reader_arg == "experimental-fast") {
424+
mps_reader = cuopt::mathematical_optimization::io::mps_reader_type_t::fast_experimental;
425+
}
409426

410427
cuopt::mathematical_optimization::solver_settings_t<int, double> settings;
411428
try {
@@ -435,5 +452,5 @@ int main(int argc, char* argv[])
435452
RAFT_CUDA_TRY(cudaSetDevice(0));
436453
}
437454

438-
return run_single_file(file_name, initial_solution_file, solve_relaxation, settings);
455+
return run_single_file(file_name, initial_solution_file, solve_relaxation, mps_reader, settings);
439456
}

cpp/include/cuopt/mathematical_optimization/constants.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
#define CUOPT_MIP_ZERO_HALF_CUTS "mip_zero_half_cuts"
7676
#define CUOPT_MIP_STRONG_CHVATAL_GOMORY_CUTS "mip_strong_chvatal_gomory_cuts"
7777
#define CUOPT_MIP_REDUCED_COST_STRENGTHENING "mip_reduced_cost_strengthening"
78+
#define CUOPT_MIP_RINS "mip_rins"
7879
#define CUOPT_MIP_OBJECTIVE_STEP "mip_objective_step"
7980
#define CUOPT_MIP_CUT_CHANGE_THRESHOLD "mip_cut_change_threshold"
8081
#define CUOPT_MIP_CUT_MIN_ORTHOGONALITY "mip_cut_min_orthogonality"
@@ -127,9 +128,19 @@
127128
#define CUOPT_MIP_HYPER_DIVING_NODE_LIMIT "mip_hyper_diving_node_limit"
128129
#define CUOPT_MIP_HYPER_DIVING_ITERATION_LIMIT_FACTOR "mip_hyper_diving_iteration_limit_factor"
129130
#define CUOPT_MIP_HYPER_DIVING_BACKTRACK_LIMIT "mip_hyper_diving_backtrack_limit"
130-
/* @brief Show per-strategy diving symbol in logs (true) instead of a generic 'D' */
131+
/* @brief Show per-strategy diving symbol in logs instead of a generic 'D' */
131132
#define CUOPT_MIP_HYPER_DIVING_SHOW_TYPE "mip_hyper_diving_show_type"
132133

134+
/* @brief Recursive sub-MIP (RINS) hyper-parameters */
135+
#define CUOPT_MIP_HYPER_SUBMIP_BASE_TARGET_FIXRATE "mip_hyper_submip_base_target_fixrate"
136+
#define CUOPT_MIP_HYPER_SUBMIP_MIN_FIXRATE "mip_hyper_submip_min_fixrate"
137+
#define CUOPT_MIP_HYPER_SUBMIP_MIN_FIXRATE_CAP "mip_hyper_submip_min_fixrate_cap"
138+
#define CUOPT_MIP_HYPER_SUBMIP_TARGET_MIP_GAP "mip_hyper_submip_target_mip_gap"
139+
#define CUOPT_MIP_HYPER_SUBMIP_NODE_LIMIT_BASE "mip_hyper_submip_node_limit_base"
140+
#define CUOPT_MIP_HYPER_SUBMIP_MAX_LEVEL "mip_hyper_submip_max_level"
141+
#define CUOPT_MIP_HYPER_SUBMIP_ITERATION_LIMIT_RATIO "mip_hyper_submip_iteration_limit_ratio"
142+
#define CUOPT_MIP_HYPER_SUBMIP_ENABLE_CPUFJ "mip_hyper_submip_enable_cpufj"
143+
133144
/* @brief MIP determinism mode constants */
134145
#define CUOPT_MODE_OPPORTUNISTIC 0
135146
#define CUOPT_MODE_DETERMINISTIC 1

0 commit comments

Comments
 (0)