From a2ec08a1b809f12331a2d2b089e3f834cadad49c Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Mon, 21 Sep 2026 10:05:48 -0500 Subject: [PATCH 01/10] Expose distributed (multi-GPU) PDLP settings in the Python API Distributed PDLP already exists in the C++ solver, registered as num_gpus, use_distributed_pdlp and distributed_pdlp_partitioner parameters, and worked generically through SolverSettings.set_parameter. This adds a typed DistributedPdlpPartitioner enum (core and thin client), wires use_distributed_pdlp/distributed_pdlp_partitioner into the REST server's solver_config model (num_gpus was already present), and documents the feature. Fixes NVIDIA#1931 Co-Authored-By: Claude Sonnet 5 --- docs/cuopt/source/convex-features.rst | 5 ++- docs/cuopt/source/convex-settings.rst | 25 ++++++++++- .../source/cuopt-c/convex/convex-c-api.rst | 13 ++++++ .../cuopt-server/client-api/sh-cli-api.rst | 5 +++ .../cuopt/linear_programming/__init__.py | 1 + .../solver_settings/__init__.py | 2 + .../solver_settings/solver_settings.pyx | 41 +++++++++++++++++- .../linear_programming/test_lp_solver.py | 25 +++++++++++ .../cuopt_sh_client/__init__.py | 3 +- .../thin_client_solver_settings.py | 42 +++++++++++++++++++ .../linear_programming/data_definition.py | 22 +++++++++- 11 files changed, 179 insertions(+), 5 deletions(-) diff --git a/docs/cuopt/source/convex-features.rst b/docs/cuopt/source/convex-features.rst index 82de2dbc78..9b3a0bf38f 100644 --- a/docs/cuopt/source/convex-features.rst +++ b/docs/cuopt/source/convex-features.rst @@ -325,4 +325,7 @@ By default, PDLP operates in the native precision of the problem type (FP64 for Multi-GPU Mode -------------- -Users can use multiple GPUs to solve a problem by specifying the ``num_gpus`` parameter. The feature is restricted to LP problems that uses concurrent mode and supports up to 2 GPUs at the moment. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. +Users can use multiple GPUs to solve a problem by specifying the ``num_gpus`` parameter, in one of two ways: + +- **Concurrent mode**: restricted to LP problems that use concurrent mode and supports up to 2 GPUs. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. +- **Distributed PDLP**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` (to use all visible GPUs) or to a value greater than 1, together with ``use_distributed_pdlp`` set to true, shards a single PDLP solve across multiple GPUs. Use ``distributed_pdlp_partitioner`` to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` and the ``DistributedPdlpPartitioner`` enum for the available strategies. diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index 22d290c7c2..f9ae7bc6e5 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -129,7 +129,30 @@ cuOpt will stop at the first limit (iteration or time) reached. Number of GPUs ^^^^^^^^^^^^^^ -``CUOPT_NUM_GPUS`` controls the number of GPUs to use for the solve. This setting is only relevant for LP problems that uses concurrent mode and supports up to 2 GPUs at the moment. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. +``CUOPT_NUM_GPUS`` controls the number of GPUs to use for the solve. + +For LP problems solved with ``Concurrent`` method, this setting supports up to 2 GPUs. Using this mode will run +PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. + +For LP problems solved with ``PDLP`` method, setting ``CUOPT_NUM_GPUS`` to ``-1`` or to a value greater than 1, +together with ``CUOPT_USE_DISTRIBUTED_PDLP`` set to true, distributes the PDLP solve across multiple GPUs. A +value of ``-1`` uses all GPUs visible to the process. + +Distributed PDLP +^^^^^^^^^^^^^^^^ + +``CUOPT_USE_DISTRIBUTED_PDLP`` controls whether PDLP should be distributed across multiple GPUs. It requires +``CUOPT_METHOD`` to be ``PDLP`` and ``CUOPT_NUM_GPUS`` to be ``-1`` or greater than 1. + +``CUOPT_DISTRIBUTED_PDLP_PARTITIONER`` controls how the problem is partitioned across the GPUs used by distributed +PDLP. Two strategies are available: ``KaMinPar``, a multi-threaded graph partitioner that generally produces better +balanced shards at the cost of extra partitioning time, and ``RoundRobin``, which assigns rows/columns across GPUs +in round-robin fashion without building a partitioning graph. ``Auto`` (the default) picks ``RoundRobin`` on a +single GPU and ``KaMinPar`` otherwise. + +C API users should use the constants defined in :ref:`distributed-pdlp-partitioner-constants` for this parameter. + +Server Thin client users should use the :class:`cuopt_sh_client.DistributedPdlpPartitioner` for this parameter. Infeasibility Detection diff --git a/docs/cuopt/source/cuopt-c/convex/convex-c-api.rst b/docs/cuopt/source/cuopt-c/convex/convex-c-api.rst index 0718361b81..068cdefe26 100644 --- a/docs/cuopt/source/cuopt-c/convex/convex-c-api.rst +++ b/docs/cuopt/source/cuopt-c/convex/convex-c-api.rst @@ -214,6 +214,8 @@ These constants are used as parameter names in the :c:func:`cuOptSetParameter`, .. doxygendefine:: CUOPT_SOLUTION_FILE .. doxygendefine:: CUOPT_NUM_CPU_THREADS .. doxygendefine:: CUOPT_NUM_GPUS +.. doxygendefine:: CUOPT_USE_DISTRIBUTED_PDLP +.. doxygendefine:: CUOPT_DISTRIBUTED_PDLP_PARTITIONER .. doxygendefine:: CUOPT_USER_PROBLEM_FILE .. doxygendefine:: CUOPT_PDLP_PRECISION @@ -230,6 +232,17 @@ These constants are used to configure `CUOPT_PDLP_SOLVER_MODE` via :c:func:`cuOp .. doxygendefine:: CUOPT_PDLP_SOLVER_MODE_METHODICAL1 .. doxygendefine:: CUOPT_PDLP_SOLVER_MODE_FAST1 +.. _distributed-pdlp-partitioner-constants: + +Distributed PDLP Partitioner Constants +--------------------------------------- + +These constants are used to configure `CUOPT_DISTRIBUTED_PDLP_PARTITIONER` via :c:func:`cuOptSetIntegerParameter`. + +.. doxygendefine:: CUOPT_DISTRIBUTED_PDLP_PARTITIONER_AUTO +.. doxygendefine:: CUOPT_DISTRIBUTED_PDLP_PARTITIONER_KAMINPAR +.. doxygendefine:: CUOPT_DISTRIBUTED_PDLP_PARTITIONER_ROUND_ROBIN + .. _pdlp-precision-constants: PDLP Precision Constants diff --git a/docs/cuopt/source/cuopt-server/client-api/sh-cli-api.rst b/docs/cuopt/source/cuopt-server/client-api/sh-cli-api.rst index a681fe180b..29204c1ea3 100644 --- a/docs/cuopt/source/cuopt-server/client-api/sh-cli-api.rst +++ b/docs/cuopt/source/cuopt-server/client-api/sh-cli-api.rst @@ -25,6 +25,11 @@ LP Supporting Classes :undoc-members: :no-inherited-members: +.. autoclass:: cuopt_sh_client.DistributedPdlpPartitioner + :members: + :undoc-members: + :no-inherited-members: + .. autoclass:: cuopt.linear_programming.data_model.DataModel :members: :undoc-members: diff --git a/python/cuopt/cuopt/linear_programming/__init__.py b/python/cuopt/cuopt/linear_programming/__init__.py index 835d09d76a..4ac795b67c 100644 --- a/python/cuopt/cuopt/linear_programming/__init__.py +++ b/python/cuopt/cuopt/linear_programming/__init__.py @@ -8,6 +8,7 @@ from cuopt.linear_programming.solution import Solution from cuopt.linear_programming.solver import BatchSolve, Solve from cuopt.linear_programming.solver_settings import ( + DistributedPdlpPartitioner, PDLPSolverMode, SolverMethod, SolverSettings, diff --git a/python/cuopt/cuopt/linear_programming/solver_settings/__init__.py b/python/cuopt/cuopt/linear_programming/solver_settings/__init__.py index 7d984489f2..84f505eb46 100644 --- a/python/cuopt/cuopt/linear_programming/solver_settings/__init__.py +++ b/python/cuopt/cuopt/linear_programming/solver_settings/__init__.py @@ -8,6 +8,7 @@ """ from .solver_settings import ( + DistributedPdlpPartitioner, PDLPSolverMode, SolverMethod, SolverSettings, @@ -19,6 +20,7 @@ solver_params = tuple(_solver_params_list) __all__ = [ + "DistributedPdlpPartitioner", "PDLPSolverMode", "SolverMethod", "SolverSettings", diff --git a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx index a5dcc78d18..b74e794492 100644 --- a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx +++ b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # noqa +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # cython: profile=False @@ -111,6 +111,45 @@ class PDLPSolverMode(IntEnum): return "%d" % self.value +class DistributedPdlpPartitioner(IntEnum): + """ + Enum representing the graph partitioning strategy used to split a + problem across GPUs when distributed (multi-GPU) PDLP is used, i.e. + when ``method`` is ``SolverMethod.PDLP`` and ``num_gpus`` is ``-1`` + or greater than ``1``. + + Attributes + ---------- + Auto + Automatically pick a partitioner: ``RoundRobin`` on a single GPU, + ``KaMinPar`` otherwise. + KaMinPar + Multi-threaded KaMinPar graph partitioner. Generally produces + better balanced shards at the cost of extra partitioning time. + RoundRobin + Round-robin assignment of rows/columns across GPUs, without + building a partitioning graph. + + Notes + ----- + Default value is Auto. + """ + + Auto = 0 + KaMinPar = auto() + RoundRobin = auto() + + def __str__(self): + """Convert the partitioner to a string. + + Returns + ------- + str + The string representation of the partitioner. + """ + return "%d" % self.value + + cdef class SolverSettings: def __init__(self): self.c_solver_settings.reset(new solver_settings_t[int, double]()) diff --git a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py index ae58752ffb..b891005861 100644 --- a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py +++ b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py @@ -19,12 +19,15 @@ CUOPT_ABSOLUTE_DUAL_TOLERANCE, CUOPT_ABSOLUTE_GAP_TOLERANCE, CUOPT_ABSOLUTE_PRIMAL_TOLERANCE, + CUOPT_DISTRIBUTED_PDLP_PARTITIONER, CUOPT_DUAL_INFEASIBLE_TOLERANCE, CUOPT_INFEASIBILITY_DETECTION, CUOPT_ITERATION_LIMIT, CUOPT_METHOD, CUOPT_MIP_HEURISTICS_ONLY, + CUOPT_NUM_GPUS, CUOPT_PDLP_SOLVER_MODE, + CUOPT_USE_DISTRIBUTED_PDLP, CUOPT_PRIMAL_INFEASIBLE_TOLERANCE, CUOPT_RELATIVE_DUAL_TOLERANCE, CUOPT_RELATIVE_GAP_TOLERANCE, @@ -39,6 +42,7 @@ LPTerminationStatus, ) from cuopt.linear_programming.solver_settings import ( + DistributedPdlpPartitioner, PDLPSolverMode, SolverMethod, SolverSettings, @@ -374,6 +378,27 @@ def test_solver_settings_basic(): PDLPSolverMode.Methodical1 ) + # Distributed (multi-GPU) PDLP settings + settings.set_parameter(CUOPT_NUM_GPUS, -1) + settings.set_parameter(CUOPT_USE_DISTRIBUTED_PDLP, True) + settings.set_parameter( + CUOPT_DISTRIBUTED_PDLP_PARTITIONER, + DistributedPdlpPartitioner.RoundRobin, + ) + + assert settings.get_parameter(CUOPT_NUM_GPUS) == -1 + assert settings.get_parameter(CUOPT_USE_DISTRIBUTED_PDLP) is True + assert settings.get_parameter(CUOPT_DISTRIBUTED_PDLP_PARTITIONER) == int( + DistributedPdlpPartitioner.RoundRobin + ) + + +def test_distributed_pdlp_partitioner_enum(): + assert int(DistributedPdlpPartitioner.Auto) == 0 + assert int(DistributedPdlpPartitioner.KaMinPar) == 1 + assert int(DistributedPdlpPartitioner.RoundRobin) == 2 + assert str(DistributedPdlpPartitioner.KaMinPar) == "1" + def test_solver_settings(tmp_path): """Push every registered parameter to the C++ layer via set_c_solver_settings.""" diff --git a/python/cuopt_self_hosted/cuopt_sh_client/__init__.py b/python/cuopt_self_hosted/cuopt_sh_client/__init__.py index 5a5481b6a6..1cab2f7a6b 100644 --- a/python/cuopt_self_hosted/cuopt_sh_client/__init__.py +++ b/python/cuopt_self_hosted/cuopt_sh_client/__init__.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 from cuopt_sh_client._version import __git_commit__, __version__ @@ -12,6 +12,7 @@ ) from .thin_client_solution import ThinClientSolution from .thin_client_solver_settings import ( + DistributedPdlpPartitioner, PDLPSolverMode, SolverMethod, ThinClientSolverSettings, diff --git a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py index fca85b33c3..2ef9b4dba9 100644 --- a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py +++ b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py @@ -67,6 +67,48 @@ def __str__(self): return "%d" % self.value +# Note these classes are only used on the thin client side. +# They are duplicates of the classes in +# cuopt.linear_programming.solver_settings.solver_settings +class DistributedPdlpPartitioner(IntEnum): + """ + Enum representing the graph partitioning strategy used to split a + problem across GPUs when distributed (multi-GPU) PDLP is used, i.e. + when ``method`` is ``SolverMethod.PDLP`` and ``num_gpus`` is ``-1`` + or greater than ``1``. + + Attributes + ---------- + Auto + Automatically pick a partitioner: ``RoundRobin`` on a single GPU, + ``KaMinPar`` otherwise. + KaMinPar + Multi-threaded KaMinPar graph partitioner. Generally produces + better balanced shards at the cost of extra partitioning time. + RoundRobin + Round-robin assignment of rows/columns across GPUs, without + building a partitioning graph. + + Notes + ----- + Default value is Auto. + """ + + Auto = 0 + KaMinPar = auto() + RoundRobin = auto() + + def __str__(self): + """Convert the partitioner to a string. + + Returns + ------- + str + The string representation of the partitioner. + """ + return "%d" % self.value + + class ThinClientSolverSettings: def __init__(self): self.parameter_dict = {} diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py index 7f25808372..8d804df49e 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py @@ -474,7 +474,27 @@ class SolverConfig(BaseModel): ) num_gpus: Optional[int] = Field( default=None, - description="Set the number of GPUs to use for LP solve.", + description="Set the number of GPUs to use for LP solve. For " + "distributed (multi-GPU) PDLP, use -1 to use all visible GPUs, " + "or a value greater than 1 to use that many GPUs.", + ) + use_distributed_pdlp: Optional[bool] = Field( + default=None, + description="Set True to distribute the PDLP solve of an LP " + "problem across multiple GPUs. Requires method to be PDLP and " + "num_gpus to be -1 or greater than 1.", + ) + distributed_pdlp_partitioner: Optional[int] = Field( + default=None, + description="Partitioner used to split the problem across GPUs " + "when use_distributed_pdlp is set:" + "
" + "- Auto: 0, pick automatically (RoundRobin on 1 GPU, " + "KaMinPar otherwise)" + "
" + "- KaMinPar: 1, multi-threaded KaMinPar graph partitioner" + "
" + "- RoundRobin: 2, round-robin assignment, no graph", ) augmented: Optional[int] = Field( default=-1, From 4a40af0fb79bd89d8b1b88f004e60de80c09ef49 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Mon, 21 Sep 2026 11:10:02 -0500 Subject: [PATCH 02/10] Note distributed PDLP GPU-resident dispatch dependency (#1958) Solving via DataModel/Solve builds the problem directly on the GPU; without the dispatch fix in NVIDIA/cuopt#1958, use_distributed_pdlp and distributed_pdlp_partitioner are stored but have no effect there (MPS file based solves are unaffected). Document this until #1958 lands. Co-Authored-By: Claude Sonnet 5 --- .../linear_programming/solver_settings/solver_settings.pyx | 6 ++++++ .../cuopt_sh_client/thin_client_solver_settings.py | 6 ++++++ .../utils/linear_programming/data_definition.py | 4 +++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx index b74e794492..4d82009801 100644 --- a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx +++ b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx @@ -133,6 +133,12 @@ class DistributedPdlpPartitioner(IntEnum): Notes ----- Default value is Auto. + + Distributed PDLP is dispatched from a problem built directly on the + GPU (as ``Solve`` does) only if the underlying cuOpt build includes the + GPU-resident dispatch fix (NVIDIA/cuopt#1958); until then, these + settings are stored but have no effect on the solve. MPS file based + solves are unaffected. """ Auto = 0 diff --git a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py index 2ef9b4dba9..46be34a78d 100644 --- a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py +++ b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py @@ -92,6 +92,12 @@ class DistributedPdlpPartitioner(IntEnum): Notes ----- Default value is Auto. + + Distributed PDLP is dispatched from a problem built directly on the + GPU only if the server's cuOpt build includes the GPU-resident + dispatch fix (NVIDIA/cuopt#1958); until then, these settings are + stored but have no effect on the solve. MPS file based solves are + unaffected. """ Auto = 0 diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py index 8d804df49e..ea1949ab5e 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py @@ -482,7 +482,9 @@ class SolverConfig(BaseModel): default=None, description="Set True to distribute the PDLP solve of an LP " "problem across multiple GPUs. Requires method to be PDLP and " - "num_gpus to be -1 or greater than 1.", + "num_gpus to be -1 or greater than 1. Requires a cuOpt build " + "with the GPU-resident distributed PDLP dispatch fix " + "(NVIDIA/cuopt#1958).", ) distributed_pdlp_partitioner: Optional[int] = Field( default=None, From 38a52b76285770ed979c41e50be5bfb23a426dc9 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Mon, 21 Sep 2026 11:12:21 -0500 Subject: [PATCH 03/10] Revert PR-number reference added to docstrings Volatile references like PR numbers don't age well in code comments per the repo's conventions (skills/cuopt-developer/references/conventions.md); that context belongs in the PR description, not the source. Co-Authored-By: Claude Sonnet 5 --- .../linear_programming/solver_settings/solver_settings.pyx | 6 ------ .../cuopt_sh_client/thin_client_solver_settings.py | 6 ------ .../utils/linear_programming/data_definition.py | 4 +--- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx index 4d82009801..b74e794492 100644 --- a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx +++ b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx @@ -133,12 +133,6 @@ class DistributedPdlpPartitioner(IntEnum): Notes ----- Default value is Auto. - - Distributed PDLP is dispatched from a problem built directly on the - GPU (as ``Solve`` does) only if the underlying cuOpt build includes the - GPU-resident dispatch fix (NVIDIA/cuopt#1958); until then, these - settings are stored but have no effect on the solve. MPS file based - solves are unaffected. """ Auto = 0 diff --git a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py index 46be34a78d..2ef9b4dba9 100644 --- a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py +++ b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py @@ -92,12 +92,6 @@ class DistributedPdlpPartitioner(IntEnum): Notes ----- Default value is Auto. - - Distributed PDLP is dispatched from a problem built directly on the - GPU only if the server's cuOpt build includes the GPU-resident - dispatch fix (NVIDIA/cuopt#1958); until then, these settings are - stored but have no effect on the solve. MPS file based solves are - unaffected. """ Auto = 0 diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py index ea1949ab5e..8d804df49e 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py @@ -482,9 +482,7 @@ class SolverConfig(BaseModel): default=None, description="Set True to distribute the PDLP solve of an LP " "problem across multiple GPUs. Requires method to be PDLP and " - "num_gpus to be -1 or greater than 1. Requires a cuOpt build " - "with the GPU-resident distributed PDLP dispatch fix " - "(NVIDIA/cuopt#1958).", + "num_gpus to be -1 or greater than 1.", ) distributed_pdlp_partitioner: Optional[int] = Field( default=None, From 6bdec48b8a8100bde0c7363c07560c7a7f9c353d Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Mon, 21 Sep 2026 15:41:44 -0500 Subject: [PATCH 04/10] Address CodeRabbit doc feedback: qualify num_gpus=-1 and document core Python usage -1 resolves to all visible GPUs, which is only one GPU on a single-GPU host; sharding requires more than one GPU actually selected. Also add a core Python SolverSettings example for distributed PDLP alongside the existing C/thin-client guidance. Co-Authored-By: Claude Sonnet 5 --- docs/cuopt/source/convex-features.rst | 2 +- docs/cuopt/source/convex-settings.rst | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/cuopt/source/convex-features.rst b/docs/cuopt/source/convex-features.rst index 9b3a0bf38f..fe2ec692d8 100644 --- a/docs/cuopt/source/convex-features.rst +++ b/docs/cuopt/source/convex-features.rst @@ -328,4 +328,4 @@ Multi-GPU Mode Users can use multiple GPUs to solve a problem by specifying the ``num_gpus`` parameter, in one of two ways: - **Concurrent mode**: restricted to LP problems that use concurrent mode and supports up to 2 GPUs. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. -- **Distributed PDLP**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` (to use all visible GPUs) or to a value greater than 1, together with ``use_distributed_pdlp`` set to true, shards a single PDLP solve across multiple GPUs. Use ``distributed_pdlp_partitioner`` to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` and the ``DistributedPdlpPartitioner`` enum for the available strategies. +- **Distributed PDLP**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` and the ``DistributedPdlpPartitioner`` enum for the available strategies. diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index f9ae7bc6e5..4b8ec36041 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -136,13 +136,15 @@ PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resou For LP problems solved with ``PDLP`` method, setting ``CUOPT_NUM_GPUS`` to ``-1`` or to a value greater than 1, together with ``CUOPT_USE_DISTRIBUTED_PDLP`` set to true, distributes the PDLP solve across multiple GPUs. A -value of ``-1`` uses all GPUs visible to the process. +value of ``-1`` uses all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; +multi-GPU sharding only happens when more than one GPU is actually selected. Distributed PDLP ^^^^^^^^^^^^^^^^ ``CUOPT_USE_DISTRIBUTED_PDLP`` controls whether PDLP should be distributed across multiple GPUs. It requires -``CUOPT_METHOD`` to be ``PDLP`` and ``CUOPT_NUM_GPUS`` to be ``-1`` or greater than 1. +``CUOPT_METHOD`` to be ``PDLP`` and ``CUOPT_NUM_GPUS`` to be ``-1`` or greater than 1 (as above, ``-1`` may +resolve to a single visible GPU, in which case the solve still runs but is not actually sharded). ``CUOPT_DISTRIBUTED_PDLP_PARTITIONER`` controls how the problem is partitioned across the GPUs used by distributed PDLP. Two strategies are available: ``KaMinPar``, a multi-threaded graph partitioner that generally produces better @@ -152,6 +154,24 @@ single GPU and ``KaMinPar`` otherwise. C API users should use the constants defined in :ref:`distributed-pdlp-partitioner-constants` for this parameter. +Python API users should use :class:`cuopt.linear_programming.DistributedPdlpPartitioner` for this parameter: + +.. code-block:: python + + from cuopt.linear_programming import ( + DistributedPdlpPartitioner, + SolverMethod, + SolverSettings, + ) + + settings = SolverSettings() + settings.set_parameter("method", SolverMethod.PDLP) + settings.set_parameter("num_gpus", -1) + settings.set_parameter("use_distributed_pdlp", True) + settings.set_parameter( + "distributed_pdlp_partitioner", DistributedPdlpPartitioner.KaMinPar + ) + Server Thin client users should use the :class:`cuopt_sh_client.DistributedPdlpPartitioner` for this parameter. From fa7f4b55f9c51221a21ba35efd70604fd258db7f Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Tue, 22 Sep 2026 07:49:04 -0500 Subject: [PATCH 05/10] Drop DistributedPdlpPartitioner enum, keep the setting a plain int Per review: unlike method/pdlp_solver_mode, this setting has no existing typed-enum precedent pulling it that direction, and most other enum-like int settings (presolve, augmented, folding, dualize, ordering, barrier_dual_initial_point) already ship as plain documented ints with no dedicated class. A dedicated enum needs propagating through every binding by hand; the plain int already flows through the generic parameter registry everywhere. Removed from core Python, thin client, and docs; distributed_pdlp_partitioner is now just an int (0/1/2). Co-Authored-By: Claude Sonnet 5 --- docs/cuopt/source/convex-features.rst | 2 +- docs/cuopt/source/convex-settings.rst | 24 +++++------ .../cuopt-server/client-api/sh-cli-api.rst | 5 --- .../cuopt/linear_programming/__init__.py | 1 - .../solver_settings/__init__.py | 2 - .../solver_settings/solver_settings.pyx | 39 ----------------- .../linear_programming/test_lp_solver.py | 18 ++------ .../cuopt_sh_client/__init__.py | 3 +- .../thin_client_solver_settings.py | 42 ------------------- 9 files changed, 15 insertions(+), 121 deletions(-) diff --git a/docs/cuopt/source/convex-features.rst b/docs/cuopt/source/convex-features.rst index fe2ec692d8..7a25d042dd 100644 --- a/docs/cuopt/source/convex-features.rst +++ b/docs/cuopt/source/convex-features.rst @@ -328,4 +328,4 @@ Multi-GPU Mode Users can use multiple GPUs to solve a problem by specifying the ``num_gpus`` parameter, in one of two ways: - **Concurrent mode**: restricted to LP problems that use concurrent mode and supports up to 2 GPUs. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. -- **Distributed PDLP**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` and the ``DistributedPdlpPartitioner`` enum for the available strategies. +- **Distributed PDLP**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` for the available strategies. diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index 4b8ec36041..3f09219d08 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -147,32 +147,28 @@ Distributed PDLP resolve to a single visible GPU, in which case the solve still runs but is not actually sharded). ``CUOPT_DISTRIBUTED_PDLP_PARTITIONER`` controls how the problem is partitioned across the GPUs used by distributed -PDLP. Two strategies are available: ``KaMinPar``, a multi-threaded graph partitioner that generally produces better -balanced shards at the cost of extra partitioning time, and ``RoundRobin``, which assigns rows/columns across GPUs -in round-robin fashion without building a partitioning graph. ``Auto`` (the default) picks ``RoundRobin`` on a -single GPU and ``KaMinPar`` otherwise. +PDLP: + +* ``0``: Auto (default) - picks ``RoundRobin`` on a single GPU and ``KaMinPar`` otherwise +* ``1``: KaMinPar - a multi-threaded graph partitioner that generally produces better balanced shards at the cost of + extra partitioning time +* ``2``: RoundRobin - assigns rows/columns across GPUs in round-robin fashion, without building a partitioning graph C API users should use the constants defined in :ref:`distributed-pdlp-partitioner-constants` for this parameter. -Python API users should use :class:`cuopt.linear_programming.DistributedPdlpPartitioner` for this parameter: +Python API users can set this parameter directly: .. code-block:: python - from cuopt.linear_programming import ( - DistributedPdlpPartitioner, - SolverMethod, - SolverSettings, - ) + from cuopt.linear_programming import SolverMethod, SolverSettings settings = SolverSettings() settings.set_parameter("method", SolverMethod.PDLP) settings.set_parameter("num_gpus", -1) settings.set_parameter("use_distributed_pdlp", True) - settings.set_parameter( - "distributed_pdlp_partitioner", DistributedPdlpPartitioner.KaMinPar - ) + settings.set_parameter("distributed_pdlp_partitioner", 1) # KaMinPar -Server Thin client users should use the :class:`cuopt_sh_client.DistributedPdlpPartitioner` for this parameter. +Server Thin client users can set this parameter directly (see the note at the top of this page). Infeasibility Detection diff --git a/docs/cuopt/source/cuopt-server/client-api/sh-cli-api.rst b/docs/cuopt/source/cuopt-server/client-api/sh-cli-api.rst index 29204c1ea3..a681fe180b 100644 --- a/docs/cuopt/source/cuopt-server/client-api/sh-cli-api.rst +++ b/docs/cuopt/source/cuopt-server/client-api/sh-cli-api.rst @@ -25,11 +25,6 @@ LP Supporting Classes :undoc-members: :no-inherited-members: -.. autoclass:: cuopt_sh_client.DistributedPdlpPartitioner - :members: - :undoc-members: - :no-inherited-members: - .. autoclass:: cuopt.linear_programming.data_model.DataModel :members: :undoc-members: diff --git a/python/cuopt/cuopt/linear_programming/__init__.py b/python/cuopt/cuopt/linear_programming/__init__.py index 4ac795b67c..835d09d76a 100644 --- a/python/cuopt/cuopt/linear_programming/__init__.py +++ b/python/cuopt/cuopt/linear_programming/__init__.py @@ -8,7 +8,6 @@ from cuopt.linear_programming.solution import Solution from cuopt.linear_programming.solver import BatchSolve, Solve from cuopt.linear_programming.solver_settings import ( - DistributedPdlpPartitioner, PDLPSolverMode, SolverMethod, SolverSettings, diff --git a/python/cuopt/cuopt/linear_programming/solver_settings/__init__.py b/python/cuopt/cuopt/linear_programming/solver_settings/__init__.py index 84f505eb46..7d984489f2 100644 --- a/python/cuopt/cuopt/linear_programming/solver_settings/__init__.py +++ b/python/cuopt/cuopt/linear_programming/solver_settings/__init__.py @@ -8,7 +8,6 @@ """ from .solver_settings import ( - DistributedPdlpPartitioner, PDLPSolverMode, SolverMethod, SolverSettings, @@ -20,7 +19,6 @@ solver_params = tuple(_solver_params_list) __all__ = [ - "DistributedPdlpPartitioner", "PDLPSolverMode", "SolverMethod", "SolverSettings", diff --git a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx index b74e794492..bdd9741a09 100644 --- a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx +++ b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx @@ -111,45 +111,6 @@ class PDLPSolverMode(IntEnum): return "%d" % self.value -class DistributedPdlpPartitioner(IntEnum): - """ - Enum representing the graph partitioning strategy used to split a - problem across GPUs when distributed (multi-GPU) PDLP is used, i.e. - when ``method`` is ``SolverMethod.PDLP`` and ``num_gpus`` is ``-1`` - or greater than ``1``. - - Attributes - ---------- - Auto - Automatically pick a partitioner: ``RoundRobin`` on a single GPU, - ``KaMinPar`` otherwise. - KaMinPar - Multi-threaded KaMinPar graph partitioner. Generally produces - better balanced shards at the cost of extra partitioning time. - RoundRobin - Round-robin assignment of rows/columns across GPUs, without - building a partitioning graph. - - Notes - ----- - Default value is Auto. - """ - - Auto = 0 - KaMinPar = auto() - RoundRobin = auto() - - def __str__(self): - """Convert the partitioner to a string. - - Returns - ------- - str - The string representation of the partitioner. - """ - return "%d" % self.value - - cdef class SolverSettings: def __init__(self): self.c_solver_settings.reset(new solver_settings_t[int, double]()) diff --git a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py index b891005861..e0d8d421d2 100644 --- a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py +++ b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py @@ -42,7 +42,6 @@ LPTerminationStatus, ) from cuopt.linear_programming.solver_settings import ( - DistributedPdlpPartitioner, PDLPSolverMode, SolverMethod, SolverSettings, @@ -381,23 +380,12 @@ def test_solver_settings_basic(): # Distributed (multi-GPU) PDLP settings settings.set_parameter(CUOPT_NUM_GPUS, -1) settings.set_parameter(CUOPT_USE_DISTRIBUTED_PDLP, True) - settings.set_parameter( - CUOPT_DISTRIBUTED_PDLP_PARTITIONER, - DistributedPdlpPartitioner.RoundRobin, - ) + # 0=Auto, 1=KaMinPar, 2=RoundRobin + settings.set_parameter(CUOPT_DISTRIBUTED_PDLP_PARTITIONER, 2) assert settings.get_parameter(CUOPT_NUM_GPUS) == -1 assert settings.get_parameter(CUOPT_USE_DISTRIBUTED_PDLP) is True - assert settings.get_parameter(CUOPT_DISTRIBUTED_PDLP_PARTITIONER) == int( - DistributedPdlpPartitioner.RoundRobin - ) - - -def test_distributed_pdlp_partitioner_enum(): - assert int(DistributedPdlpPartitioner.Auto) == 0 - assert int(DistributedPdlpPartitioner.KaMinPar) == 1 - assert int(DistributedPdlpPartitioner.RoundRobin) == 2 - assert str(DistributedPdlpPartitioner.KaMinPar) == "1" + assert settings.get_parameter(CUOPT_DISTRIBUTED_PDLP_PARTITIONER) == 2 def test_solver_settings(tmp_path): diff --git a/python/cuopt_self_hosted/cuopt_sh_client/__init__.py b/python/cuopt_self_hosted/cuopt_sh_client/__init__.py index 1cab2f7a6b..d6d3b4e0d0 100644 --- a/python/cuopt_self_hosted/cuopt_sh_client/__init__.py +++ b/python/cuopt_self_hosted/cuopt_sh_client/__init__.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 from cuopt_sh_client._version import __git_commit__, __version__ @@ -12,7 +12,6 @@ ) from .thin_client_solution import ThinClientSolution from .thin_client_solver_settings import ( - DistributedPdlpPartitioner, PDLPSolverMode, SolverMethod, ThinClientSolverSettings, diff --git a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py index 2ef9b4dba9..fca85b33c3 100644 --- a/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py +++ b/python/cuopt_self_hosted/cuopt_sh_client/thin_client_solver_settings.py @@ -67,48 +67,6 @@ def __str__(self): return "%d" % self.value -# Note these classes are only used on the thin client side. -# They are duplicates of the classes in -# cuopt.linear_programming.solver_settings.solver_settings -class DistributedPdlpPartitioner(IntEnum): - """ - Enum representing the graph partitioning strategy used to split a - problem across GPUs when distributed (multi-GPU) PDLP is used, i.e. - when ``method`` is ``SolverMethod.PDLP`` and ``num_gpus`` is ``-1`` - or greater than ``1``. - - Attributes - ---------- - Auto - Automatically pick a partitioner: ``RoundRobin`` on a single GPU, - ``KaMinPar`` otherwise. - KaMinPar - Multi-threaded KaMinPar graph partitioner. Generally produces - better balanced shards at the cost of extra partitioning time. - RoundRobin - Round-robin assignment of rows/columns across GPUs, without - building a partitioning graph. - - Notes - ----- - Default value is Auto. - """ - - Auto = 0 - KaMinPar = auto() - RoundRobin = auto() - - def __str__(self): - """Convert the partitioner to a string. - - Returns - ------- - str - The string representation of the partitioner. - """ - return "%d" % self.value - - class ThinClientSolverSettings: def __init__(self): self.parameter_dict = {} From 0890eca5ed99c4b8b9dd03236f3f417b06cbb1cb Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Tue, 22 Sep 2026 07:59:43 -0500 Subject: [PATCH 06/10] Fix import order and trim docs to match plain-int settings convention CUOPT_USE_DISTRIBUTED_PDLP was out of alphabetical order in the test import block. Also trimmed the Distributed PDLP doc section to match how other plain-int settings (augmented, pdlp_precision) are documented elsewhere on this page: a value list and a default note, no per-interface code examples. Co-Authored-By: Claude Sonnet 5 --- docs/cuopt/source/convex-settings.rst | 18 +++--------------- .../tests/linear_programming/test_lp_solver.py | 2 +- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index 3f09219d08..bfc37718a2 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -154,21 +154,9 @@ PDLP: extra partitioning time * ``2``: RoundRobin - assigns rows/columns across GPUs in round-robin fashion, without building a partitioning graph -C API users should use the constants defined in :ref:`distributed-pdlp-partitioner-constants` for this parameter. - -Python API users can set this parameter directly: - -.. code-block:: python - - from cuopt.linear_programming import SolverMethod, SolverSettings - - settings = SolverSettings() - settings.set_parameter("method", SolverMethod.PDLP) - settings.set_parameter("num_gpus", -1) - settings.set_parameter("use_distributed_pdlp", True) - settings.set_parameter("distributed_pdlp_partitioner", 1) # KaMinPar - -Server Thin client users can set this parameter directly (see the note at the top of this page). +.. note:: The default value is ``false`` for ``CUOPT_USE_DISTRIBUTED_PDLP`` and ``0`` (Auto) for + ``CUOPT_DISTRIBUTED_PDLP_PARTITIONER``. C API users should use the constants defined in + :ref:`distributed-pdlp-partitioner-constants`. Infeasibility Detection diff --git a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py index e0d8d421d2..56a02c76eb 100644 --- a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py +++ b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py @@ -27,13 +27,13 @@ CUOPT_MIP_HEURISTICS_ONLY, CUOPT_NUM_GPUS, CUOPT_PDLP_SOLVER_MODE, - CUOPT_USE_DISTRIBUTED_PDLP, CUOPT_PRIMAL_INFEASIBLE_TOLERANCE, CUOPT_RELATIVE_DUAL_TOLERANCE, CUOPT_RELATIVE_GAP_TOLERANCE, CUOPT_RELATIVE_PRIMAL_TOLERANCE, CUOPT_SOLUTION_FILE, CUOPT_TIME_LIMIT, + CUOPT_USE_DISTRIBUTED_PDLP, CUOPT_USER_PROBLEM_FILE, CUOPT_PRESOLVE, ) From b6688830c53a90151839e2ab72d9f956b675bdc6 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Tue, 22 Sep 2026 08:16:40 -0500 Subject: [PATCH 07/10] Add server-side test for distributed PDLP solver_config fields conversion.create_solver had no coverage for num_gpus, use_distributed_pdlp, or distributed_pdlp_partitioner, unlike the existing test_create_solver_limits pattern for time_limit/ iteration_limit. Co-Authored-By: Claude Sonnet 5 --- .../cuopt_server/tests/test_lp_conversion.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py b/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py index 667c16672c..4d4ca8651a 100644 --- a/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py +++ b/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py @@ -58,6 +58,25 @@ def test_create_solver_limits(): assert int(solver_settings.get_parameter("iteration_limit")) == 100 +def test_create_solver_distributed_pdlp(): + data = get_lp_json() + data["solver_config"]["method"] = 1 # PDLP + data["solver_config"]["num_gpus"] = -1 + data["solver_config"]["use_distributed_pdlp"] = True + data["solver_config"]["distributed_pdlp_partitioner"] = 2 # RoundRobin + + warnings, solver_settings = conversion.create_solver( + LPData.parse_obj(data), None + ) + + assert warnings == [] + assert int(solver_settings.get_parameter("num_gpus")) == -1 + assert bool(solver_settings.get_parameter("use_distributed_pdlp")) is True + assert ( + int(solver_settings.get_parameter("distributed_pdlp_partitioner")) == 2 + ) + + def test_create_solver_limits_clamped_by_environment(monkeypatch): monkeypatch.setenv("CUOPT_LP_TIME_LIMIT_SEC", "2") monkeypatch.setenv("CUOPT_LP_ITERATION_LIMIT", "10") From 4db80a597664f1ad6f37ff66df7cf25a28e4a748 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Wed, 23 Sep 2026 09:43:57 -0500 Subject: [PATCH 08/10] Rename to multi-GPU PDLP (mPDLP) terminology in Python and docs Per team naming discussion: "distributed PDLP" collides with the existing D-PDLP solver name. Adds use_multi_gpu_pdlp / multi_gpu_pdlp_partitioner as the public Python parameter names (core SolverSettings.set_parameter/get_parameter and the REST server's SolverConfig), translating to the existing C++ parameter names (use_distributed_pdlp / distributed_pdlp_partitioner), which stay unchanged since they're already part of the shipped C API. Docs updated to "Multi-GPU PDLP (mPDLP)" throughout, with a note on the C++/C API's underlying names. Also clarifies what "RoundRobin on 1 GPU" means (nothing to partition, so it's a no-op). Co-Authored-By: Claude Sonnet 5 --- ci/vale/styles/cuOpt/Headings.yml | 1 + docs/cuopt/source/convex-features.rst | 2 +- docs/cuopt/source/convex-settings.rst | 20 +++++++++++-------- .../solver_settings/solver_settings.pyx | 12 +++++++++++ .../linear_programming/test_lp_solver.py | 11 +++++++++- .../cuopt_server/tests/test_lp_conversion.py | 6 +++--- .../utils/linear_programming/conversion.py | 10 +++++++++- .../linear_programming/data_definition.py | 17 ++++++++++------ 8 files changed, 59 insertions(+), 20 deletions(-) diff --git a/ci/vale/styles/cuOpt/Headings.yml b/ci/vale/styles/cuOpt/Headings.yml index 9d80fcdbe8..6e91e1404d 100644 --- a/ci/vale/styles/cuOpt/Headings.yml +++ b/ci/vale/styles/cuOpt/Headings.yml @@ -23,6 +23,7 @@ exceptions: - cuDSS - gRPC - mTLS + - mPDLP - (cuopt) - cuopt-server - solver_configs diff --git a/docs/cuopt/source/convex-features.rst b/docs/cuopt/source/convex-features.rst index 7a25d042dd..8bc2364020 100644 --- a/docs/cuopt/source/convex-features.rst +++ b/docs/cuopt/source/convex-features.rst @@ -328,4 +328,4 @@ Multi-GPU Mode Users can use multiple GPUs to solve a problem by specifying the ``num_gpus`` parameter, in one of two ways: - **Concurrent mode**: restricted to LP problems that use concurrent mode and supports up to 2 GPUs. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. -- **Distributed PDLP**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` for the available strategies. +- **Multi-GPU PDLP (mPDLP)**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` (Python: ``use_multi_gpu_pdlp``) set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` (Python: ``multi_gpu_pdlp_partitioner``) to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` for the available strategies. diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index bfc37718a2..26715cb24c 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -135,28 +135,32 @@ For LP problems solved with ``Concurrent`` method, this setting supports up to 2 PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. For LP problems solved with ``PDLP`` method, setting ``CUOPT_NUM_GPUS`` to ``-1`` or to a value greater than 1, -together with ``CUOPT_USE_DISTRIBUTED_PDLP`` set to true, distributes the PDLP solve across multiple GPUs. A -value of ``-1`` uses all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; -multi-GPU sharding only happens when more than one GPU is actually selected. +together with ``CUOPT_USE_DISTRIBUTED_PDLP`` set to true, distributes the PDLP solve across multiple GPUs (this +is cuOpt's multi-GPU PDLP, or mPDLP). A value of ``-1`` uses all GPUs visible to the process, which may resolve +to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually +selected. -Distributed PDLP -^^^^^^^^^^^^^^^^ +Multi-GPU PDLP (mPDLP) +^^^^^^^^^^^^^^^^^^^^^^ ``CUOPT_USE_DISTRIBUTED_PDLP`` controls whether PDLP should be distributed across multiple GPUs. It requires ``CUOPT_METHOD`` to be ``PDLP`` and ``CUOPT_NUM_GPUS`` to be ``-1`` or greater than 1 (as above, ``-1`` may resolve to a single visible GPU, in which case the solve still runs but is not actually sharded). -``CUOPT_DISTRIBUTED_PDLP_PARTITIONER`` controls how the problem is partitioned across the GPUs used by distributed -PDLP: +``CUOPT_DISTRIBUTED_PDLP_PARTITIONER`` controls how the problem is partitioned across the GPUs used by mPDLP: * ``0``: Auto (default) - picks ``RoundRobin`` on a single GPU and ``KaMinPar`` otherwise * ``1``: KaMinPar - a multi-threaded graph partitioner that generally produces better balanced shards at the cost of extra partitioning time * ``2``: RoundRobin - assigns rows/columns across GPUs in round-robin fashion, without building a partitioning graph +With a single GPU there is nothing to partition, so both strategies are equivalent no-ops; Auto picks +RoundRobin there because it skips KaMinPar's graph-partitioning work for no benefit. + .. note:: The default value is ``false`` for ``CUOPT_USE_DISTRIBUTED_PDLP`` and ``0`` (Auto) for ``CUOPT_DISTRIBUTED_PDLP_PARTITIONER``. C API users should use the constants defined in - :ref:`distributed-pdlp-partitioner-constants`. + :ref:`distributed-pdlp-partitioner-constants`. Python API users can also use the ``use_multi_gpu_pdlp`` and + ``multi_gpu_pdlp_partitioner`` parameter aliases. Infeasibility Detection diff --git a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx index bdd9741a09..5fe209c1ec 100644 --- a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx +++ b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx @@ -52,6 +52,16 @@ cpdef get_solver_parameter_names(): solver_params = get_solver_parameter_names() for param in solver_params: globals()["CUOPT_"+param.upper()] = param +# Public spelling for the two distributed-PDLP parameters, mapped to the +# underlying C++ parameter names. Accepted as aliases by get_parameter and +# set_parameter; the CUOPT_* constants below mirror the auto-generated ones. +PARAMETER_ALIASES = { + "use_multi_gpu_pdlp": "use_distributed_pdlp", + "multi_gpu_pdlp_partitioner": "distributed_pdlp_partitioner", +} +for alias, canonical in PARAMETER_ALIASES.items(): + globals()["CUOPT_" + alias.upper()] = globals()["CUOPT_" + canonical.upper()] + class SolverMethod(IntEnum): """ @@ -163,6 +173,7 @@ cdef class SolverSettings: For a list of availabe parameters, their descriptions, default values, and acceptable ranges, see the cuOpt documentation `parameter.rst`. """ + name = PARAMETER_ALIASES.get(name, name) if name not in solver_params: raise ValueError("Invalid parameter. Please check documentation") if name in self.settings_dict: @@ -188,6 +199,7 @@ cdef class SolverSettings: For a list of availabe parameters, their descriptions, default values, and acceptable ranges, see the cuOpt documentation `parameter.rst`. """ + name = PARAMETER_ALIASES.get(name, name) if name not in solver_params: raise ValueError("Invalid parameter. Please check documentation") self.settings_dict[name] = value diff --git a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py index 56a02c76eb..640f3f49a6 100644 --- a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py +++ b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py @@ -377,7 +377,7 @@ def test_solver_settings_basic(): PDLPSolverMode.Methodical1 ) - # Distributed (multi-GPU) PDLP settings + # Multi-GPU PDLP settings, via the canonical (C++) parameter names settings.set_parameter(CUOPT_NUM_GPUS, -1) settings.set_parameter(CUOPT_USE_DISTRIBUTED_PDLP, True) # 0=Auto, 1=KaMinPar, 2=RoundRobin @@ -387,6 +387,15 @@ def test_solver_settings_basic(): assert settings.get_parameter(CUOPT_USE_DISTRIBUTED_PDLP) is True assert settings.get_parameter(CUOPT_DISTRIBUTED_PDLP_PARTITIONER) == 2 + # Same settings, via the public multi_gpu_pdlp aliases + settings.set_parameter("use_multi_gpu_pdlp", True) + settings.set_parameter("multi_gpu_pdlp_partitioner", 1) + + assert settings.get_parameter("use_multi_gpu_pdlp") is True + assert settings.get_parameter("multi_gpu_pdlp_partitioner") == 1 + # Aliases resolve to the same underlying parameter as the canonical name + assert settings.get_parameter(CUOPT_DISTRIBUTED_PDLP_PARTITIONER) == 1 + def test_solver_settings(tmp_path): """Push every registered parameter to the C++ layer via set_c_solver_settings.""" diff --git a/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py b/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py index 4d4ca8651a..99c2600a03 100644 --- a/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py +++ b/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py @@ -58,12 +58,12 @@ def test_create_solver_limits(): assert int(solver_settings.get_parameter("iteration_limit")) == 100 -def test_create_solver_distributed_pdlp(): +def test_create_solver_multi_gpu_pdlp(): data = get_lp_json() data["solver_config"]["method"] = 1 # PDLP data["solver_config"]["num_gpus"] = -1 - data["solver_config"]["use_distributed_pdlp"] = True - data["solver_config"]["distributed_pdlp_partitioner"] = 2 # RoundRobin + data["solver_config"]["use_multi_gpu_pdlp"] = True + data["solver_config"]["multi_gpu_pdlp_partitioner"] = 2 # RoundRobin warnings, solver_settings = conversion.create_solver( LPData.parse_obj(data), None diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/conversion.py b/python/cuopt_server/cuopt_server/utils/linear_programming/conversion.py index fb130f1579..d72e96bc00 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/conversion.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/conversion.py @@ -17,6 +17,13 @@ from cuopt_server.utils.linear_programming.data_definition import WarmStartData +# solver_params entries whose SolverConfig attribute uses a different +# (public-facing) name than the underlying C++ parameter. +SOLVER_CONFIG_FIELD_ALIASES = { + "use_distributed_pdlp": "use_multi_gpu_pdlp", + "distributed_pdlp_partitioner": "multi_gpu_pdlp_partitioner", +} + def ignored_warning(field): return f"solver config {field} ignored in the cuopt service" @@ -98,7 +105,8 @@ def create_solver(LP_data, warmstart_data): if param.endswith("tolerance"): param_value = getattr(solver_config.tolerances, param, None) else: - param_value = getattr(solver_config, param, None) + attr_name = SOLVER_CONFIG_FIELD_ALIASES.get(param, param) + param_value = getattr(solver_config, attr_name, None) if param_value is not None and param_value != "": solver_settings.set_parameter(param, param_value) diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py index 8d804df49e..1afde179e0 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py @@ -475,26 +475,31 @@ class SolverConfig(BaseModel): num_gpus: Optional[int] = Field( default=None, description="Set the number of GPUs to use for LP solve. For " - "distributed (multi-GPU) PDLP, use -1 to use all visible GPUs, " - "or a value greater than 1 to use that many GPUs.", + "multi-GPU PDLP, use -1 to use all visible GPUs, or a value " + "greater than 1 to use that many GPUs; multi-GPU sharding only " + "happens when more than one GPU is actually selected.", ) - use_distributed_pdlp: Optional[bool] = Field( + use_multi_gpu_pdlp: Optional[bool] = Field( default=None, description="Set True to distribute the PDLP solve of an LP " "problem across multiple GPUs. Requires method to be PDLP and " "num_gpus to be -1 or greater than 1.", ) - distributed_pdlp_partitioner: Optional[int] = Field( + multi_gpu_pdlp_partitioner: Optional[int] = Field( default=None, description="Partitioner used to split the problem across GPUs " - "when use_distributed_pdlp is set:" + "when use_multi_gpu_pdlp is set:" "
" "- Auto: 0, pick automatically (RoundRobin on 1 GPU, " "KaMinPar otherwise)" "
" "- KaMinPar: 1, multi-threaded KaMinPar graph partitioner" "
" - "- RoundRobin: 2, round-robin assignment, no graph", + "- RoundRobin: 2, round-robin assignment, no graph" + "
" + "With 1 GPU there is nothing to partition, so both strategies " + "are equivalent no-ops; Auto picks RoundRobin there because it " + "skips KaMinPar's graph-partitioning work for no benefit.", ) augmented: Optional[int] = Field( default=-1, From 5b14ea820953f9dd334fe79716e1a19cd32a92a2 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Wed, 23 Sep 2026 10:07:43 -0500 Subject: [PATCH 09/10] Rename Python multi_gpu_pdlp aliases to mpdlp Per naming discussion: use the mPDLP short form (matching Bulle's naming) rather than the fully spelled-out multi_gpu_pdlp. Renames use_multi_gpu_pdlp -> use_mpdlp and multi_gpu_pdlp_partitioner -> mpdlp_partitioner throughout (core SolverSettings aliases, REST SolverConfig fields, docs, tests). Still translates internally to the unchanged, already-shipped use_distributed_pdlp / distributed_pdlp_partitioner C++ parameter names. Co-Authored-By: Claude Sonnet 5 --- docs/cuopt/source/convex-features.rst | 2 +- docs/cuopt/source/convex-settings.rst | 4 ++-- .../solver_settings/solver_settings.pyx | 4 ++-- .../cuopt/tests/linear_programming/test_lp_solver.py | 10 +++++----- .../cuopt_server/tests/test_lp_conversion.py | 6 +++--- .../utils/linear_programming/conversion.py | 4 ++-- .../utils/linear_programming/data_definition.py | 6 +++--- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/cuopt/source/convex-features.rst b/docs/cuopt/source/convex-features.rst index 8bc2364020..62fffd99ca 100644 --- a/docs/cuopt/source/convex-features.rst +++ b/docs/cuopt/source/convex-features.rst @@ -328,4 +328,4 @@ Multi-GPU Mode Users can use multiple GPUs to solve a problem by specifying the ``num_gpus`` parameter, in one of two ways: - **Concurrent mode**: restricted to LP problems that use concurrent mode and supports up to 2 GPUs. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. -- **Multi-GPU PDLP (mPDLP)**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` (Python: ``use_multi_gpu_pdlp``) set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` (Python: ``multi_gpu_pdlp_partitioner``) to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` for the available strategies. +- **Multi-GPU PDLP (mPDLP)**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` (Python: ``use_mpdlp``) set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` (Python: ``mpdlp_partitioner``) to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` for the available strategies. diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index 26715cb24c..76821d6423 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -159,8 +159,8 @@ RoundRobin there because it skips KaMinPar's graph-partitioning work for no bene .. note:: The default value is ``false`` for ``CUOPT_USE_DISTRIBUTED_PDLP`` and ``0`` (Auto) for ``CUOPT_DISTRIBUTED_PDLP_PARTITIONER``. C API users should use the constants defined in - :ref:`distributed-pdlp-partitioner-constants`. Python API users can also use the ``use_multi_gpu_pdlp`` and - ``multi_gpu_pdlp_partitioner`` parameter aliases. + :ref:`distributed-pdlp-partitioner-constants`. Python API users can also use the ``use_mpdlp`` and + ``mpdlp_partitioner`` parameter aliases. Infeasibility Detection diff --git a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx index 5fe209c1ec..154d18ef5d 100644 --- a/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx +++ b/python/cuopt/cuopt/linear_programming/solver_settings/solver_settings.pyx @@ -56,8 +56,8 @@ for param in solver_params: globals()["CUOPT_"+param.upper()] = param # underlying C++ parameter names. Accepted as aliases by get_parameter and # set_parameter; the CUOPT_* constants below mirror the auto-generated ones. PARAMETER_ALIASES = { - "use_multi_gpu_pdlp": "use_distributed_pdlp", - "multi_gpu_pdlp_partitioner": "distributed_pdlp_partitioner", + "use_mpdlp": "use_distributed_pdlp", + "mpdlp_partitioner": "distributed_pdlp_partitioner", } for alias, canonical in PARAMETER_ALIASES.items(): globals()["CUOPT_" + alias.upper()] = globals()["CUOPT_" + canonical.upper()] diff --git a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py index 640f3f49a6..c558120a25 100644 --- a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py +++ b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py @@ -387,12 +387,12 @@ def test_solver_settings_basic(): assert settings.get_parameter(CUOPT_USE_DISTRIBUTED_PDLP) is True assert settings.get_parameter(CUOPT_DISTRIBUTED_PDLP_PARTITIONER) == 2 - # Same settings, via the public multi_gpu_pdlp aliases - settings.set_parameter("use_multi_gpu_pdlp", True) - settings.set_parameter("multi_gpu_pdlp_partitioner", 1) + # Same settings, via the public mpdlp aliases + settings.set_parameter("use_mpdlp", True) + settings.set_parameter("mpdlp_partitioner", 1) - assert settings.get_parameter("use_multi_gpu_pdlp") is True - assert settings.get_parameter("multi_gpu_pdlp_partitioner") == 1 + assert settings.get_parameter("use_mpdlp") is True + assert settings.get_parameter("mpdlp_partitioner") == 1 # Aliases resolve to the same underlying parameter as the canonical name assert settings.get_parameter(CUOPT_DISTRIBUTED_PDLP_PARTITIONER) == 1 diff --git a/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py b/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py index 99c2600a03..bb6ab3c8e9 100644 --- a/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py +++ b/python/cuopt_server/cuopt_server/tests/test_lp_conversion.py @@ -58,12 +58,12 @@ def test_create_solver_limits(): assert int(solver_settings.get_parameter("iteration_limit")) == 100 -def test_create_solver_multi_gpu_pdlp(): +def test_create_solver_mpdlp(): data = get_lp_json() data["solver_config"]["method"] = 1 # PDLP data["solver_config"]["num_gpus"] = -1 - data["solver_config"]["use_multi_gpu_pdlp"] = True - data["solver_config"]["multi_gpu_pdlp_partitioner"] = 2 # RoundRobin + data["solver_config"]["use_mpdlp"] = True + data["solver_config"]["mpdlp_partitioner"] = 2 # RoundRobin warnings, solver_settings = conversion.create_solver( LPData.parse_obj(data), None diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/conversion.py b/python/cuopt_server/cuopt_server/utils/linear_programming/conversion.py index d72e96bc00..f4bcca148b 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/conversion.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/conversion.py @@ -20,8 +20,8 @@ # solver_params entries whose SolverConfig attribute uses a different # (public-facing) name than the underlying C++ parameter. SOLVER_CONFIG_FIELD_ALIASES = { - "use_distributed_pdlp": "use_multi_gpu_pdlp", - "distributed_pdlp_partitioner": "multi_gpu_pdlp_partitioner", + "use_distributed_pdlp": "use_mpdlp", + "distributed_pdlp_partitioner": "mpdlp_partitioner", } diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py index 1afde179e0..b4ae9b66c4 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/data_definition.py @@ -479,16 +479,16 @@ class SolverConfig(BaseModel): "greater than 1 to use that many GPUs; multi-GPU sharding only " "happens when more than one GPU is actually selected.", ) - use_multi_gpu_pdlp: Optional[bool] = Field( + use_mpdlp: Optional[bool] = Field( default=None, description="Set True to distribute the PDLP solve of an LP " "problem across multiple GPUs. Requires method to be PDLP and " "num_gpus to be -1 or greater than 1.", ) - multi_gpu_pdlp_partitioner: Optional[int] = Field( + mpdlp_partitioner: Optional[int] = Field( default=None, description="Partitioner used to split the problem across GPUs " - "when use_multi_gpu_pdlp is set:" + "when use_mpdlp is set:" "
" "- Auto: 0, pick automatically (RoundRobin on 1 GPU, " "KaMinPar otherwise)" From aef5894f0cfe526444a42c00e63dc58dfc269233 Mon Sep 17 00:00:00 2001 From: Ramakrishna Prabhu Date: Wed, 23 Sep 2026 10:28:43 -0500 Subject: [PATCH 10/10] Drop mPDLP abbreviation from documentation prose Per team decision: documentation spells out "multi-GPU PDLP" in full (no abbreviations); "mpdlp" stays as the short form used in code identifiers only. Removes the now-unused Vale heading exception. Co-Authored-By: Claude Sonnet 5 --- ci/vale/styles/cuOpt/Headings.yml | 1 - docs/cuopt/source/convex-features.rst | 2 +- docs/cuopt/source/convex-settings.rst | 8 ++++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ci/vale/styles/cuOpt/Headings.yml b/ci/vale/styles/cuOpt/Headings.yml index 6e91e1404d..9d80fcdbe8 100644 --- a/ci/vale/styles/cuOpt/Headings.yml +++ b/ci/vale/styles/cuOpt/Headings.yml @@ -23,7 +23,6 @@ exceptions: - cuDSS - gRPC - mTLS - - mPDLP - (cuopt) - cuopt-server - solver_configs diff --git a/docs/cuopt/source/convex-features.rst b/docs/cuopt/source/convex-features.rst index 62fffd99ca..d1239d6345 100644 --- a/docs/cuopt/source/convex-features.rst +++ b/docs/cuopt/source/convex-features.rst @@ -328,4 +328,4 @@ Multi-GPU Mode Users can use multiple GPUs to solve a problem by specifying the ``num_gpus`` parameter, in one of two ways: - **Concurrent mode**: restricted to LP problems that use concurrent mode and supports up to 2 GPUs. Using this mode will run PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resources. -- **Multi-GPU PDLP (mPDLP)**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` (Python: ``use_mpdlp``) set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` (Python: ``mpdlp_partitioner``) to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` for the available strategies. +- **Multi-GPU PDLP**: restricted to LP problems solved with the ``PDLP`` method. Setting ``num_gpus`` to ``-1`` or to a value greater than 1, together with ``use_distributed_pdlp`` (Python: ``use_mpdlp``) set to true, shards a single PDLP solve across multiple GPUs. ``-1`` selects all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. Use ``distributed_pdlp_partitioner`` (Python: ``mpdlp_partitioner``) to control how the problem is split across GPUs. See :ref:`distributed-pdlp-partitioner-constants` for the available strategies. diff --git a/docs/cuopt/source/convex-settings.rst b/docs/cuopt/source/convex-settings.rst index 76821d6423..66ae2d1c45 100644 --- a/docs/cuopt/source/convex-settings.rst +++ b/docs/cuopt/source/convex-settings.rst @@ -136,18 +136,18 @@ PDLP and barrier in parallel on different GPUs to avoid sharing single GPU resou For LP problems solved with ``PDLP`` method, setting ``CUOPT_NUM_GPUS`` to ``-1`` or to a value greater than 1, together with ``CUOPT_USE_DISTRIBUTED_PDLP`` set to true, distributes the PDLP solve across multiple GPUs (this -is cuOpt's multi-GPU PDLP, or mPDLP). A value of ``-1`` uses all GPUs visible to the process, which may resolve +is cuOpt's multi-GPU PDLP). A value of ``-1`` uses all GPUs visible to the process, which may resolve to a single GPU on a single-GPU host; multi-GPU sharding only happens when more than one GPU is actually selected. -Multi-GPU PDLP (mPDLP) -^^^^^^^^^^^^^^^^^^^^^^ +Multi-GPU PDLP +^^^^^^^^^^^^^^ ``CUOPT_USE_DISTRIBUTED_PDLP`` controls whether PDLP should be distributed across multiple GPUs. It requires ``CUOPT_METHOD`` to be ``PDLP`` and ``CUOPT_NUM_GPUS`` to be ``-1`` or greater than 1 (as above, ``-1`` may resolve to a single visible GPU, in which case the solve still runs but is not actually sharded). -``CUOPT_DISTRIBUTED_PDLP_PARTITIONER`` controls how the problem is partitioned across the GPUs used by mPDLP: +``CUOPT_DISTRIBUTED_PDLP_PARTITIONER`` controls how the problem is partitioned across the GPUs used by multi-GPU PDLP: * ``0``: Auto (default) - picks ``RoundRobin`` on a single GPU and ``KaMinPar`` otherwise * ``1``: KaMinPar - a multi-threaded graph partitioner that generally produces better balanced shards at the cost of