Gurobi
Gurobi est une suite logicielle commerciale qui permet de résoudre des problèmes complexes d'optimisation. Nous abordons ici son utilisation sur nos grappes.
Limites de la licence
Nous dispensons le soutien technique pour la licence gratuite disponible sur Nibi, Fir, Rorqual et Trillium. Cette licence permet 4096 utilisations simultanées (avec jetons) et l'optimisation distribuée sur un maximum de 100 nœuds. Plusieurs tâches peuvent être exécutées en simultané. Vous devez cependant accepter certaines conditions. Faites parvenir un courriel au soutien technique avec l'entente (Academic Usage Agreement) dûment complétée; vous pourrez ensuite utiliser les applications après un délai de quelques jours.
Academic Usage Agreement
My Alliance username is "_______" and I am a member of the academic institution "_____________________." This message confirms that I will only use the Gurobi license provided on Digital Research Alliance of Canada systems for the purpose of non-commercial research project(s) to be published in publicly available article(s).
Configurer votre compte
Il n'est pas nécessaire de créer le fichier ~/.licenses/gurobi.lic. Les paramètres pour l'utilisation de notre licence Gurobi sont configurés par défaut quand un module Gurobi est chargé sur une grappe.
Tester votre licence
Pour vous assurer que votre nom d'utilisateur a bien été ajouté à la licence Gurobi, lancez la commande suivante :
$ module load gurobi $ gurobi_cl 1> /dev/null && echo Success || echo Fail
Si vous obtenez Success, vous pouvez utiliser Gurobi immédiatement. Si vous obtenez Fail, vérifiez s'il existe un fichier nommé ~/.license/gurobi; si c'est le cas, supprimez ce fichier, chargez le module Gurobi de nouveau et refaites le test.
Si vous obtenez encore Fail, vérifiez si une variable d'environnement définit GUROBI dans vos fichiers ~/.bashrc ou ~/.bash_profile; si c'est le cas, supprimez la ou les lignes correspondantes ou mettez-les en commentaire, déconnectez-vous et connectez-vous de nouveau, chargez le module Gurobi de nouveau et refaites le test.
Si vous obtenez toujours Fail, contactez le soutien technique pour de l'assistance.
Utiliser un minimum de licences
Veuillez noter que toutes les demandes de licence Gurobi sont gérées par un serveur de licences unique situé en Ontario. Il est donc important de limiter au maximum les tentatives de demande de licence. Plutôt que de demander une licence à chaque invocation de Gurobi dans une tâche (ce qui peut se produire des dizaines, voire des centaines de fois), assurez-vous que votre programme, quel que soit le langage ou l'environnement utilisé, n'effectue qu'une seule demande de licence et réutilise ensuite ce jeton de licence pendant toute la vie de la tâche. Cela améliorera les performances de votre tâche, car contacter un serveur de licence distant est très coûteux en temps. De plus, la réactivité de notre serveur sera également améliorée. Une utilisation incorrecte de Gurobi à cet égard peut entraîner des échecs aléatoires et intermittents. Si cela se produit, nous vous contacterons pour vous inviter à interrompre toutes vos tâches jusqu'à ce que votre programme soit corrigé et testé afin de garantir la résolution du problème. Voyez la documentation pour les programmes en C++. Cette documentation explique comment créer un environnement Gurobi unique utilisable pour tous vos modèles. Pour Python, consultez cette page qui explique comment mettre en œuvre ce même principe d'environnement unique, et donc d'un jeton de licence unique, pour plusieurs modèles. D'autres programmes utilisant Gurobi, comme R, peuvent également facilement déclencher ce problème lors d'une exécution lorsque de nombreuses tâches parallèles sont soumises et/ou exécutées simultanément.
Si vous soumettez de nombreuses tâches Gurobi en boucle à l'ordonnanceur, utilisez l'exemple de script suivant (ou un équivalent) pour assurer un démarrage progressif. Cela permettra de minimiser la fréquence d'utilisation des licences et, par conséquent, la charge sur notre serveur de licences Gurobi. Le script utilise l'option de dépendance after de l'ordonnanceur slurm qui est décrite dans Soumettre une tâche : Fonctions avancées. Nous limitons à 10 000 le nombre d'utilisations de licences Gurobi par grappe, sur une période de 24 heures. Si votre programme Gurobi utilise un algorithme nécessitant l'utilisation de deux licences par tâche, cela correspond à un maximum de 5 000 tâches soumises par jour.
[l2(nibi):~] cat submit.sh
i=1; jobid=$(sbatch --parsable --output=slurm-%j-$i.out script.sh)
for i in {2..1000}; do
jobid=$(sbatch --parsable --dependency=after:$jobid --output=slurm-%j-$i.out script.sh)
[ "$?" -ne 0 ] && exit 1
done
Allocations interactives
Ligne de commande
[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
Interpréteur interactif
[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()
où
* 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
Répéter des appels API
Il est possible d'enregistrer des appels API et de rejouer l'enregistrement avec
[gra800:~] gurobi_cl recording000.grbr
Référence : https://www.gurobi.com/documentation/8.1/refman/recording_api_calls.html
Soumettre une tâche en lots sur une grappe
Une fois que votre script Slurm est prêt, vous pouvez le soumettre à la queue avec la commande sbatch script-name.sh. Vous pouvez vérifier l'état de vos tâches dans la queue avec la commande sq. Les scripts suivants solutionnent deux problèmes qui se trouvent dans le répertoire examples de chaque module Gurobi.
Exemple de données
Le script Slurm suivant utilise l' interface ligne de commande pour résoudre un modèle simple pour produire des pièces de monnaie écrit en format LP. La dernière ligne montre comment des paramètres peuvent être passés directement à l'outil ligne de commande gurobi_cl avec des arguments simples. Pour sélectionner les meilleurs paramètres pour un problème particulier et pour choisir les valeurs optimales, voyez les sections Performance and Parameters et Algorithms and Search dans la page Knowledge Base et dans la documentation Gurobi.
#!/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
Exemple avec Python
Le script Slurm suivant solutionne un modèle simple de l'emplacement de divers sites avec Gurobi Python. L'exemple montre comment paramétrer les fils en nombre égal à celui des cœurs alloués à la tâche en générant un fichier gurobi.env dans le répertoire de travail quand vous utilisez l'interface Gurobi Python. Ceci doit être fait pour chaque tâche soumise, autrement Gurobi lancera par défaut autant de fils d'exécution qu'il y a de cœurs physiques dans le nœud de calcul plutôt que d'utiliser le nombre de cœurs physiques alloués à la tâche par l'ordonnanceur, ce qui risque de ralentir la tâche et nuire aux tâches exécutées sur le même nœud par les autres utilisateurs.
#!/bin/bash
#SBATCH --account=def-group # indiquez le nom du compte
#SBATCH --time=0-00:30 # indiquez la limite de temps (jj-hh:mm)
#SBATCH --cpus-per-task=4 # indiquez le nombre de fils
#SBATCH --mem=4G # demandez toute la mémoire
#SBATCH --nodes=1 # ne pas modifier
#module load StdEnv/2020 # versions < 10.0.3
module load StdEnv/2023 # versions > 10.0.3
module load gurobi/11.0.1
echo "Threads ${SLURM_CPUS_ON_NODE:-1}" > gurobi.env
gurobi.sh ${GUROBI_HOME}/examples/python/facility.py
Environnements virtuels Python
Gurobi a sa propre version de Python qui ne contient aucun autre paquet de tiers autre que Gurobi. Pour utiliser Gurobi avec d'autres paquets Python comme NumPy, Matplotlib, Pandas et autres, il faut créer un environnement virtuel Python dans lequel seront installés gurobipy et par exemple pandas.
Avant de commencer, il faut décider quelle combinaison des versions Gurobi et Python nous voulons utiliser. La liste suivante montre les versions de Python supportées par les versions principales de Gurobi dans les environnements standards (StdEnv).
[name@server ~] module load StdEnv/2016; module load gurobi/8.1.1; cd $EBROOTGUROBI/lib; ls -d python* python2.7 python2.7_utf16 python2.7_utf32 python3.5_utf32 python3.6_utf32 python3.7_utf32 [name@server ~] module load StdEnv/2020; module load gurobi/9.5.2; cd $EBROOTGUROBI/lib; ls -d python* python2.7_utf16 python2.7_utf32 python3.10_utf32 python3.7 python3.7_utf32 python3.8_utf32 python3.9_utf32 [name@server ~] module load StdEnv/2023; module load gurobi/10.0.3; cd $EBROOTGUROBI/lib; ls -d python* python3.10_utf32 python3.11_utf32 python3.7 python3.7_utf32 python3.8_utf32 python3.9_utf32 [name@server ~] module load StdEnv/2023; module load gurobi/11.0.1; cd $EBROOTGUROBI/lib; ls -d python* python3.11
Installer Gurobi pour Python
Tel que mentionné vers la fin de How do I install Gurobi for Python?, la méthode précédemment recommandée pour installer Gurobi pour Python avec setup.py est désormais obsolète et ne peut être utilisée qu'avec les versions Gurobi 10 (et plus anciennes). La section Versions Gurobi 11.0.0 (et plus récentes) montre comment télécharger simultanément une roue binaire compatible à partir de pypi.org et la convertir dans un format utilisable avec la nouvelle commande recommandée.
Versions Gurobi 10.0.3 et moins récentes
Il faut suivre les étapes suivantes une fois sur chaque système avec StdEnv2023 et moins récents. Chargez d'abord les modules pour créer l'environnement virtuel, puis activez cet environnement.
[name@server ~] $ module load gurobi/10.0.3 python
[name@server ~] $ virtualenv --no-download ~/env_gurobi
[name@server ~] $ source ~/env_gurobi/bin/activateInstallez les paquets que vous voulez utiliser, ici pandas. Par exemple
(env_gurobi) [name@server ~] $ pip install --no-index pandasInstallez maintenant gurobipy dans l'environnement. À partir de StdEnv/2023, il n'est plus possible de l'installer dans $EBROOTGUROBI avec la commande python setup.py build --build-base /tmp/${USER} install, ce qui causerait une erreur fatale et le message error: could not create 'gurobipy.egg-info': Read-only file system. Copiez les fichiers ailleurs (par exemple dans /tmp/$USER) où l'installation sera faite, comme ci-dessous :
(env_gurobi) [name@server ~] $ mkdir /tmp/$USER
(env_gurobi) [name@server ~] $ cp -r $EBROOTGUROBI/{lib,setup.py} /tmp/$USER
(env_gurobi) [name@server ~] $ cd /tmp/$USER
(env_gurobi) [name@server ~] $ python setup.py install
(env_gurobi) [roberpj@gra-login1:/tmp/roberpj] python setup.py install
/home/roberpj/env_gurobi/lib/python3.11/site-packages/setuptools/_core_metadata.py:158: SetuptoolsDeprecationWarning: Invalid config.
!!
********************************************************************************
newlines are not allowed in `summary` and will break in the future
********************************************************************************
!!
write_field('Summary', single_line(summary))
removing /tmp/roberpj/build
(env_gurobi) [roberpj@gra-login1:/tmp/roberpj]
(env_gurobi) [name@server ~] $ deactivate
[name@server ~]
Versions Gurobi 11.0.0 (et plus récentes)
Encore une fois, les étapes suivantes doivent être effectuées une fois pour chaque système sous StdEnv/2023 et les versions antérieures. Chargez d'abord les modules dans Créer et utiliser un environnement virtuel, puis activez-le. La version 11.0.0 est ignorée car il a été observé qu'elle produit une erreur de segmentation dans au moins un exemple, comparé à la version 11.0.1 qui fonctionne sans problème.
[name@server ~] $ module load gurobi/11.0.1 python
[name@server ~] $ virtualenv --no-download ~/env_gurobi
[name@server ~] $ source ~/env_gurobi/bin/activateComme précédemment, installez tous les paquets Python nécessaires. Étant donné que l'exemple suivant nécessite numpy, nous installons le paquet Pandas.
(env_gurobi) [name@server ~] $ pip install --no-index pandasInstallez ensuite gurobipy dans l'environnement. Comme mentionné ci-dessus et dans [article], l'utilisation de setup.py pour installer Gurobi pour Python est déconseillée à partir de Gurobi 11. Pip et conda sont tous deux proposés comme alternatives; cependant, comme conda ne doit pas être utilisé sur nos systèmes, l'approche avec pip sera démontrée ici. L'installation de gurobipy est légèrement compliquée car nos systèmes Linux sont configurés avec le préfixe gentoo. En conséquence, ni A) la commande recommandée pour télécharger et installer l'extension gurobipy depuis le serveur public PyPI pip install gurobipy==11.0.1 mentionnée dans l'article B) ni la commande hors ligne pour installer la roue avec python -m pip install --find-links <wheel-dir> --no-index gurobipy ne fonctionneront. Au lieu de cela, nous avons préparé un script pour télécharger et convertir simultanément la roue existante dans un format utilisable avec un nouveau nom. Il y a une mise en garde; pour chaque nouvelle version de Gurobi, vous devez vous rendre sur https://pypi.org/project/gurobipy/11.0.1/#history, cliquer sur la version souhaitée et cliquer sur le bouton Download files situé dans le menu de gauche. Enfin, cliquez pour copier le lien https du fichier wheel (nommé gurobipy-11.0.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl dans le cas de Gurobi 11.0.1) et collez-le comme argument --url comme ci-dessous.
(env_gurobi) [name@server ~] $ wget https://raw.githubusercontent.com/ComputeCanada/wheels_builder/main/unmanylinuxize.sh
(env_gurobi) [name@server ~] $ chmod u+rx unmanylinuxize.sh
(env_gurobi) [name@server ~] $ ./unmanylinuxize.sh --package gurobipy --version 11.0.1 --url
https://files.pythonhosted.org/packages/1c/96/4c800e7cda4a1688d101a279087646912cf432b0f61ff5c816f0bc8503e0/gurobipy-11.0.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
(env_gurobi) [name@server ~] $ ls
gurobipy-11.0.1-cp311-cp311-linux_x86_64.whl unmanylinuxize.sh
(env_gurobi) [name@server ~] $ python -m pip install --find-links $PWD --no-index gurobipy
(env_gurobi) [name@server ~] $ deactivate
[name@server ~]
Travailler dans l'environnement avec Gurobi
Une fois créé, notre environnement Gurobi peut être activé et utilisé à tout moment. Pour démontrer cela, nous chargeons également Gurobi (donc $EBROOTGUROBI est défini) et scipy-stack (donc scipy est disponible). Les deux sont nécessaires pour exécuter l'exemple de matrice (avec numpy qui était déjà installé dans notre environnement via pandas avec pip dans une étape précédente).
[name@server ~] $ module load gurobi/11.0.1 scipy-stack
source ~/env_gurobi/bin/activate
(env_gurobi) [name@server ~]Les scripts Python comme les exemples fournis avec le module gurobi peuvent alors être exécutés dans l'environnement virtuel avec Python.
(env_gurobi) [name@server ~] $ python $EBROOTGUROBI/examples/python/matrix1.pyDe même, des scripts Python personnalisés tels que les suivants peuvent être soumis en tant que tâches à la file d'attente en écrivant des scripts Slurm qui chargent votre environnement virtuel.
[name@server ~] $ cat my_gurobi_script.py
import pandas as pd
import numpy as np
import gurobipy as gurobi
from gurobipy import *
etcSoumettez le script dans la queue avec sbatch my_slurm_script.sh.
#!/bin/bash
#SBATCH --account=def-somegrp # indiques le nom du compte
#SBATCH --time=0-00:30 # indiquez la limite de temps (jj-hh:mm)
#SBATCH --nodes=1 # utiliser un (1) nœud
#SBATCH --cpus-per-task=4 # indiquez le nombre de CPU
#SBATCH --mem=4000M # demandez toute la mémoire
module load StdEnv/2023
module load gurobi/11.0.1
# module load scipy-stack # uncomment if needed
echo "Threads ${SLURM_CPUS_ON_NODE:-1}" > gurobi.env
source ~/env_gurobi/bin/activate
python my_gurobi_script.py
Pour plus d'information sur la création et l'utilisation des environnements virtuels Python, voir Créer un environnement virtuel dans vos tâches.
Utiliser Gurobi avec Java
Vous devez aussi charger un module Java et ajouter une option à la commande Java pour permettre à l'environnement virtuel Java de localiser les bibliothèques Gurobi, comme dans l'exemple suivant.
#!/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
Utiliser Gurobi avec des notebooks Jupyter
Vous trouverez de l'information sur Resources, Code and Modeling Examples et Optimization with Python – Jupyter Notebook Modeling Examples. Sur le site support.gurobi.com faites une recherche avec Jupyter Notebooks.
Voir aussi cette démonstration, à 38min 28sec de la vidéo.
Comment citer Gurobi
Voir How do I cite Gurobi software for an academic publication?
Getting Help
The Gurobi general Help Center is located here.
Gurobot a new Gurobi AI Agent is available here.
The official online Gurobi documentation is here.
For help using Gurobi on the Alliance submit a ticket.