-
Notifications
You must be signed in to change notification settings - Fork 222
refactor: keep the GPU warm-start path out of host-only translation units #1803
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
base: split/2-devirtualize-to-optimization-problem
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -1637,4 +1637,77 @@ template CUOPT_EXPORT optimization_problem_t<int32_t, float> | |
| rmm::cuda_stream_view) const; | ||
| #endif | ||
|
|
||
| // GPU-target warm-start handling, declared in optimization_problem_utils.hpp. | ||
| // | ||
| // Defined here rather than inline in the header so that CUDA-free consumers of that | ||
| // header (the gRPC client in cuopt_client) never instantiate the device conversions. | ||
| template <typename i_t, typename f_t> | ||
| void apply_warmstart_gpu_target(solver_settings_t<i_t, f_t>* solver_settings, | ||
| const raft::handle_t* handle) | ||
| { | ||
| auto& pdlp = solver_settings->get_pdlp_settings(); | ||
|
|
||
| const bool has_view = (solver_settings->get_pdlp_warm_start_data_view() | ||
| .last_restart_duality_gap_dual_solution_.size() > 0); | ||
| const bool has_device_data = pdlp.get_pdlp_warm_start_data().is_populated(); | ||
| const bool has_host_data = pdlp.get_cpu_pdlp_warm_start_data().is_populated(); | ||
|
|
||
| if (!has_view && !has_device_data && !has_host_data) { return; } | ||
|
|
||
| if (has_view) { | ||
| // Warmstart from Python (spans over cuDF) -> solver needs device_uvectors. | ||
| pdlp_warm_start_data_t<i_t, f_t> warm_start(solver_settings->get_pdlp_warm_start_data_view(), | ||
| handle->get_stream()); | ||
| pdlp.set_pdlp_warm_start_data(warm_start); | ||
| } else if (has_device_data) { | ||
| // Already device-resident from the C++ API: nothing to do. | ||
| } else { | ||
| // Host warmstart -> GPU backend: convert H2D. | ||
| pdlp_warm_start_data_t<i_t, f_t> warm_start = | ||
| convert_to_gpu_warmstart(pdlp.get_cpu_pdlp_warm_start_data(), handle->get_stream()); | ||
| pdlp.set_pdlp_warm_start_data(warm_start); | ||
| } | ||
| } | ||
|
|
||
| // Null-handle CPU-target warm-start handling for callers that do have a device. | ||
| // | ||
| // Mirrors apply_warmstart_cpu_target() but adds the case that one cannot handle: warm | ||
| // start already sitting in device_uvectors, which needs a D2H copy before a remote solve. | ||
| // Dropping this silently loses a user's warm start on the | ||
| // populate_from_data_model_view(..., handle=nullptr) path (see cython_solve.cu). | ||
| template <typename i_t, typename f_t> | ||
| void apply_warmstart_cpu_target_with_device(solver_settings_t<i_t, f_t>* solver_settings) | ||
| { | ||
| auto& pdlp = solver_settings->get_pdlp_settings(); | ||
|
|
||
| // Already in host form. | ||
| if (pdlp.get_cpu_pdlp_warm_start_data().is_populated()) { return; } | ||
|
|
||
| // Warm-start view (host spans from Cython) -> CPU backend: copy directly, no CUDA needed. | ||
| if (solver_settings->get_pdlp_warm_start_data_view() | ||
| .last_restart_duality_gap_dual_solution_.size() > 0) { | ||
| pdlp.get_cpu_pdlp_warm_start_data() = | ||
| cpu_pdlp_warm_start_data_t<i_t, f_t>(solver_settings->get_pdlp_warm_start_data_view()); | ||
| return; | ||
| } | ||
|
|
||
| // Device-resident warm start -> CPU backend: convert D2H. | ||
| auto& gpu_ws = pdlp.get_pdlp_warm_start_data(); | ||
| if (gpu_ws.is_populated()) { | ||
| pdlp.get_cpu_pdlp_warm_start_data() = | ||
| convert_to_cpu_warmstart(gpu_ws, gpu_ws.current_primal_solution_.stream()); | ||
| } | ||
| } | ||
|
Comment on lines
+1640
to
+1700
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. 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift Add regression tests for warm-start target conversion. Add gtest coverage for host-view to CPU conversion, host-data to GPU conversion, and device-data to CPU conversion. This cohort adds these paths but includes no test change. As per coding guidelines, “Add unit tests.” 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
|
|
||
| #if MIP_INSTANTIATE_FLOAT | ||
| template CUOPT_EXPORT void apply_warmstart_gpu_target(solver_settings_t<int, float>*, | ||
| const raft::handle_t*); | ||
| template CUOPT_EXPORT void apply_warmstart_cpu_target_with_device(solver_settings_t<int, float>*); | ||
| #endif | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| #if MIP_INSTANTIATE_DOUBLE | ||
| template CUOPT_EXPORT void apply_warmstart_gpu_target(solver_settings_t<int, double>*, | ||
| const raft::handle_t*); | ||
| template CUOPT_EXPORT void apply_warmstart_cpu_target_with_device(solver_settings_t<int, double>*); | ||
| #endif | ||
|
|
||
| } // namespace cuopt::mathematical_optimization | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| /* clang-format off */ | ||
| /* | ||
| * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
| /* clang-format on */ | ||
|
|
||
| // Warm-start accessors of pdlp_solver_settings_t, split out of solver_settings.cu. | ||
| // | ||
| // These are trivial `return member_;` getters -- they hand back a reference and emit no | ||
| // device code, even where the referent is a GPU type. The gRPC client needs them, so they | ||
| // build into the CUDA-free cuopt_client library while the rest of the class (which does | ||
| // real thrust/rmm work) stays in solver_settings.cu. | ||
| // | ||
| // Only these members are instantiated below, deliberately NOT `template class`: the class | ||
| // holds a pdlp_warm_start_data_t, so instantiating all of it here would pull in device | ||
| // ctor/dtor code that belongs in the CUDA TU. | ||
|
|
||
| #include <cuopt/export.hpp> | ||
| #include <cuopt/mathematical_optimization/pdlp/solver_settings.hpp> | ||
|
|
||
| // Required: the explicit instantiations below are guarded on MIP_INSTANTIATE_* / | ||
| // PDLP_INSTANTIATE_*. Without this header those macros are undefined, the guards | ||
| // evaluate false, and this TU silently compiles to zero symbols. | ||
| #include <mip_heuristics/mip_constants.hpp> | ||
|
|
||
| namespace cuopt::mathematical_optimization { | ||
|
|
||
| template <typename i_t, typename f_t> | ||
| const cpu_pdlp_warm_start_data_t<i_t, f_t>& | ||
| pdlp_solver_settings_t<i_t, f_t>::get_cpu_pdlp_warm_start_data() const noexcept | ||
| { | ||
| return cpu_pdlp_warm_start_data_; | ||
| } | ||
|
|
||
| template <typename i_t, typename f_t> | ||
| cpu_pdlp_warm_start_data_t<i_t, f_t>& | ||
| pdlp_solver_settings_t<i_t, f_t>::get_cpu_pdlp_warm_start_data() noexcept | ||
| { | ||
| return cpu_pdlp_warm_start_data_; | ||
| } | ||
|
|
||
| template <typename i_t, typename f_t> | ||
| const pdlp_warm_start_data_view_t<i_t, f_t>& | ||
| pdlp_solver_settings_t<i_t, f_t>::get_pdlp_warm_start_data_view() const noexcept | ||
| { | ||
| return pdlp_warm_start_data_view_; | ||
| } | ||
|
|
||
| #if MIP_INSTANTIATE_FLOAT || PDLP_INSTANTIATE_FLOAT | ||
| template CUOPT_EXPORT const cpu_pdlp_warm_start_data_t<int, float>& | ||
| pdlp_solver_settings_t<int, float>::get_cpu_pdlp_warm_start_data() const noexcept; | ||
| template CUOPT_EXPORT cpu_pdlp_warm_start_data_t<int, float>& | ||
| pdlp_solver_settings_t<int, float>::get_cpu_pdlp_warm_start_data() noexcept; | ||
| template CUOPT_EXPORT const pdlp_warm_start_data_view_t<int, float>& | ||
| pdlp_solver_settings_t<int, float>::get_pdlp_warm_start_data_view() const noexcept; | ||
| #endif | ||
|
|
||
| #if MIP_INSTANTIATE_DOUBLE | ||
| template CUOPT_EXPORT const cpu_pdlp_warm_start_data_t<int, double>& | ||
| pdlp_solver_settings_t<int, double>::get_cpu_pdlp_warm_start_data() const noexcept; | ||
| template CUOPT_EXPORT cpu_pdlp_warm_start_data_t<int, double>& | ||
| pdlp_solver_settings_t<int, double>::get_cpu_pdlp_warm_start_data() noexcept; | ||
| template CUOPT_EXPORT const pdlp_warm_start_data_view_t<int, double>& | ||
| pdlp_solver_settings_t<int, double>::get_pdlp_warm_start_data_view() const noexcept; | ||
| #endif | ||
|
|
||
| } // namespace cuopt::mathematical_optimization |
Uh oh!
There was an error while loading. Please reload this page.