|
1 | 1 | /* clang-format off */ |
2 | 2 | /* |
3 | | - * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
| 3 | + * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
4 | 4 | * SPDX-License-Identifier: Apache-2.0 |
5 | 5 | */ |
6 | 6 | /* clang-format on */ |
7 | 7 |
|
| 8 | +#include <cuopt/linear_programming/backend_selection.hpp> |
| 9 | +#include <cuopt/linear_programming/cpu_optimization_problem.hpp> |
8 | 10 | #include <cuopt/linear_programming/mip/solver_settings.hpp> |
9 | 11 | #include <cuopt/linear_programming/optimization_problem.hpp> |
| 12 | +#include <cuopt/linear_programming/optimization_problem_utils.hpp> |
10 | 13 | #include <cuopt/linear_programming/solve.hpp> |
11 | 14 | #include <mps_parser/parser.hpp> |
12 | 15 | #include <utilities/logger.hpp> |
@@ -89,7 +92,6 @@ int run_single_file(const std::string& file_path, |
89 | 92 | bool solve_relaxation, |
90 | 93 | const std::map<std::string, std::string>& settings_strings) |
91 | 94 | { |
92 | | - const raft::handle_t handle_{}; |
93 | 95 | cuopt::linear_programming::solver_settings_t<int, double> settings; |
94 | 96 |
|
95 | 97 | try { |
@@ -122,13 +124,31 @@ int run_single_file(const std::string& file_path, |
122 | 124 | return -1; |
123 | 125 | } |
124 | 126 |
|
125 | | - auto op_problem = |
126 | | - cuopt::linear_programming::mps_data_model_to_optimization_problem(&handle_, mps_data_model); |
| 127 | + // Determine memory backend and create problem using interface |
| 128 | + // Create handle only for GPU memory backend (avoid CUDA init on CPU-only hosts) |
| 129 | + auto memory_backend = cuopt::linear_programming::get_memory_backend_type(); |
| 130 | + std::unique_ptr<raft::handle_t> handle_ptr; |
| 131 | + std::unique_ptr<cuopt::linear_programming::optimization_problem_interface_t<int, double>> |
| 132 | + problem_interface; |
| 133 | + |
| 134 | + if (memory_backend == cuopt::linear_programming::memory_backend_t::GPU) { |
| 135 | + handle_ptr = std::make_unique<raft::handle_t>(); |
| 136 | + problem_interface = |
| 137 | + std::make_unique<cuopt::linear_programming::optimization_problem_t<int, double>>( |
| 138 | + handle_ptr.get()); |
| 139 | + } else { |
| 140 | + problem_interface = |
| 141 | + std::make_unique<cuopt::linear_programming::cpu_optimization_problem_t<int, double>>(); |
| 142 | + } |
| 143 | + |
| 144 | + // Populate the problem from MPS data model |
| 145 | + cuopt::linear_programming::populate_from_mps_data_model(problem_interface.get(), mps_data_model); |
127 | 146 |
|
128 | | - const bool is_mip = |
129 | | - (op_problem.get_problem_category() == cuopt::linear_programming::problem_category_t::MIP || |
130 | | - op_problem.get_problem_category() == cuopt::linear_programming::problem_category_t::IP) && |
131 | | - !solve_relaxation; |
| 147 | + const bool is_mip = (problem_interface->get_problem_category() == |
| 148 | + cuopt::linear_programming::problem_category_t::MIP || |
| 149 | + problem_interface->get_problem_category() == |
| 150 | + cuopt::linear_programming::problem_category_t::IP) && |
| 151 | + !solve_relaxation; |
132 | 152 |
|
133 | 153 | try { |
134 | 154 | auto initial_solution = |
@@ -157,10 +177,10 @@ int run_single_file(const std::string& file_path, |
157 | 177 | try { |
158 | 178 | if (is_mip) { |
159 | 179 | auto& mip_settings = settings.get_mip_settings(); |
160 | | - auto solution = cuopt::linear_programming::solve_mip(op_problem, mip_settings); |
| 180 | + auto solution = cuopt::linear_programming::solve_mip(problem_interface.get(), mip_settings); |
161 | 181 | } else { |
162 | 182 | auto& lp_settings = settings.get_pdlp_settings(); |
163 | | - auto solution = cuopt::linear_programming::solve_lp(op_problem, lp_settings); |
| 183 | + auto solution = cuopt::linear_programming::solve_lp(problem_interface.get(), lp_settings); |
164 | 184 | } |
165 | 185 | } catch (const std::exception& e) { |
166 | 186 | CUOPT_LOG_ERROR("Error: %s", e.what()); |
@@ -334,19 +354,23 @@ int main(int argc, char* argv[]) |
334 | 354 | const auto initial_solution_file = program.get<std::string>("--initial-solution"); |
335 | 355 | const auto solve_relaxation = program.get<bool>("--relaxation"); |
336 | 356 |
|
337 | | - // All arguments are parsed as string, default values are parsed as int if unused. |
338 | | - const auto num_gpus = program.is_used("--num-gpus") |
339 | | - ? std::stoi(program.get<std::string>("--num-gpus")) |
340 | | - : program.get<int>("--num-gpus"); |
341 | | - |
| 357 | + // Only initialize CUDA resources if using GPU memory backend (not remote execution) |
| 358 | + auto memory_backend = cuopt::linear_programming::get_memory_backend_type(); |
342 | 359 | std::vector<std::shared_ptr<rmm::mr::device_memory_resource>> memory_resources; |
343 | 360 |
|
344 | | - for (int i = 0; i < std::min(raft::device_setter::get_device_count(), num_gpus); ++i) { |
345 | | - cudaSetDevice(i); |
346 | | - memory_resources.push_back(make_async()); |
347 | | - rmm::mr::set_per_device_resource(rmm::cuda_device_id{i}, memory_resources.back().get()); |
| 361 | + if (memory_backend == cuopt::linear_programming::memory_backend_t::GPU) { |
| 362 | + // All arguments are parsed as string, default values are parsed as int if unused. |
| 363 | + const auto num_gpus = program.is_used("--num-gpus") |
| 364 | + ? std::stoi(program.get<std::string>("--num-gpus")) |
| 365 | + : program.get<int>("--num-gpus"); |
| 366 | + |
| 367 | + for (int i = 0; i < std::min(raft::device_setter::get_device_count(), num_gpus); ++i) { |
| 368 | + RAFT_CUDA_TRY(cudaSetDevice(i)); |
| 369 | + memory_resources.push_back(make_async()); |
| 370 | + rmm::mr::set_per_device_resource(rmm::cuda_device_id{i}, memory_resources.back().get()); |
| 371 | + } |
| 372 | + RAFT_CUDA_TRY(cudaSetDevice(0)); |
348 | 373 | } |
349 | | - cudaSetDevice(0); |
350 | 374 |
|
351 | 375 | return run_single_file(file_name, initial_solution_file, solve_relaxation, settings_strings); |
352 | 376 | } |
0 commit comments