build: add the CUDA-free cuopt_client library - #1804
Draft
ramakrishnap-nv wants to merge 1 commit into
Draft
Conversation
With the host code now separable, this adds the target that makes use of it. cuopt_client holds the host-side problem representation (parsers, data_model_view, mps_data_model, writers), the gRPC wire protocol (generated protos + mappers) and the gRPC clients for both LP/MIP and routing. libcuopt and cuopt_grpc_server both link it, so there is one mapper implementation rather than a client-side fork. Both gRPC arms qualify: the routing mappers added in #1597 reference no raft/rmm/thrust either. solve_remote.cpp stays in libcuopt -- it is the local-vs-remote dispatcher and calls into the GPU solver. Built as an OBJECT library plus a SHARED library, mirroring cuopt_objs/cuopt. cuopt_static embeds the objects directly rather than linking the shared library, because the internal test binaries reach parser internals such as mps_phase_registry_t. Two build details worth knowing: * cuopt_client uses default visibility, deliberately unlike cuopt_objs. libcuopt depends on roughly 214 of its symbols -- essentially the whole host-side API -- because this library was carved out of the internals rather than designed as a curated CUOPT_EXPORT surface. Hiding them makes libcuopt.so fail to load with "undefined symbol: grpc_client_t::solve_mip". * logger.cpp moves into the client sources: both the parsers and the gRPC code include <utilities/logger.hpp>, so without it the library has an unresolved reference to the logger. Result: libcuopt_client.so NEEDED: libgrpc++, libprotobuf, libabseil, librapids_logger, libc, libstdc++, libgomp, libdl -- no libcudart, no rmm, no raft, no cudss ldd -r over libcuopt.so + libcuopt_client.so: 0 unresolved symbols Note that raft/rmm headers are still needed at *build* time (the CPU headers transitively include them), which costs nothing at runtime because the device getters throw. Separating the headers is follow-up work, and is what a standalone client package would additionally require. 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. |
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.
4 of 4 toward a CUDA-free client library. Stacked on #1803. This is the payoff PR — almost entirely CMake, since #1801–#1803 did the code work.
Why
Calling a remote
cuopt_grpc_servercurrently requires the full GPU stack.pip install cuoptpullscudf,cupy-cuda13x[ctk],rmm,pylibraft,numba-cuda,scipy,pandasandlibcuoptonto a machine that only serializes protobuf over a socket.The motivating consumer is an MCP server: it imports only
Client,TlsConfig,DataModel,Read,SolverSettings— noSolve— yet installs the entire CUDA stack today.What
cuopt_clientholds the host-side problem representation (parsers,data_model_view,mps_data_model, writers), the gRPC wire protocol (generated protos + mappers) and the gRPC clients for both LP/MIP and routing.libcuoptandcuopt_grpc_serverboth link it — one mapper implementation, not a client-side fork.Both gRPC arms qualify: the routing mappers from #1597 reference no raft/rmm/thrust either.
solve_remote.cppstays inlibcuopt— it's the local-vs-remote dispatcher and calls into the GPU solver.Two build details worth reviewing
Object + shared library pair, mirroring
cuopt_objs/cuopt.cuopt_staticembeds the objects directly rather than linking the shared library, because internal test binaries reach parser internals likemps_phase_registry_t. Linking the shared library instead produces link failures inMPS_FAST_PARSER_TEST,GRPC_CLIENT_TESTandPDLP_MG_TEST.Default visibility, deliberately unlike
cuopt_objs.cuopt_objscan hide everything not markedCUOPT_EXPORTbecauselibcuopthas a curated public API.cuopt_clientis different — it was carved out of the internals, solibcuoptdepends on ~214 of its symbols (essentially the wholecpu_optimization_problem_t/data_model_view_t/mps_data_model_t/grpc_client_tsurface). With hidden visibility,libcuopt.sofails to load:Curating that would mean annotating essentially every host-side method. Open to opinions, but default visibility looks like the right trade.
Also:
logger.cppmoves into the client sources — both the parsers and the gRPC code include<utilities/logger.hpp>.Result
Known gaps
cuopt::routing::symbols still undefined — host-only accessors ofrouting::solver_settings_t/assignment_tinrouting/solver_settings.cuandassignment.cu. Same pattern as refactor: split host-only members out of CUDA translation units #1801; follow-up.solver_wrapper.pyx, and thecuopt-clientwheel /libcuopt-clientconda output all come next.cpu_optimization_problem_t.Testing
Full build + 126 test binaries, 0 errors. 111/125 pass; the 14 failures are
cudaErrorUnknownfrom a locally wedgednvidia_uvm, identical on unmodifiedmain. The GPU-dependent tests need a clean CI run to confirm.🤖 Generated with Claude Code