Skip to content
2 changes: 1 addition & 1 deletion ci/test_self_hosted_service.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export CUOPT_RESULT_DIR

trap 'rm -rf "$CUOPT_DATA_DIR" "$CUOPT_RESULT_DIR"' EXIT
# cuopt_problem_data and other small problems should be less than 1k
export CUOPT_MAX_RESULT=1
export CUOPT_MAX_RESULT=2
CERT_FOLDER=$(pwd)/python/cuopt_self_hosted/cuopt_sh_client/tests/utils/certs
export CUOPT_SSL_CERTFILE=${CERT_FOLDER}/server.crt
export CUOPT_SSL_KEYFILE=${CERT_FOLDER}/server.key
Expand Down
10 changes: 10 additions & 0 deletions docs/cuopt/source/cuopt-server/examples/lp-examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ LP Python Examples

The following example showcases how to use the ``CuOptServiceSelfHostClient`` to solve a simple LP problem in normal mode and batch mode (where multiple problems are solved at once).

.. note::
LP batch mode is deprecated and will be removed in a future release. Prefer
sequential ``cuopt.linear_programming.Solve`` calls. Server and CLI batch
paths still use batch solve today; check response ``warnings`` or logs for the
deprecation notice.

The OpenAPI specification for the server is available in :doc:`open-api spec <../../open-api>`. The example data is structured as per the OpenAPI specification for the server, please refer :doc:`LPData under "POST /cuopt/request" <../../open-api>` under schema section. LP and MILP share same spec.

If you want to run server locally, please run the following command in a terminal or tmux session so you can test examples in another terminal.
Expand Down Expand Up @@ -404,6 +410,10 @@ In case the user needs to update solver settings through CLI, the option ``-ss``

In the case of batch mode, you can send a bunch of ``mps`` files at once, and acquire results. The batch mode works only for ``mps`` in the case of CLI:

.. note::
LP batch mode is deprecated; see :ref:`Batch Mode <batch-mode>` in
:doc:`../../lp-qp-features`.

.. note::
Batch mode is not available for MILP problems.

Expand Down
5 changes: 4 additions & 1 deletion docs/cuopt/source/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ Linear Programming FAQs

.. dropdown:: How small and how many problems can I give when using the batch mode?

LP batch mode is deprecated; see :ref:`Batch Mode <batch-mode>` in
:doc:`lp-qp-features`.

The batch mode allows solving many LPs in parallel to try to fully utilize the GPU when LP problems are too small. Using H100 SXM, the problem should be of at least 1K elements, and giving more than 100 LPs will usually not increase performance.

.. dropdown:: Can the solver run on dense problems?
Expand All @@ -364,7 +367,7 @@ Linear Programming FAQs
- Hardware: If using self-hosted, you should use a recent server-grade GPU. We recommend H100 SXM (not the PCIE version).
- Tolerance: The set tolerance usually has a massive impact on performance. Try the lowest possible value using ``set_optimality_tolerance`` until you have reached your lowest possible acceptable accuracy.
- PDLP Solver mode: PDLP solver mode will change the way PDLP internally optimizes the problem. The mode choice can drastically impact how fast a specific problem will be solved. You should test the different modes to see which one fits your problem best.
- Batch mode: In case you know upfront that you need to solve multiple LP problems, instead of solving them sequentially, you should use the batch mode which can solve multiple LPs in parallel.
- Batch mode: Deprecated for LP; prefer sequential ``cuopt.linear_programming.Solve`` calls (see :ref:`Batch Mode <batch-mode>`). While available, batch mode can solve multiple LPs in parallel.
- Presolve: Presolve can reduce problem size and improve solve time.

.. dropdown:: What solver mode should I choose?
Expand Down
12 changes: 12 additions & 0 deletions docs/cuopt/source/lp-qp-features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,23 @@ The user may specify a time limit to the solver. By default the solver runs unti
Note that ``time_limit`` applies only to solve time inside the LP solver. This does not include time for network transfer, validation of input, and other operations that occur outside the solver. The overhead associated with these operations are usually small compared to the solve time.


.. _batch-mode:

Batch Mode
----------

Users can submit a set of problems which will be solved in a batch. Problems will be solved at the same time in parallel to fully utilize the GPU. Checkout :ref:`self-hosted client <generic-example-with-normal-and-batch-mode>` example in thin client.

.. warning:: Deprecated

LP batch mode (Python ``cuopt.linear_programming.BatchSolve``, server requests
with a list of LP problems, and multi-file ``cuopt_sh`` LP submissions) is
deprecated and will be removed in a future release. Prefer sequential
``cuopt.linear_programming.Solve`` calls, or implement your own parallelism
(for example with ``concurrent.futures``). Existing batch APIs still run in
parallel today; callers may see a ``DeprecationWarning`` or a deprecation
message in server ``warnings``.

PDLP Precision Modes
--------------------

Expand Down
15 changes: 15 additions & 0 deletions python/cuopt/cuopt/linear_programming/solver/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import os
import time
import warnings

from cuopt.linear_programming.solver import solver_wrapper
from cuopt.linear_programming.solver_settings import SolverSettings
Expand Down Expand Up @@ -114,6 +115,13 @@ def BatchSolve(data_model_list, solver_settings=None):
Solve the list of Linear Programs passed as input and returns the solutions
and total solve time.

.. deprecated::
LP BatchSolve is deprecated and will be removed in a future release.
It runs concurrent LPs in multiple C++ threads, which can be done
independently in user code. Use sequential :func:`Solve` calls instead,
e.g. ``[Solve(dm, solver_settings) for dm in data_model_list]``, or
implement your own parallelism (e.g. ``concurrent.futures``).

Data Model objects can be construed through setters
(see linear_programming.DataModel class) or through a MPS file
(see cuopt.linear_programming.ParseMps function)
Expand Down Expand Up @@ -182,6 +190,13 @@ def BatchSolve(data_model_list, solver_settings=None):
>>> # Print the value of one specific variable
>>> print(solution.get_vars()["var_name"])
"""
warnings.warn(
"LP BatchSolve is deprecated and will be removed in a future release. "
"Use sequential Solve() calls or implement your own parallelism "
"(e.g. concurrent.futures).",
DeprecationWarning,
stacklevel=2,
)
if solver_settings is None:
solver_settings = SolverSettings()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ def test_parser_and_batch_solver():
batch_solution, solve_time = solver.BatchSolve(data_model_list, settings)

# Call Solve on each individual data model object
individual_solutions = [] * nb_solves
Comment thread
Iroy30 marked this conversation as resolved.
individual_solutions = []
for i in range(nb_solves):
individual_solution = solver.Solve(
mps_parser.ParseMps(file_path), settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,10 @@ def create_solution(sol):
if type(LP_data) is list:
is_batch = True
data_model_list = []
warnings = []
warnings = [
"LP batch mode is deprecated and will be removed in a future release. "
"Use sequential Solve() calls or implement your own parallelism."
]
for i_data in LP_data:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are calling batch LP but have changed it to sequential solves under the hood which is misleading

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. So what is your recommendation?

i_warnings, data_model = create_data_model(i_data)
data_model_list.append(data_model)
Expand Down
Loading