13
$\begingroup$

The state-of-art solvers like CPLEX or Gurobi and some of the open-source solvers have had the different APIs (like Python, C/C++, Java, etc.) in which users could write their MP model in own favourite programming language.

AFAIK, the core of the many solvers, usually, has been written in C and other APIs are the layer to exchange the required data and results with its core (To compile the input to the core and to invoke the results from that.). Also, through the many APIs that have been developed, Python is more popular between the data analyses. Also, some of its libraries, like NumPy, have methods to deal with the matrix-based operations. (One of the new attempts could be found in Gurobi 9 Python API).

I was wondering if, is there any difference between these APIs specifically in the performance and speed? (E.g. between Python and Java)?

$\endgroup$
11
$\begingroup$

The difference between a C++ and Python API can be massive, but it also depends on the quality of the Python implementation.

A key factor to consider when setting expectations, is the way the API is used to communicate information. There are two main ways to interact with APIs: (i) reading files, and (ii) creating models in the API.

Reading files

For example, our solver's Python API allows people to read a model like so:

import libocteract

m=Model()

m.import_model_file("path/to/my/ampl/gams/pyomo/nl/lp/mps/file")

For open source formats, such as .nl or .mps, this command is a thin wrapper around the C++ library which reads the file directly.

For our AMPL and GAMS interfaces, the Python command is a thin wrapper around their respective C++ APIs.

In both cases, the Python overhead is minimal, because we invoke the C++ libraries directly.

However, many solvers (especially open-source) will first construct the problem in Python, and then copy/pipe that object to the solver, which can be hundreds of times slower.

Building Models

This is trickier. Models are typically in some condensed format (like .nl), or are parsed by a dedicated parser (like AMPL) which transforms them to condensed format, so passing them to a solver quickly is doable.

However, setting up the math through an API can't be as effective, unless a condensed format is used (which takes us back to the "Reading files" case).

Say I want to add a non-linear constraint. In Octeract Engine, the binding in Python is:

m.add_constraint("log(x^2)-1<=0")

Because we have a high performance parser built into the engine, we can parse the string directly, extract the variables automatically, create the computational graph, and a name for the constraint. The only overhead here is copying the string from Python to C++.

In C++ however, we also allow users to create constraints directly from a syntax tree or computational graph, which is much faster.

This is an important point: it's not that we can't expose the graph methods to Python for speed - we could, but forcing a user to build a complex object like that in Python defeats the purpose of using Python in the first place.

The bottomline

As long as the structures we pass to an API are high performance structures, such as a condensed file format, a sparse matrix, or a computational graph, there should be little difference between C++ and Python, as long as the Python implementation is good.

If we are doing incremental changes to the model through the API, or building it piece by piece, the Python API can be considerably slower.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Many thanks for your detailed explanation. I know that, if we have a static model using a framework like AMPL or GAMS can be a good choice. (as you said too). But, for the dynamic models using a low-level API has lots of benefits. Would you please say is there any reason to use Python API if we can use other high-performance APIs like C++ or Java? $\endgroup$ – A.Omidi Feb 8 at 12:11
  • 4
    $\begingroup$ The main advantages are simplicity, rapid prototyping, and how easy it is to then pass information to other Python objects for pre/post processing. The way I would go about these things is to try out Python and only switch to more complicated APIs if I see that it's a bottleneck. If my overall ecosystem is in Python, I would write my own Python thin wrapper around the C++ API to have the best of both worlds. $\endgroup$ – Nikos Kazazakis Feb 8 at 12:27
  • $\begingroup$ Thanks once again. $\endgroup$ – A.Omidi Feb 8 at 12:46
  • $\begingroup$ You are welcome :) $\endgroup$ – Nikos Kazazakis Feb 8 at 13:28
5
$\begingroup$

Python is a "slow" programming language because it is interpreted (at least CPython is), so in OR-Tools, for example, that impacts the model building speed if the model is big enough or your logic involves many loops.

Examples:

Edit: as others have said, this can be avoided if the API implementation is just a wrapper and leaves all the heavy work to a lower level language.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Many thanks for your answer. $\endgroup$ – A.Omidi Feb 8 at 11:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.