Skip to content

Make solver_settings_t buildable without the GPU library: plain parameter bases, shared registry, opaque device warm start - #2196

Closed
ramakrishnap-nv wants to merge 3 commits into
NVIDIA:mainfrom
ramakrishnap-nv:solver-settings-parameter-base
Closed

ramakrishnap-nv wants to merge 3 commits into
NVIDIA:mainfrom
ramakrishnap-nv:solver-settings-parameter-base

Conversation

@ramakrishnap-nv

@ramakrishnap-nv ramakrishnap-nv commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Description

pdlp_solver_settings_t and mip_solver_settings_t mix plain parameters with GPU-backed data. Constructing a solver_settings_t needed the CUDA translation unit (the device warm start was held by value) and its destructor needed rmm, so anything that only needs the parameters, such as a CPU-only remote client, had to link the GPU stack. The table of parameter names, defaults and ranges also lived in a CUDA translation unit.

This makes solver_settings_t usable without the GPU library, with no change to the public API.

  • Plain bases. New pdlp_parameters_t and mip_parameters_t (no CUDA, rmm or raft includes) hold the enums, tolerances_t and every plain user-facing member. The settings classes derive from them, so settings.tolerances.x, settings.time_limit, pdlp_solver_settings_t<>::tolerances_t and the rest keep working unchanged.
  • One registry. The name/default/range table and set/get_parameter*, load/dump_parameters_* move into solver_parameter_registry_t, built into the CPU-only cuopt_client library. solver_settings_t keeps its API and forwards to it.
  • Opaque device warm start. New opaque_ptr_t: an owning pointer with value semantics whose clone and destroy functions are recorded where the GPU library creates the object. pdlp_solver_settings_t holds the device warm start through it, created on first use. Copying clones the data, as a by-value member did. solver_settings_t() is now inline, so a CPU-only caller needs no GPU symbol to construct, copy or destroy one.

solver_settings_t stays the only settings type. This is groundwork for running the remote gRPC client and the Java client without CUDA or rmm at run time. That follow-up is not in this PR.

Longer term, the warm start and initial solutions are inputs to a solve rather than settings, and are better as their own objects with settings as a plain key/value store. That is an API change and is intentionally not part of this PR. When it lands, opaque_ptr_t is removed with no user-visible change.

Review notes

  • Source compatible, but the layout of pdlp_solver_settings_t / mip_solver_settings_t changes, so this is not binary compatible. Please flag anything that depends on that.
  • get_tolerances() and set_optimality_tolerance() moved inline into the bases; the dead pdlp_solver_settings_t::get_tolerances() declaration is now defined.
  • About 700 in-tree references across 121 files needed no call-site changes.
  • opaque_ptr_t copies clone the pointee. Tests cover that a copied settings object owns its own device warm start.

Testing

Built every target (ninja -k 0) with 0 errors. Passing locally: LP_UNIT_TEST 44 (new tests for opaque_ptr_t, copy ownership of the device warm start, every parameter name accepting its own default, and set-by-name reaching the members), GRPC_CLIENT_TEST 120, HEURISTICS_HYPER_PARAMS_TEST 19, QP_UNIT_TEST 22, SEMI_CONTINUOUS_TEST 3, MPS_FAST_PARSER_TEST 26, GRPC_PIPE_SERIALIZATION_TEST 21, and NUMOPT_INTERNAL_TEST 438 tests (run per suite). libcuopt_client.so has 0 rmm/CUDA/raft undefined symbols, and a JVM loads the Java gRPC client's native library with no rmm and no preload. A solver_settings_t-based C wrapper and the Java client's 7 live-server integration tests pass against the rebuilt server.

Not clean on my machine, and not compared against an unmodified baseline: the remaining failures in NUMOPT_INTERNAL_TEST, C_API_TEST, INCUMBENT_CALLBACK_TEST and CLI_TEST were each either a missing local dataset or an abort in cusparseSpMVOp_bufferSize (CUDA 13.3 toolkit with the conda cuSPARSE 12.8.2 runtime). The cuSPARSE abort also blocks the PDLP suites that would exercise warm start through this path end to end. DOC_EXAMPLE_TEST leaves a stale /tmp/user_problem.mps that fails its next run; that is existing behavior. I tested on a base a few commits behind main; the patch applies cleanly on main, but I did not rebuild there. The Python/Cython package was not built.

Checklist

  • I am familiar with the Contributing Guidelines.
  • Testing
    • New or existing tests cover these changes
    • Added tests
    • Created an issue to follow-up
    • NA
  • Documentation
    • The documentation is up to date with these changes
    • Added new documentation
    • NA

🤖 Generated with Claude Code

pdlp_solver_settings_t and mip_solver_settings_t mixed user-facing parameters with
GPU-backed data (rmm buffers, warm start, callbacks), so anything that needed only the
parameters had to link the GPU stack, and the parameter table lived next to the GPU code.

- Add pdlp_parameters_t and mip_parameters_t (new headers, no CUDA/rmm/raft includes). The
  settings classes now derive from them, so every member keeps its name and meaning.
- Move the name/default/range table and the set/get/file functions into
  solver_parameter_registry_t, built into the CPU-only cuopt_client library.
  solver_settings_t forwards to it.
- Add cpu_solver_settings_t, the counterpart of cpu_optimization_problem_t, on the same
  registry. A test checks it lists the same parameters and defaults as solver_settings_t.

Source compatible; the layout of the two settings classes changes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
@ramakrishnap-nv ramakrishnap-nv added non-breaking Introduces a non-breaking change improvement Improves an existing functionality labels Oct 21, 2026
@copy-pr-bot

copy-pr-bot Bot commented Oct 21, 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 and others added 2 commits October 21, 2026 13:13
…build CPU-only

pdlp_solver_settings_t held a pdlp_warm_start_data_t by value. Its default constructor is in a
CUDA translation unit and its destructor needs rmm, so constructing a solver_settings_t forced
every caller to link the GPU library, and its constructor could not live in the CPU-only client.

- Add opaque_ptr_t: an owning pointer with value semantics whose clone and destroy functions are
  recorded where the GPU library creates the object. Copying clones, like a by-value member.
- Hold the device warm start through it, created on first use by the GPU library.
- Define solver_settings_t's constructor inline, so a CPU-only caller needs no GPU symbol to
  construct, copy or destroy one.

No public API change. Tests cover opaque_ptr_t and that a copied settings object owns its own
device warm start.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
…type

With the device warm start behind an opaque pointer, solver_settings_t builds, copies and
destroys without any GPU symbol, so a separate CPU-only settings type is redundant and would
be a second type to keep in sync. Replace its tests with equivalent ones on solver_settings_t:
every parameter name accepts its own default, and setting by name reaches the members.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
@ramakrishnap-nv ramakrishnap-nv changed the title Split solver settings into plain parameter bases and a shared registry Make solver_settings_t buildable without the GPU library: plain parameter bases, shared registry, opaque device warm start Oct 21, 2026
@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator Author

Closing this proof of concept. The direction (plain settings, data objects separate, one unified settings object) is being written up as a design for the team to agree first; the spike branch stays available as a reference.

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

Labels

improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant