Gurobi: Difference between revisions

From Alliance Doc
Jump to navigation Jump to search
No edit summary
(Marked this version for translation)
Line 136: Line 136:
packages like NumPy, Matplotlib, Pandas and others, we need to create a [[Python#Creating_and_using_a_virtual_environment|virtual Python environment]] in which we can install both <code>gurobipy</code> and e.g. <code>pandas</code>. Note that when using Gurobi with Python it is important to minimize the number of times that your Python code will attempt to checkout a license from the single Compute Canada license server for Gurobi, as overloading it will disrupt your own Gurobi jobs as well as those of other users. For this reason, your Python code should do as much work as possible inside a single environment, creating new models within this single existing environment as needed. A new license token is checked out at the creation of a new environment, so it is particularly important not to create a new environment inside of a loop.  
packages like NumPy, Matplotlib, Pandas and others, we need to create a [[Python#Creating_and_using_a_virtual_environment|virtual Python environment]] in which we can install both <code>gurobipy</code> and e.g. <code>pandas</code>. Note that when using Gurobi with Python it is important to minimize the number of times that your Python code will attempt to checkout a license from the single Compute Canada license server for Gurobi, as overloading it will disrupt your own Gurobi jobs as well as those of other users. For this reason, your Python code should do as much work as possible inside a single environment, creating new models within this single existing environment as needed. A new license token is checked out at the creation of a new environment, so it is particularly important not to create a new environment inside of a loop.  


<!--T:214-->
Before we start, we need to decide which combination of versions for Gurobi and Python to use.  For example compare the python versions supported by the gurobi 8.11 and 9.0.1 modules:
Before we start, we need to decide which combination of versions for Gurobi and Python to use.  For example compare the python versions supported by the gurobi 8.11 and 9.0.1 modules:



Revision as of 20:49, 24 January 2022

Other languages:

Gurobi is a commercial software suite for solving complex optimization problems. This page wiki page describes the non-commercial use of Gurobi software on Compute Canada clusters and is currently a work in progress.

License Limitations

Compute Canada supports and provides a free license to use Gurobi on the Graham, Cedar, Béluga and Niagara clusters. The license provides a total number of 4096 simultaneous uses (tokens in use) and permits distributed optimization with up to 100 nodes. A single user can run multiple simultaneous jobs. In order to use Gurobi you must agree to certain conditions. Please contact support and include a copy of the following completed Academic Usage Agreement. You will then be added into the Compute Canada license file as a permitted user within a few days:

Academic Usage Agreement

My Compute Canada username is "_______" and I am a member of the academic institution "_____________________".  This message confirms that I will only use the Compute Canada Gurobi license provided on Compute Canada systems for the purpose of non-commercial research project(s) to be published in publicly available article(s).

Configuring your account

You do NOT need to create a ~/.licenses/gurobi.lic file. The required settings to use the Compute Canada Gurobi license are configured by default when you load a gurobi module on any cluster. To verify your username has been added to the Compute Canada Gurobi license and working properly run the following command:

$ module load gurobi
$ gurobi_cl 1> /dev/null && echo Success || echo Fail

If it returns "Success" then you can being using gurobi immediately. If it returns "Fail" then contact contact support for help.

Interactive Allocations

Gurobi Command-Line Tools

[gra-login2:~] salloc --time=1:00:0 --cpus-per-task=8 --mem=1G --account=def-xyz
[gra800:~] module load gurobi
[gra800:~] gurobi_cl Record=1 Threads=8 Method=2 ResultFile=p0033.sol LogFile=p0033.log $GUROBI_HOME/examples/data/p0033.mps
[gra800:~] gurobi_cl --help

Gurobi Interactive Shell

[gra-login2:~] salloc --time=1:00:0 --cpus-per-task=8 --mem=1G --account=def-xyz
[gra800:~] module load gurobi
[gra800:~] echo "Record 1" > gurobi.env    see *
[gra800:~] gurobi.sh
gurobi> m = read('/cvmfs/restricted.computecanada.ca/easybuild/software/2017/Core/gurobi/8.1.1/examples/data/glass4.mps') 
gurobi> m.Params.Threads = 8               see **
gurobi> m.Params.Method = 2
gurobi> m.Params.ResultFile = "glass4.sol"
gurobi> m.Params.LogFile = "glass4.log"
gurobi> m.optimize()
gurobi> m.write('glass4.lp')
gurobi> m.status                           see ***
gurobi> m.runtime                          see ****
gurobi> help()

where

   * https://www.gurobi.com/documentation/8.1/refman/recording_api_calls.html
  ** https://www.gurobi.com/documentation/8.1/refman/parameter_descriptions.html
 *** https://www.gurobi.com/documentation/8.1/refman/optimization_status_codes.html
**** https://www.gurobi.com/documentation/8.1/refman/attributes.html

Replaying API calls

You can record API calls and repeat them with command

[gra800:~] gurobi_cl recording000.grbr

Reference: https://www.gurobi.com/documentation/8.1/refman/recording_api_calls.html

Cluster Batch Job Submission

Once a slurm script has been prepared for a Gurobi problem it can be submitted to the queue by running the sbatch script-name.sh command. The jobs status in the queue can then be checked by running the sq command. Sample slurm scripts for two such problems provided with each gurobi module version in the examples directory are given here:

Data Example

The following slurm script utilizes the Gurobi command-line interface to solve a simple coin production model written in LP format. The last line demonstrates how parameters can be passed directly to the Gurobi command-line tool gurobi_cl using simple command line arguments. For help selecting which parameters are best used for a particular problem and choosing optimal values refer to both the Performance and Parameters & Algorithms and Search sections found in the Gurobi Knowledge Base as well as the extensive online Gurobi Documentation.

File : script-lp_coins.sh

#!/bin/bash
#SBATCH --account=def-group   # some account
#SBATCH --time=0-00:30        # specify time limit (D-HH:MM)
#SBATCH --cpus-per-task=8     # specify number threads
#SBATCH --mem=4G              # specify total memory
#SBATCH --nodes=1             # do not change

#module load StdEnv/2016      # for versions < 9.0.3 
module load StdEnv/2020       # for versions > 9.0.2

module load gurobi/9.5.0

rm -f coins.sol
gurobi_cl Threads=$SLURM_CPUS_ON_NODE Method=2 ResultFile=coins.sol ${GUROBI_HOME}/examples/data/coins.lp


Python Example

This is an example slurm script for solving a simple facility location model using Gurobi Python. The example shows how-to set the Threads parameter with a dynamically created gurobi.env file when using the Gurobi python interface.

File : script-py_facility.sh

#!/bin/bash
#SBATCH --account=def-group   # some account
#SBATCH --time=0-00:30        # specify time limit (D-HH:MM)
#SBATCH --cpus-per-task=4     # specify number threads
#SBATCH --mem=4G              # specify total memory
#SBATCH --nodes=1             # do not change

#module load StdEnv/2016      # for versions < 9.0.3 
module load StdEnv/2020       # for versions > 9.0.2

module load gurobi/9.5.0

echo "Threads ${SLURM_CPUS_ON_NODE:-1}" > gurobi.env

gurobi.sh ${GUROBI_HOME}/examples/python/facility.py


Using Gurobi in Python virtual environments

Gurobi brings it's own version of Python but that one does not contain any 3rd-party Python packages except Gurobi. In order to use Gurobi together with popular Python packages like NumPy, Matplotlib, Pandas and others, we need to create a virtual Python environment in which we can install both gurobipy and e.g. pandas. Note that when using Gurobi with Python it is important to minimize the number of times that your Python code will attempt to checkout a license from the single Compute Canada license server for Gurobi, as overloading it will disrupt your own Gurobi jobs as well as those of other users. For this reason, your Python code should do as much work as possible inside a single environment, creating new models within this single existing environment as needed. A new license token is checked out at the creation of a new environment, so it is particularly important not to create a new environment inside of a loop.

Before we start, we need to decide which combination of versions for Gurobi and Python to use. For example compare the python versions supported by the gurobi 8.11 and 9.0.1 modules:

[name@server ~] $ module load StdEnv/2016  (not needed for gurobi>9.0.2)
[name@server ~] $ module load gurobi/8.1.1
[name@server ~] $ cd $EBROOTGUROBI/lib
[name@server ~] $ ls -d python*
  python2.7        python2.7_utf32    python2.7_utf16
  python3.5_utf32  python3.6_utf32    python3.7_utf32
[name@server ~] $ module load StdEnv/2016  (not needed for gurobi>9.0.2)
[name@server ~] $ module load gurobi/9.0.1
[name@server ~] $ cd $EBROOTGUROBI/lib
[name@server ~] $ ls -d python*
  python3.7        python2.7_utf16  python2.7_utf32
  python3.5_utf32  python3.8_utf32  python3.6_utf32  python3.7_utf32


We see that gurobi/8.1.1 brings it's own installation of python2.7 and Python packages for Python 2.7, 3.5, 3.6 and 3.7 (pythonX.Y_utf32) while gurobi/9.0.1 by default uses python3.7 and brings Python packages for Python 2.7, 3.5, 3.6, 3.7 and 3.8 (pythonX.Y_utf32).

Creating the virtual environment

In this example we want to create a Python environment based on python/3.7 in which we want to use gurobi/9.0.1 and install the Pandas package. The following steps need to be done only once per system. First load the modules to create the virtual environment and activate it:

[name@server ~] $ module load gurobi/9.0.1 python/3.7
[name@server ~] $ virtualenv --no-download  ~/env_gurobi
  Using base prefix '/cvmfs/soft.computecanada.ca/easybuild/software/2017/Core/python/3.7.4'
  New python executable in /home/name/env_gurobi/bin/python
  Installing setuptools, pip, wheel...
  done.
[name@server ~] $ source ~/env_gurobi/bin/activate

Now that the environment has been activated install the Python packages we want to use, in this case pandas for example:

(env_gurobi) [name@server ~] $ pip install --no-index  pandas
  Ignoring pip: markers 'python_version < "3"' don't match your environment
  Looking in links:
  /cvmfs/soft.computecanada.ca/custom/python/wheelhouse/nix/avx2
  /cvmfs/soft.computecanada.ca/custom/python/wheelhouse/nix/generic
  /cvmfs/soft.computecanada.ca/custom/python/wheelhouse/generic
  Collecting pandas,
  Collecting numpy>1.13.3 (from pandas)
  [...]
  Successfully installed numpy-1.18.4 pandas-1.0.3 python-dateutil-2.8.1 pytz-2020.1 six-1.15.0

The third and final step is to install gurobipy into the environment:

(env_gurobi) [name@server ~] $ cd $EBROOTGUROBI
(env_gurobi) [name@server ~] $ python setup.py build --build-base /tmp/${USER} install
  running build
  running build_py
  creating /tmp/name
  creating /tmp/name/lib
  creating /tmp/name/lib/gurobipy
  copying lib/python3.7_utf32/gurobipy/__init__.py -> /tmp/name/lib/gurobipy
  copying lib/python3.7_utf32/gurobipy/gurobipy.so -> /tmp/name/lib/gurobipy
  running install
  running install_lib
  creating /home/name/env_gurobi/lib/python3.7/site-packages/gurobipy
  copying /tmp/name/lib/gurobipy/gurobipy.so -> /home/name/env_gurobi/lib/python3.7/site-packages/gurobipy
  copying /tmp/name/lib/gurobipy/__init__.py -> /home/name/env_gurobi/lib/python3.7/site-packages/gurobipy
  byte-compiling /home/name/env_gurobi/lib/python3.7/site-packages/gurobipy/__init__.py to __init__.cpython-37.pyc
  running install_egg_info
  Writing /home/name/env_gurobi/lib/python3.7/site-packages/gurobipy-9.0.1-py3.7.egg-info


Using the virtual environment

Python scripts can now import both Pandas and Gurobi:

[name@server ~] $ cat my_gurobi_script.py
  import pandas as pd
  import numpy as np
  import gurobipy as gurobi
  from gurobipy import *
  etc


Once created we can activate our Gurobi environment at any time with:

[name@server ~] $ module load gurobi/9.0.1
  source ~/env_gurobi/bin/activate
  (env_gurobi) python my_gurobi_script.py


Note that we now use python instead of gurobi.sh! This is an example job script that we can use:


File : gurobi-py_example.sh

#!/bin/bash
#SBATCH --time=0-00:30        # time limit (D-HH:MM)
#SBATCH --cpus-per-task=1     # number of CPUs (threads) to use
#SBATCH --mem-per-cpu=1000M   # memory per CPU (in MB)

module load StdEnv/2016.4
module load gurobi/9.0.1

source ~/env_gurobi/bin/activate

# Create environment file in current directory setting the number of threads:
echo "Threads ${SLURM_CPUS_ON_NODE:-1}" > gurobi.env

python  my_gurobi_script.py


Using Gurobi with Java

To use Gurobi with Java, you will also need to load a Java module and add an option to your Java command in order to allow the Java virtual environment to find the Gurobi libraries. A sample job script is below:

File : gurobi-java.sh

#!/bin/bash
#SBATCH --time=0-00:30        # time limit (D-HH:MM)
#SBATCH --cpus-per-task=1     # number of CPUs (threads) to use
#SBATCH --mem=4096M           # memory per CPU (in MB)

module load java/14.0.2
module load gurobi/9.1.2

java -Djava.library.path=$EBROOTGUROBI/lib -Xmx4g -jar my_java_file.jar


Using Gurobi with Jupyter notebooks

Various topics can be found by visiting Resources then clicking Code and Modeling Examples and finally Optimization with Python – Jupyter Notebook Modeling Examples. Alternatively visit support.gurobi.com and search on Jupyter Notebooks. Information specific to using Gurobi with Jupyter notebooks on Compute Canada systems will be added to this wiki section in the future as required.

Cite Gurobi

Please see How do I cite Gurobi software for an academic publication?