refactor: make to_optimization_problem a free function - #1802
Draft
ramakrishnap-nv wants to merge 1 commit into
Draft
refactor: make to_optimization_problem a free function#1802ramakrishnap-nv wants to merge 1 commit into
ramakrishnap-nv wants to merge 1 commit into
Conversation
cpu_optimization_problem_t::to_optimization_problem() was a virtual member on
optimization_problem_interface_t. That put it in the vtable of every implementer,
including the CPU one -- so cpu_optimization_problem_t's vtable held an entry that
only libcuopt can define.
Vtable relocations are resolved eagerly at load time, unlike ordinary function
calls, so this cannot be deferred or hidden behind lazy binding. Any library
carrying that vtable is unloadable without libcuopt.so present.
It is now a free function declared in optimization_problem.hpp and defined in
cpu_optimization_problem_to_gpu.cpp, dispatching on the concrete type:
auto gpu = to_optimization_problem(problem, &handle);
The GPU override was a one-line `return nullptr` ("already a GPU problem"), so the
dispatch is a single dynamic_cast and the semantics are unchanged -- a GPU-backed
problem still yields nullptr. cpu_optimization_problem_t befriends the function to
reach its host-side storage.
Six call sites updated across pdlp/solve.cu, mip_heuristics/solve.cu,
grpc/server/grpc_worker.cpp and solution_interface_test.cu.
Splitting the definition into its own translation unit also keeps
<optimization_problem.hpp> and the raft handle out of cpu_optimization_problem.cpp,
which is otherwise pure host code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
This was referenced Aug 25, 2026
Collaborator
Author
|
/ok to test |
CI Test Summary⏭️ All 5 test job(s) skipped. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
2 of 4 toward a CUDA-free client library. Stacked on #1801 — review that first; the base will move to
mainonce it lands.The problem
to_optimization_problem()was avirtualmember onoptimization_problem_interface_t, so it occupied a slot in the vtable of every implementer — includingcpu_optimization_problem_t, whose vtable therefore held an entry onlylibcuoptcan define.Vtable relocations are resolved eagerly at load time, unlike ordinary function calls. So this cannot be deferred, hidden behind lazy binding, or worked around with a dispatch hook: any library carrying that vtable is unloadable without
libcuopt.sopresent.The change
Now a free function declared in
optimization_problem.hpp, defined incpu_optimization_problem_to_gpu.cpp, dispatching on the concrete type:The GPU override was a one-line
return nullptr("already a GPU problem"), so the dispatch is a singledynamic_castand semantics are unchanged — a GPU-backed problem still yieldsnullptr.cpu_optimization_problem_tbefriends the function to reach its host-side storage.6 call sites updated:
pdlp/solve.cu,mip_heuristics/solve.cu,grpc/server/grpc_worker.cpp, and two insolution_interface_test.cu.Bonus
Moving the definition to its own TU also keeps
<optimization_problem.hpp>and the raft handle out ofcpu_optimization_problem.cpp, which is otherwise pure host code.Discussion point
This trades a virtual for a
dynamic_cast. That's the deliberate choice — the alternative (keeping it virtual and dispatching through a registered function pointer) doesn't work, because the vtable slot still needs a definition at load time. Happy to discuss if there's a third option I've missed.Testing
Full build + 126 test binaries, 0 errors. 111/125 pass; the 14 failures are
cudaErrorUnknownfrom a locally wedgednvidia_uvm, identical on unmodifiedmain.🤖 Generated with Claude Code