-
Notifications
You must be signed in to change notification settings - Fork 122
Change solution object to return host memory instead of gpu memory from libcuopt for lp and milp #576
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change solution object to return host memory instead of gpu memory from libcuopt for lp and milp #576
Changes from 2 commits
79d5157
1ab34ab
2160bef
9ca1325
999a549
a72b785
1ea0702
1a5edbf
e735ee1
b9d5ea0
4a43461
0f4b100
7511a06
324b412
816cd21
582004d
5e62f50
d64f387
2880a7c
6e9f901
6632c56
0e66899
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -131,28 +131,21 @@ linear_programming_ret_t call_solve_lp( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const bool use_pdlp_solver_mode = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| auto solution = cuopt::linear_programming::solve_lp( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| op_problem, solver_settings, problem_checking, use_pdlp_solver_mode, is_batch_mode); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Convert device vectors to host vectors for LP solution | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| linear_programming_ret_t lp_ret{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>(solution.get_primal_solution().release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>(solution.get_dual_solution().release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>(solution.get_reduced_cost().release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().current_primal_solution_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().current_dual_solution_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().initial_primal_average_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().initial_dual_average_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().current_ATY_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().sum_primal_solutions_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().sum_dual_solutions_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().last_restart_duality_gap_primal_solution_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| std::make_unique<rmm::device_buffer>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().last_restart_duality_gap_dual_solution_.release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_primal_solution()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_dual_solution()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_reduced_cost()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().current_primal_solution_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().current_dual_solution_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().initial_primal_average_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().initial_dual_average_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().current_ATY_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().sum_primal_solutions_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().sum_dual_solutions_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().last_restart_duality_gap_primal_solution_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cuopt::host_copy(solution.get_pdlp_warm_start_data().last_restart_duality_gap_dual_solution_), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().initial_primal_weight_, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+151
to
160
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Skip warm-start host copies when we’re in batch mode. With this change every PDLP warm-start vector is eagerly Wrap these initializers so the copies only occur when @@
- cuopt::host_copy(solution.get_pdlp_warm_start_data().current_primal_solution_),
- cuopt::host_copy(solution.get_pdlp_warm_start_data().current_dual_solution_),
- cuopt::host_copy(solution.get_pdlp_warm_start_data().initial_primal_average_),
- cuopt::host_copy(solution.get_pdlp_warm_start_data().initial_dual_average_),
- cuopt::host_copy(solution.get_pdlp_warm_start_data().current_ATY_),
- cuopt::host_copy(solution.get_pdlp_warm_start_data().sum_primal_solutions_),
- cuopt::host_copy(solution.get_pdlp_warm_start_data().sum_dual_solutions_),
- cuopt::host_copy(solution.get_pdlp_warm_start_data().last_restart_duality_gap_primal_solution_),
- cuopt::host_copy(solution.get_pdlp_warm_start_data().last_restart_duality_gap_dual_solution_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().current_primal_solution_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().current_dual_solution_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().initial_primal_average_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().initial_dual_average_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().current_ATY_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().sum_primal_solutions_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().sum_dual_solutions_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().last_restart_duality_gap_primal_solution_),
+ is_batch_mode ? std::vector<double>{}
+ : cuopt::host_copy(solution.get_pdlp_warm_start_data().last_restart_duality_gap_dual_solution_),(or compute the vectors above the initializer and reuse them). That preserves existing semantics while avoiding unnecessary transfers in the batch path. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().initial_step_size_, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_pdlp_warm_start_data().total_pdlp_iterations_, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -194,7 +187,9 @@ mip_ret_t call_solve_mip( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error_type_t::ValidationError, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "MIP solve cannot be called on an LP problem!"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| auto solution = cuopt::linear_programming::solve_mip(op_problem, solver_settings); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mip_ret_t mip_ret{std::make_unique<rmm::device_buffer>(solution.get_solution().release()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Convert device vector to host vector for MILP solution | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mip_ret_t mip_ret{cuopt::host_copy(solution.get_solution()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_termination_status(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_error_status().get_error_type(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| solution.get_error_status().what(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 2174
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 112
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 2788
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 40
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 1252
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 6185
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 3206
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 38
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 2594
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 82
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 38
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 1281
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 166
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 311
🏁 Script executed:
Repository: NVIDIA/cuopt
Length of output: 1177
Consider batching device-to-host transfers to reduce redundant synchronizations.
The
host_copyfunction includes an implicitstream_view.synchronize()(line 123 ofcopy_helpers.hpp). With 12 sequentialhost_copycalls here, this creates 12 synchronization barriers—one per call—instead of a single barrier. Whileraft::copyprovides built-in CUDA error checking, consolidating the copies into a batched operation with one synchronization at the end would be more efficient:🤖 Prompt for AI Agents