Skip to content

refactor: split host-only members out of CUDA translation units - #1801

Draft
ramakrishnap-nv wants to merge 1 commit into
mainfrom
split/1-host-device-tus
Draft

refactor: split host-only members out of CUDA translation units#1801
ramakrishnap-nv wants to merge 1 commit into
mainfrom
split/1-host-device-tus

Conversation

@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

1 of 4 toward a CUDA-free client library. See #1798 for the full picture (that PR is superseded by this series).

What

Several classes are mostly host code but live entirely in .cu files, so anything needing their host-side members has to link the CUDA library. This separates them.

File Size CUDA-touching lines
math_optimization/solver_settings.cu.cpp + _gpu.cu 713 5
mip_heuristics/solver_settings.cu.cu + .cpp 58 3
pdlp/solution_conversion.cu → + solution_conversion_cpu.cpp 225 23

math_optimization/solver_settings.cu is the clearest case — 713 lines of parameter handling with 5 lines that touch a stream.

The rule each split follows

Host code moves to the .cpp; members taking an rmm::cuda_stream_view or returning a device_uvector stay in the .cu; moved members are instantiated explicitly per-member rather than via template class.

That last point is load-bearing: template class in the host file would emit device ctors/dtors for members it cannot construct.

Gotcha worth knowing

The explicit instantiations are guarded on MIP_INSTANTIATE_* / PDLP_INSTANTIATE_*, so each new file must include mip_heuristics/mip_constants.hpp. Without it the guards evaluate false and the translation unit silently compiles to zero symbols — no error, just a link failure much later. I hit this during development; nm --defined-only on the object is how you catch it.

Risk

Low. Every moved definition is byte-identical and all files still build into libcuopt exactly as before — no target changes here. Also swaps thrust::count for std::count in solve_remote.cpp, which operates on a host vector.

Testing

Full build + 126 test binaries, 0 errors. 111/125 tests pass; the 14 failures are cudaErrorUnknown from a locally wedged nvidia_uvm, identical on unmodified main.

🤖 Generated with Claude Code

Several classes are mostly host code but live entirely in .cu files, which means
anything needing their host-side members has to link the CUDA library. This
separates them so the host halves compile as plain C++.

  math_optimization/solver_settings.cu -> .cpp + _gpu.cu   (713 lines, 5 CUDA)
  mip_heuristics/solver_settings.cu    -> .cu  + .cpp      (58 lines, 3 CUDA)
  pdlp/solution_conversion.cu          -> + solution_conversion_cpu.cpp

Each split follows one rule: host code moves to the .cpp, members taking an
rmm::cuda_stream_view or returning a device_uvector stay in the .cu, and the
moved members are instantiated explicitly per-member rather than via
`template class`. The distinction matters -- `template class` in the .cpp would
emit device ctors/dtors for members the host file cannot construct.

The explicit instantiations are guarded on MIP_INSTANTIATE_* / PDLP_INSTANTIATE_*,
so each new file includes mip_heuristics/mip_constants.hpp. Without it the guards
evaluate false and the translation unit silently compiles to zero symbols.

Also replaces thrust::count with std::count in solve_remote.cpp; it operates on
a host vector, so thrust was gratuitous.

No behaviour change: every moved definition is byte-identical, and all files
still build into libcuopt exactly as before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

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.

@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator Author

/ok to test

@github-actions

Copy link
Copy Markdown

CI Test Summary

8 failed · 1 passed · 4 skipped

wheel-tests-cuopt / 12.9.2, 3.14, amd64, ubuntu24.04, h100, latest-driver, latest-deps — 7 failed tests
  • tests/linear_programming/test_cpu_only_execution.py
  • tests/linear_programming/test_grpc_client.py
  • tests/linear_programming/test_incumbent_callbacks.py
  • tests/linear_programming/test_lp_solver.py
  • tests/linear_programming/test_parser.py
  • tests/linear_programming/test_python_API.py
  • tests/socp/test_socp.py
wheel-tests-cuopt / 13.3.0, 3.13, amd64, rockylinux8, rtxpro6000, latest-driver, latest-deps — 7 failed tests
  • tests/linear_programming/test_cpu_only_execution.py
  • tests/linear_programming/test_grpc_client.py
  • tests/linear_programming/test_incumbent_callbacks.py
  • tests/linear_programming/test_lp_solver.py
  • tests/linear_programming/test_parser.py
  • tests/linear_programming/test_python_API.py
  • tests/socp/test_socp.py
wheel-tests-cuopt / 12.2.2, 3.11, arm64, ubuntu22.04, a100, latest-driver, latest-deps — 7 failed tests
  • tests/linear_programming/test_cpu_only_execution.py
  • tests/linear_programming/test_grpc_client.py
  • tests/linear_programming/test_incumbent_callbacks.py
  • tests/linear_programming/test_lp_solver.py
  • tests/linear_programming/test_parser.py
  • tests/linear_programming/test_python_API.py
  • tests/socp/test_socp.py
wheel-tests-cuopt / 13.0.3, 3.12, arm64, rockylinux8, l4, latest-driver, latest-deps — 7 failed tests
  • tests/linear_programming/test_cpu_only_execution.py
  • tests/linear_programming/test_grpc_client.py
  • tests/linear_programming/test_incumbent_callbacks.py
  • tests/linear_programming/test_lp_solver.py
  • tests/linear_programming/test_parser.py
  • tests/linear_programming/test_python_API.py
  • tests/socp/test_socp.py
wheel-tests-cuopt / 12.9.2, 3.11, amd64, ubuntu22.04, l4, latest-driver, oldest-deps — 7 failed tests
  • tests/linear_programming/test_cpu_only_execution.py
  • tests/linear_programming/test_grpc_client.py
  • tests/linear_programming/test_incumbent_callbacks.py
  • tests/linear_programming/test_lp_solver.py
  • tests/linear_programming/test_parser.py
  • tests/linear_programming/test_python_API.py
  • tests/socp/test_socp.py
wheel-tests-cuopt / 13.3.0, 3.14, amd64, ubuntu26.04, rtxpro6000, latest-driver, latest-deps — 7 failed tests
  • tests/linear_programming/test_cpu_only_execution.py
  • tests/linear_programming/test_grpc_client.py
  • tests/linear_programming/test_incumbent_callbacks.py
  • tests/linear_programming/test_lp_solver.py
  • tests/linear_programming/test_parser.py
  • tests/linear_programming/test_python_API.py
  • tests/socp/test_socp.py
wheel-tests-cuopt / 13.0.3, 3.12, amd64, ubuntu24.04, rtxpro6000, latest-driver, latest-deps — 7 failed tests
  • tests/linear_programming/test_cpu_only_execution.py
  • tests/linear_programming/test_grpc_client.py
  • tests/linear_programming/test_incumbent_callbacks.py
  • tests/linear_programming/test_lp_solver.py
  • tests/linear_programming/test_parser.py
  • tests/linear_programming/test_python_API.py
  • tests/socp/test_socp.py
wheel-tests-cuopt / 13.3.0, 3.14, arm64, ubuntu26.04, l4, latest-driver, latest-deps — 7 failed tests
  • tests/linear_programming/test_cpu_only_execution.py
  • tests/linear_programming/test_grpc_client.py
  • tests/linear_programming/test_incumbent_callbacks.py
  • tests/linear_programming/test_lp_solver.py
  • tests/linear_programming/test_parser.py
  • tests/linear_programming/test_python_API.py
  • tests/socp/test_socp.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant