diff --git a/ci/test_self_hosted_service.sh b/ci/test_self_hosted_service.sh index 9469d69bb1..083c2f6a9a 100755 --- a/ci/test_self_hosted_service.sh +++ b/ci/test_self_hosted_service.sh @@ -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 diff --git a/docs/cuopt/source/cuopt-server/examples/lp-examples.rst b/docs/cuopt/source/cuopt-server/examples/lp-examples.rst index 7bba75d046..1f0f0c30eb 100644 --- a/docs/cuopt/source/cuopt-server/examples/lp-examples.rst +++ b/docs/cuopt/source/cuopt-server/examples/lp-examples.rst @@ -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. @@ -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 ` in + :doc:`../../lp-qp-features`. + .. note:: Batch mode is not available for MILP problems. diff --git a/docs/cuopt/source/faq.rst b/docs/cuopt/source/faq.rst index 8061376e25..015a56d4fd 100644 --- a/docs/cuopt/source/faq.rst +++ b/docs/cuopt/source/faq.rst @@ -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 ` 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? @@ -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 `). 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? diff --git a/docs/cuopt/source/lp-qp-features.rst b/docs/cuopt/source/lp-qp-features.rst index e3cbddbb05..bf9ff574c6 100644 --- a/docs/cuopt/source/lp-qp-features.rst +++ b/docs/cuopt/source/lp-qp-features.rst @@ -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 ` 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 -------------------- diff --git a/python/cuopt/cuopt/linear_programming/solver/solver.py b/python/cuopt/cuopt/linear_programming/solver/solver.py index daaf525498..10e29b488e 100644 --- a/python/cuopt/cuopt/linear_programming/solver/solver.py +++ b/python/cuopt/cuopt/linear_programming/solver/solver.py @@ -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 @@ -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) @@ -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() 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 feb5b4ad5e..6857a06d5e 100644 --- a/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py +++ b/python/cuopt/cuopt/tests/linear_programming/test_lp_solver.py @@ -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 + individual_solutions = [] for i in range(nb_solves): individual_solution = solver.Solve( mps_parser.ParseMps(file_path), settings diff --git a/python/cuopt_server/cuopt_server/utils/linear_programming/solver.py b/python/cuopt_server/cuopt_server/utils/linear_programming/solver.py index 0bc05a9b9f..e05e9fed5d 100644 --- a/python/cuopt_server/cuopt_server/utils/linear_programming/solver.py +++ b/python/cuopt_server/cuopt_server/utils/linear_programming/solver.py @@ -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: i_warnings, data_model = create_data_model(i_data) data_model_list.append(data_model)