Python/fr: Difference between revisions

From Alliance Doc
Jump to navigation Jump to search
No edit summary
No edit summary
 
(152 intermediate revisions by 2 users not shown)
Line 5: Line 5:
[http://www.python.org/ Python] est un langage de programmation interprété dont la philosophie de design repose principalement sur la lisibilité du code. Sa syntaxe est simple et expressive et sa bibliothèque de modules standards est très étendue.
[http://www.python.org/ Python] est un langage de programmation interprété dont la philosophie de design repose principalement sur la lisibilité du code. Sa syntaxe est simple et expressive et sa bibliothèque de modules standards est très étendue.


Les capacités du langage Python peuvent être étendues à l'aide de paquets développés par des tiers. En général, nous n'installons pas les paquets de tiers dans le répertoire de logiciels disponibles afin de simplifier le plus possible les opérations; il revient donc aux utilisateurs et aux groupes de les installer. En revanche, nous mettons à votre disposition plusieurs versions de l'interpréteur Python et les outils nécessaires pour que vous puissiez facilement installer les paquets dont vous avez besoin.
Les capacités du langage Python peuvent être étendues à l'aide de paquets développés par des tiers. En général, nous n'installons pas les paquets de tiers dans le répertoire de logiciels disponibles afin de simplifier le plus possible les opérations; il vous revient donc de les installer. En revanche, nous mettons à votre disposition plusieurs versions de l'interpréteur Python et les outils nécessaires pour que vous puissiez facilement installer les paquets dont vous avez besoin.


Les sections suivantes présentent l'interpréteur Python et expliquent comment installer et utiliser les paquets.
Les sections suivantes présentent l'interpréteur Python et expliquent comment installer et utiliser les paquets.
Line 12: Line 12:


===Version par défaut===
===Version par défaut===
Une version est disponible quand vous vous connectez à nos grappes, mais vous aurez souvent besoin d'une version différente, surtout si vous voulez installer des paquets. Trouvez donc la version de Python dont vous avez besoin et [[Utiliser des modules | chargez le module approprié]]. En cas de doute, vous pouvez utiliser la plus récente version disponible.
Une version est disponible quand vous vous connectez à nos grappes, mais vous aurez souvent besoin d'une version différente, surtout si vous voulez installer des paquets. Trouvez la version de Python dont vous avez besoin et [[Utiliser des modules | chargez le module approprié]]. En cas de doute, vous pouvez utiliser la plus récente version disponible.mpi4py comme dépendance d'un autre paquet.


===Charger un module Python ===
===Charger un module Python ===
Line 18: Line 18:
{{Command|module avail python}}
{{Command|module avail python}}


Vous pouvez ensuite charger la version de votre choix avec la commande <tt>module load</tt>, par exemple, pour charger Python 3.10 avec
Vous pouvez ensuite charger la version de votre choix avec la commande <code>module load</code>, par exemple, pour charger Python 3.10 avec
{{Command|module load python/3.10}}
{{Command|module load python/3.10}}


===Version supportée===
===Version supportée===
Les paquets en provenance de la [[Available Python wheels/fr|liste des wheels]] sont fournis surtout pour les trois plus récentes versions de Python disponibles sur les systèmes.
En règle générale dans l'écosystème Python, la transition vers des versions plus modernes s'accélère et plusieurs paquets ne supportent que les quelques dernières versions de Python 3.x. Dans notre cas, nous offrons uniquement des paquets préconstruits  ([[Available Python wheels/fr|wheels Python]]) pour les trois versions les plus récentes disponibles sur nos systèmes. Des problèmes de dépendance se présenteront quand vous tentez d'installer ces paquets avec les plus anciennes versions de Python. Voir [[Python/fr#Message_Package_'X'_requires_a_different_Python:_X.Y.Z_not_in_'>=X.Y'|la section Dépannage]].  


In addition, newer packages version drop support of older Python versions. For instance, one package may require Python to be greater to 3.8. This will result in dependencies issues when trying to install those packages with Python 3.6. See [[Python#Package_.27X.27_requires_a_different_Python:_X.Y.Z_not_in_.27.3E.3DX.Y.27|Troubleshooting]]
Le tableau suivant montre les dates auxquelles nous avons cessé de construire des wheels pour les versions de Python.
 
Drop schedule of Python modules
{| class="wikitable"
{| class="wikitable"
|-
|-
! Python version
! Version
! Date
! Date
|-
|-
Line 77: Line 75:
Avec chaque version de Python vient l'outil [http://pypi.python.org/pypi/virtualenv virtualenv] qui permet de créer des environnements virtuels à l'intérieur desquels vous pourrez installer facilement vos paquets Python. Ces environnements permettent par exemple d'installer plusieurs versions d'un même paquet, ou encore de compartimenter les installations en fonction des besoins ou des expériences à réaliser. Vous créeriez habituellement vos environnements virtuels Python dans votre répertoire /home ou dans un de vos répertoires /project. Pour une troisième option, voyez ci-dessous la section ''Créer un environnement virtuel dans vos tâches''.
Avec chaque version de Python vient l'outil [http://pypi.python.org/pypi/virtualenv virtualenv] qui permet de créer des environnements virtuels à l'intérieur desquels vous pourrez installer facilement vos paquets Python. Ces environnements permettent par exemple d'installer plusieurs versions d'un même paquet, ou encore de compartimenter les installations en fonction des besoins ou des expériences à réaliser. Vous créeriez habituellement vos environnements virtuels Python dans votre répertoire /home ou dans un de vos répertoires /project. Pour une troisième option, voyez ci-dessous la section ''Créer un environnement virtuel dans vos tâches''.


Pour créer un environnement virtuel, sélectionnez d'abord une version de Python avec <tt>module load python</tt>, comme indiqué ci-dessus dans ''Charger un module Python''. Si vous voulez utiliser les paquets listés dans ''Pile logicielle SciPy'', lancez aussi <tt>module load scipy-stack</tt>. Entrez ensuite la prochaine commande, où <tt>ENV</tt> est le nom du répertoire pour votre nouvel environnement.   
{{Warning
|title=Où créer un environnement virtuel
|content=Ne créez pas votre environnement virtuel dans $SCRATCH à cause du risque qu'il soit en partie détruit.
Voyez plutôt [[Python/fr#Créer_un_environnement virtuel_dans_vos_tâches|Créer un environnement virtuel dans vos tâches]] ci-dessous.
}}
 
Pour créer un environnement virtuel, sélectionnez d'abord une version de Python avec <code>module load python/X.Y.Z</code>, comme indiqué ci-dessus dans <i>Charger un module Python</i>. Si vous voulez utiliser les paquets listés dans <i>Pile logicielle SciPy</i>, lancez aussi <code>module load scipy-stack/X.Y.Z</code>. Entrez ensuite la prochaine commande, où <code>ENV</code> est le nom du répertoire pour votre nouvel environnement.   
{{Command|virtualenv --no-download ~/ENV}}
{{Command|virtualenv --no-download ~/ENV}}


Line 83: Line 87:
{{Command|source ~/ENV/bin/activate}}
{{Command|source ~/ENV/bin/activate}}


Vous devriez aussi faire la mise à jour de <tt>pip</tt> dans l'environnement.
Vous devriez aussi faire la mise à jour de <code>pip</code> dans l'environnement.


{{Command|pip install --no-index --upgrade pip}}
{{Command|pip install --no-index --upgrade pip}}
Line 91: Line 95:


Pour réutiliser l'environnement virtuel :
Pour réutiliser l'environnement virtuel :
# Chargez les mêmes modules d'environnement que vous avez chargés quand l'environnement virtuel a été créé, soit <tt>module load python scipy-stack</tt>.
# Chargez les mêmes modules d'environnement que vous avez chargés quand l'environnement virtuel a été créé, soit <code>module load python scipy-stack</code>.
# Activez l'environnement avec <tt>source ENV/bin/activate</tt>.
# Activez l'environnement avec <code>source ENV/bin/activate</code>.


=== Installer des paquets ===
=== Installer des paquets ===
Line 103: Line 107:
{{Command|module load python/3.10}}
{{Command|module load python/3.10}}


Ensuite, activons l'environnement virtuel créé précédemment avec la commande <tt>virtualenv</tt>.
Ensuite, activons l'environnement virtuel créé précédemment avec la commande <code>virtualenv</code>.
{{Command|source ~/ENV/bin/activate}}
{{Command|source ~/ENV/bin/activate}}
Enfin, nous pouvons installer la dernière version stable de NumPy avec
Enfin, nous pouvons installer la dernière version stable de NumPy avec
{{Command|prompt=(ENV) [name@server ~]|pip install numpy --no-index}}
{{Command|prompt=(ENV) [name@server ~]|pip install numpy --no-index}}


La commande <code>pip</code> peut installer des paquets à partir de plusieurs sources, dont PyPI et les paquets de distribution préconstruits appelés Python [https://pythonwheels.com/ wheels]. Calcul Canada fournit des wheels Python pour plusieurs paquets. Dans l'exemple ci-dessus, l'option [https://pip.pypa.io/en/stable/reference/pip_wheel/#cmdoption-no-index <code>--no-index</code>] demande à <code>pip</code> de ''ne pas installer'' à partir de PyPI, mais plutôt de n'installer qu'à partir de paquets de source locale, soit des wheels de Calcul Canada.
La commande <code>pip</code> peut installer des paquets à partir de plusieurs sources, dont PyPI et les paquets de distribution préconstruits appelés [https://pythonwheels.com/ Python wheels]. Nous fournissons des wheels Python pour plusieurs paquets. Dans l'exemple ci-dessus, l'option [https://pip.pypa.io/en/stable/reference/pip_wheel/#cmdoption-no-index <code>--no-index</code>] demande à <code>pip</code> de <i>ne pas installer</i> à partir de PyPI, mais plutôt de n'installer qu'à partir de paquets de source locale, soit de nos wheels.
 
Si un wheel de Calcul Canada est disponible pour un paquet que vous voulez, nous vous recommandons fortement de l'utiliser avec l'option <code>--no-index</code>. Contrairement aux paquets de PyPI, les wheels compilés par le personnel de Calcul Canada évitent les problèmes de dépendances manquantes ou conflictuelles et sont de plus optimisés pour nos grappes et nos bibliothèques. Voyez [[#Lister_les_wheels_disponibles|Wheels disponibles]].


Si vous omettez l'option <code>--no-index</code>, <code>pip</code> cherchera les paquets PyPI et les paquets locaux et utilisera la version la plus récente. Si celle-ci est de PyPI, elle sera installée plutôt que celle de Calcul Canada et vous aurez possiblement des problèmes. Si vous préférez télécharger un paquet PyPI plutôt que d'utiliser un wheel, utilisez l'option <code>--no-binary</code> qui demande à <code>pip</code> de ne considérer aucun paquet préconstruit; ainsi, les wheels distribués via PyPI ne seront pas considérés et le paquet sera toujours compilé de la source.
Si un de nos wheels est disponible pour un paquet que vous voulez, nous vous recommandons fortement de l'utiliser avec l'option <code>--no-index</code>. Contrairement aux paquets de PyPI, les wheels compilés par notre personnel évitent les problèmes de dépendances manquantes ou conflictuelles et sont de plus optimisés pour nos grappes et nos bibliothèques. Voyez [[#Lister_les_wheels_disponibles|Wheels disponibles]].


Pour savoir d'où provient le paquet Python installé par <tt>pip</tt>, ajoutez l'option <tt>-vvv</tt>. Lorsque vous installez plusieurs paquets Python, il est préférable de les installer en une seule étape, puisque <tt>pip</tt> peut alors résoudre les dépendances croisées.
Si vous omettez l'option <code>--no-index</code>, <code>pip</code> cherchera les paquets PyPI et les paquets locaux et utilisera la version la plus récente. Si celle-ci est de PyPI, elle sera installée plutôt la nôtre et vous aurez possiblement des problèmes. Si vous préférez télécharger un paquet PyPI plutôt que d'utiliser un wheel, utilisez l'option <code>--no-binary</code> qui demande à <code>pip</code> de ne considérer aucun paquet préconstruit; ainsi, les wheels distribués via PyPI ne seront pas considérés et le paquet sera toujours compilé de la source.


==== Installation de paquets dépendants ====
Pour savoir d'où provient le paquet Python installé par <code>pip</code>, ajoutez l'option <code>-vvv</code>. Lorsque vous installez plusieurs paquets Python, il est préférable de les installer en une seule étape, puisque <code>pip</code> peut alors résoudre les dépendances croisées.
 
Dans certains cas, par exemple avec TensorFlow ou Pytorch, Calcul Canada offre des wheels particuliers pour  CPU ou GPU, avec les suffixes <tt>_cpu</tt> et <tt>_gpu</tt> respectivement. L'installation de paquets dépendants de <tt>tensorflow</tt> ne fonctionnera pas.
Si <tt>my_package</tt> dépend de <tt>numpy</tt> et <tt>tensorflow</tt>, les commandes suivantes nous permettront de l'installer.
{{Commands|prompt=(ENV) [name@server ~]
|pip install numpy tensorflow_cpu --no-index
|pip install my_package --no-deps
}}
L'option <tt>--no-deps</tt> indique à <tt>pip</tt> de ne pas tenir compte des dépendances.


===Créer un environnement virtuel dans vos tâches===
===Créer un environnement virtuel dans vos tâches===


Les systèmes de fichiers parallèles comme ceux qui sont installés sur les grappes de Calcul Canada sont très efficaces lorsqu'il s'agit de lire ou d'écrire de grandes portions de données, mais pas pour une utilisation intensive de petits fichiers. Pour cette raison, le lancement d'un logiciel et le chargement de bibliothèques peuvent être lents, ce qui se produit quand on lance Python et qu'on charge un environnement virtuel.  
Les systèmes de fichiers parallèles comme ceux qui sont installés sur nos grappes sont très efficaces lorsqu'il s'agit de lire ou d'écrire de grandes portions de données, mais pas pour une utilisation intensive de petits fichiers. Pour cette raison, le lancement d'un logiciel et le chargement de bibliothèques peuvent être lents, ce qui se produit quand on lance Python et qu'on charge un environnement virtuel.  


Pour contrer ce genre de ralentissement, particulièrement pour les tâches Python sur un nœud unique, vous pouvez créer votre environnement virtuel à l'intérieur de votre tâche en utilisant le disque local du nœud de calcul. Il peut sembler déraisonnable de recréer votre environnement pour chacune de vos tâches, mais c'est souvent plus rapide et plus efficace que d'utiliser le système de fichiers parallèles. Il faut créer un virtualenv localement sur chacun des nœuds utilisés par la tâche puisque l'accès à virtualenv se fait par nœud. Le script suivant en est un exemple  
Pour contrer ce genre de ralentissement, particulièrement pour les tâches Python sur un nœud unique, vous pouvez créer votre environnement virtuel à l'intérieur de votre tâche en utilisant le disque local du nœud de calcul. Il peut sembler déraisonnable de recréer votre environnement pour chacune de vos tâches, mais c'est souvent plus rapide et plus efficace que d'utiliser le système de fichiers parallèles. Il faut créer un virtualenv localement sur chacun des nœuds utilisés par la tâche puisque l'accès à virtualenv se fait par nœud. Le script suivant en est un exemple  
Line 150: Line 144:


}}
}}
où le fichier <tt>requirements.txt</tt> aura été créé dans un environnement de test. Par exemple, pour créer un environnement pour [[TensorFlow/fr|TensorFlow]], utilisez les commandes suivantes dans un nœud de connexion :
où le fichier <code>requirements.txt</code> aura été créé dans un environnement de test. Par exemple, pour créer un environnement pour [[TensorFlow/fr|TensorFlow]], utilisez les commandes suivantes dans un nœud de connexion :
{{Commands
{{Commands
|module load python/3.10
|module load python/3.10
Line 158: Line 152:
|pip install --no-index --upgrade pip
|pip install --no-index --upgrade pip
|pip install --no-index tensorflow
|pip install --no-index tensorflow
|pip freeze > requirements.txt
|pip freeze --local > requirements.txt
|deactivate
|deactivate
|rm -rf $ENVDIR
|rm -rf $ENVDIR
}}
}}


Ceci produit le fichier <tt>requirements.txt</tt> dont le contenu ressemble à ceci :
Ceci produit le fichier <code>requirements.txt</code> dont le contenu ressemble à ceci :
{{File
{{File
   |name=requirements.txt
   |name=requirements.txt
Line 212: Line 206:
Ce fichier fait en sorte que votre environnement puisse être reproduit pour les autres tâches.  
Ce fichier fait en sorte que votre environnement puisse être reproduit pour les autres tâches.  


Remarquez que les directives ci-dessus exigent que tous les paquets dont vous avez besoin soient disponibles dans les wheels Python fournis par Calcul Canada. Si ce n'est pas le cas, vous pouvez le prétélécharger (voir Prétélécharger des paquets ci-dessous). Si vous croyez que les wheels devraient être fournis, faites-en la demande au [[Technical support/fr|soutien technique]]
Remarquez que les directives ci-dessus exigent que tous les paquets dont vous avez besoin soient disponibles dans les wheels Python que nous fournissons. Si ce n'est pas le cas, vous pouvez le prétélécharger (voir Prétélécharger des paquets ci-dessous). Si vous croyez que les wheels devraient être fournis, faites-en la demande au [[Technical support/fr|soutien technique]]
 
==== Créer un environnement virtuel dans vos tâches (plusieurs nœuds)====
 
Pour que vos scripts utilisent plusieurs nœuds, chacun doit avoir son propre environnement activé.
 
1. Dans votre script de soumission de la tâche, créez l'environnement virtuel pour chacun des nœuds alloués.
<syntaxhighlight lang="bash">
srun --ntasks $SLURM_NNODES --tasks-per-node=1 bash << EOF
 
virtualenv --no-download $SLURM_TMPDIR/env
source $SLURM_TMPDIR/env/bin/activate
 
pip install --no-index --upgrade pip
pip install --no-index -r requirements.txt
 
EOF
</syntaxhighlight>
 
2. Activez l'environnement virtuel du nœud principal.
<syntaxhighlight lang="bash">source $SLURM_TMPDIR/env/bin/activate;</syntaxhighlight>
 
3. Exécutez le script avec
<syntaxhighlight lang="bash">srun python myscript.py;</syntaxhighlight>
 
==== Exemple (plusieurs nœuds) ====
{{File
  |name=submit-nnodes-venv.sh
  |lang="bash"
  |lines=yes
  |contents=
#!/bin/bash
#SBATCH --account=<your account>
#SBATCH --time=00:30:00
#SBATCH --nodes=2
#SBATCH --ntasks=2
#SBATCH --mem-per-cpu=2000M
 
module load StdEnv/2023 python/3.11 mpi4py
 
# créer l'environnement virtuel pour chacun des nœuds.
srun --ntasks $SLURM_NNODES --tasks-per-node=1 bash << EOF
virtualenv --no-download $SLURM_TMPDIR/env
source $SLURM_TMPDIR/env/bin/activate
 
pip install --no-index --upgrade pip
pip install --no-index -r requirements.txt
EOF
 
# activer uniquement sur le nœud principal                                                             
source $SLURM_TMPDIR/env/bin/activate;
# srun exporte l'environnement actuel qui contient
$VIRTUAL_ENV and $PATH variables
srun python myscript-mpi.py;
}}


=== Wheels disponibles ===
=== Wheels disponibles ===
Les wheels présentement disponibles sont listés sur la page [[Available Python wheels/fr|Wheels Python]]. Vous pouvez aussi utiliser la commande <tt>avail_wheels</tt> sur la grappe.
Les wheels présentement disponibles sont listés sur la page [[Available Python wheels/fr|Wheels Python]]. Vous pouvez aussi utiliser la commande <code>avail_wheels</code> sur la grappe.
Par défaut, cette commande montre seulement
Par défaut, cette commande montre seulement
* la '''plus récente version''' d'un paquet en particulier, à moins qu'une version particulière n'ait été spécifiée;
* la <b>plus récente version</b> d'un paquet en particulier, à moins qu'une version particulière n'ait été spécifiée;
* les versions compatibles avec le module Python chargé ou l'environnement virtuel activé; autrement, toutes les versions sont affichées;
* les versions compatibles avec le module Python chargé ou l'environnement virtuel activé; autrement, toutes les versions sont affichées;
* les versions compatibles avec l'architecture CPU que vous utilisez à ce moment.
* les versions compatibles avec l'architecture CPU et l'environnement logiciel (StdEnv) que vous utilisez à ce moment.


==== Names ====
==== Noms ====
To list wheels containing <tt>cdf</tt> (case insensitive) in its name:
Pour la liste des wheels qui contiennent <code>cdf</code> (insensible à la casse) dans leur nom, lancez
{{Command
{{Command
|avail_wheels "*cdf*"
|avail_wheels "*cdf*"
Line 234: Line 282:
}}
}}


Or an exact name:
ou utilisez le nom exact, par exemple
{{Command
{{Command
|avail_wheels numpy
|avail_wheels numpy
Line 246: Line 294:


==== Version ====
==== Version ====
To list a specific version, one can use the same format as with `pip`:
Pour la liste d'une version particulière, vous pouvez utiliser le même format qu'avec `pip`:
{{Command
{{Command
|avail_wheels numpy{{=}}{{=}}1.23
|avail_wheels numpy{{=}}{{=}}1.23
Line 256: Line 304:
numpy  1.23.0    cp310    generic
numpy  1.23.0    cp310    generic
}}
}}
Or use the long option:
ou employer la version plus longue, comme
{{Command
{{Command
|avail_wheels numpy --version 1.23
|avail_wheels numpy --version 1.23
Line 266: Line 314:
numpy  1.23.0    cp310    generic
numpy  1.23.0    cp310    generic
}}
}}
With the <tt>pip</tt> format, one can use different operators : <tt>==</tt>, <tt><</tt>, <tt>></tt>, <tt>~=</tt>, <tt><=</tt>,<tt>>=</tt>, <tt>!=</tt>. For instance, to list inferior versions:
Avec le format <code>pip</code>, vous pouvez utiliser différents opérateurs%nbsp: <code>==</code>, <code><</code>, <code>></code>, <code>~=</code>, <code><=</code>,<code>>=</code>, <code>!=</code>. Par exemple, pour lister les versions précédentes,
{{Command
{{Command
|avail_wheels 'numpy<1.23'
|avail_wheels 'numpy<1.23'
Line 276: Line 324:
numpy  1.22.2    cp310    generic
numpy  1.22.2    cp310    generic
}}
}}
And to list all available versions:
et pour lister toutes les versions disponibles,
{{Command
{{Command
|avail_wheels "*cdf*" --all-version
|avail_wheels "*cdf*" --all-version
Line 294: Line 342:


==== Python ====
==== Python ====
One can list a specific version of Python:
Pour lister une version particulière de Python, lancez
{{Command
{{Command
|avail_wheels 'numpy<1.23' --python 3.9
|avail_wheels 'numpy<1.23' --python 3.9
Line 302: Line 350:
numpy  1.22.2    cp39      generic
numpy  1.22.2    cp39      generic
}}
}}
The ''python'' column tell us for which python version the wheel is available, where <tt>cp39</tt> stands for <tt>cpython 3.9</tt>.
La colonne <i>python</i> montre la version de Python pour laquelle le wheel est disponible, <code>cp39</code> est utilisé pour <code>cpython 3.9</code>.


==== Requirements file ====
==== Requirements file ====
One can list available wheels based on a <tt>requirements.txt</tt> file with:
Pour savoir si les wheels disponibles incluent ceux qui sont indiqués dans le fichier <code>requirements.txt</code>, lancez
{{Command
{{Command
|avail_wheels -r requirements.txt  
|avail_wheels -r requirements.txt  
Line 314: Line 362:
tabulate  0.8.10    py3      generic
tabulate  0.8.10    py3      generic
}}
}}
And display wheels that are not available:
Pour la liste de ceux qui ne sont pas disponibles, la commande est
{{Command
{{Command
|avail_wheels -r requirements.txt --not-available
|avail_wheels -r requirements.txt --not-available
Line 327: Line 375:
=== Prétélécharger des paquets ===
=== Prétélécharger des paquets ===


La procédure suivante prétélécharge le paquet <tt>tensorboardX</tt> sur un nœud de connexion et l'installe sur un nœud de calcul :
La procédure suivante prétélécharge le paquet <code>tensorboardX</code> sur un nœud de connexion et l'installe sur un nœud de calcul :


# Lancez <tt>pip download --no-deps tensorboardX</tt> pour télécharger le paquet <tt>tensorboardX-1.9-py2.py3-none-any.whl</tt> (ou semblable) dans le répertoire de travail. La syntaxe pour <tt>pip download</tt> est la même que celle pour <tt>pip install</tt>.
# Lancez <code>pip download --no-deps tensorboardX</code> pour télécharger le paquet <code>tensorboardX-1.9-py2.py3-none-any.whl</code> (ou semblable) dans le répertoire de travail. La syntaxe pour <code>pip download</code> est la même que celle pour <code>pip install</code>.
# Si le nom du fichier ne se termine pas pas <tt>none-any</tt>, mais par <tt>linux_x86_64</tt> ou <tt>manylinux*_x86_64</tt>, il est possible que le wheel ne fonctionnera pas correctement. Cpontactez le [[Technical support/fr|soutien technique]] pour que nous compilions le wheel et le rendre disponible sur nos superordinateurs.
# Si le nom du fichier ne se termine pas pas <code>none-any</code>, mais par <code>linux_x86_64</code> ou <code>manylinux*_x86_64</code>, il est possible que le wheel ne fonctionnera pas correctement. Contactez le [[Technical support/fr|soutien technique]] pour que nous compilions le wheel et le rendre disponible sur nos superordinateurs.
# À l'installation, utilisez le chemin du fichier <tt>pip install tensorboardX-1.9-py2.py3-none-any.whl</tt>.
# À l'installation, utilisez le chemin du fichier <code>pip install tensorboardX-1.9-py2.py3-none-any.whl</code>.


== Programmation parallèle avec le module <tt>multiprocessing</tt> ==
== Programmation parallèle avec le module <code>multiprocessing</code> ==


La programmation parallèle avc Python est un moyen facile d'obtenir des résultats plus rapidement, ce qui est habituellement accompli avec l'utilisation du module [https://sebastianraschka.com/Articles/2014_multiprocessing.html <tt>multiprocessing</tt>]. La classe <tt>Pool</tt> de ce module est particulièrement intéressante car elle permet de contrôler le nombre de processus lancés en parallèle pour exécuter le même calcul avec des données multiples. Supposons que nous voulons calculer le <tt>cube</tt> d'une liste de nombres; le code série serait semblable à :  
La programmation parallèle avec Python est un moyen facile d'obtenir des résultats plus rapidement, ce qui est habituellement accompli avec l'utilisation du module [https://sebastianraschka.com/Articles/2014_multiprocessing.html <code>multiprocessing</code>]. La classe <code>Pool</code> de ce module est particulièrement intéressante car elle permet de contrôler le nombre de processus lancés en parallèle pour exécuter le même calcul avec des données multiples. Supposons que nous voulons calculer le <codet>cube</code> d'une liste de nombres; le code série serait semblable à :  
<tabs>
<tabs>
<tab name="Avec une boucle">
<tab name="Avec une boucle">
Line 365: Line 413:
</tabs>
</tabs>


Avec la classe <tt>Pool</tt> le code parallèle devient :  
Avec la classe <code>Pool</code> le code parallèle devient :  
<tabs>
<tabs>
<tab name="Avec une boucle">
<tab name="Avec une boucle">
Line 450: Line 498:
</tabs>
</tabs>


Remarquez que dans cet exemple, la fonction <tt>cube</tt> est en elle-même séquentielle. Il est possible qu'une fonction appelée d'une bibliothèque externe comme <tt>numpy</tt> soit en elle-même parallèle. Pour distribuer des processus avec la technique précédente, vérifiez d'abord si les fonctions appelées sont en elles-mêmes parallèles et si c'est le cas, vous devrez contrôler le nombre de fils qu'elles utiliseront. Si comme dans l'exemple les fonctions utilisent la totalité des cœurs disponibles (ici 32) et que vous lancez 32 processus, votre code sera plus lent et le nœud sera possiblement surchargé.
Remarquez que dans cet exemple, la fonction <code>cube</code> est en elle-même séquentielle. Il est possible qu'une fonction appelée d'une bibliothèque externe comme <code>numpy</code> soit en elle-même parallèle. Pour distribuer des processus avec la technique précédente, vérifiez d'abord si les fonctions appelées sont en elles-mêmes parallèles et si c'est le cas, vous devrez contrôler le nombre de fils qu'elles utiliseront. Si comme dans l'exemple les fonctions utilisent la totalité des cœurs disponibles (ici 32) et que vous lancez 32 processus, votre code sera plus lent et le nœud sera possiblement surchargé.


Comme le module <tt>multiprocessing</tt> ne peut utiliser qu'un seul nœud de calcul, le gain en performance est habituellement limité au nombre de cœurs CPU du nœud. Si vous voulez dépasser cette limite et utiliser plusieurs nœuds, considérez mpi4py ou [[Apache Spark#PySpark|PySpark]]. Il existe [https://wiki.python.org/moin/ParallelProcessing d'autres méthodes de parallélisation], mais elles ne peuvent pas toutes être utilisées avec les grappes de Calcul Canada. Souvenez-vous toutefois qu'un code de qualité fournira toujours la meilleure performance; avant de le paralléliser, assurez-vous donc que votre code est optimal. Si vous doutez de l'efficacité de votre code, contactez le [[Technical support/fr|soutien technique]].
Comme le module <code>multiprocessing</code> ne peut utiliser qu'un seul nœud de calcul, le gain en performance est habituellement limité au nombre de cœurs CPU du nœud. Si vous voulez dépasser cette limite et utiliser plusieurs nœuds, considérez mpi4py ou [[Apache Spark#PySpark|PySpark]]. Il existe [https://wiki.python.org/moin/ParallelProcessing d'autres méthodes de parallélisation], mais elles ne peuvent pas toutes être utilisées avec nos grappes. Souvenez-vous toutefois qu'un code de qualité fournira toujours la meilleure performance; avant de le paralléliser, assurez-vous donc que votre code est optimal. Si vous doutez de l'efficacité de votre code, contactez le [[Technical support/fr|soutien technique]].


== Anaconda ==
== Anaconda ==
Line 475: Line 523:
# Lancez <code>py-spy dump --pid PID</code> pour obtenir une trace de l'état de votre code.
# Lancez <code>py-spy dump --pid PID</code> pour obtenir une trace de l'état de votre code.


=== ''Package 'X' requires a different Python: X.Y.Z not in '>=X.Y' ''===
=== Message Package 'X' requires a different Python: X.Y.Z not in '>=X.Y' ===
En installant un paquet, vous pourriez avoir une erreur comme <tt>ERROR: Package 'X' requires a different Python: 3.6.10 not in '>=3.7'</tt>.
En installant un paquet, vous pourriez avoir une erreur comme <code>ERROR: Package 'X' requires a different Python: 3.6.10 not in '>=3.7'</code>.


The current python module loaded (3.6.10 in this case) is not supported by that package. You can update to a more recent python version, such as the latest available module. Or install an older version of package 'X'.
Dans ce cas, le module Python 3.6.10 qui est chargé n'est pas supporté par le paquet. Vous pouvez utiliser une version de Python plus récente, comme le dernier module disponible, ou encore installer une version moins récente du paquet X.


=== Package has requirement X, but you'll have Y which is incompatible  ===
=== Message Package has requirement X, but you'll have Y which is incompatible  ===
When installing packages, you may encounter an error similar to:
En installant un paquet, vous pourriez avoir une erreur comme
<tt>ERROR: Package has requirement X, but you'll have Y which is incompatible.</tt>.
<code>ERROR: Package has requirement X, but you'll have Y which is incompatible.</code>.


Upgrade <tt>pip</tt> to the latest version or higher than <tt>[[https://pip.pypa.io/en/stable/news/#v21-3 21.3]]</tt> to use the new dependency resolver:
Pour utiliser le nouveau résolveur de dépendances, installez la plus récente version de <code>pip</code> ou une version supérieure à <code>[[https://pip.pypa.io/en/stable/news/#v21-3 21.3]]</code>.
{{Command
{{Command
|prompt=(ENV) [name@server ~]
|prompt=(ENV) [name@server ~]
|pip install --no-index --upgrade pip}}
|pip install --no-index --upgrade pip}}
Then re-run your install command.
Lancez ensuite de nouveau la commande d'installation.


=== No matching distribution found for X ===
=== Message No matching distribution found for X ===
When installing packages, you may encounter an error similar to:
À l'installation d'un paquet, vous pouvez obtenir un message semblable à
{{Command
{{Command
|prompt=(ENV) [name@server ~]
|prompt=(ENV) [name@server ~]
Line 499: Line 547:
ERROR: No matching distribution found for X
ERROR: No matching distribution found for X
}}
}}
<tt>pip</tt> did not find a package to install that satisfies the requirements (name or version).
<code>pip</code> n'a trouvé aucun paquet à installer qui rencontre les exigences (nom, version ou tags).
Verify that the name and version are correct.
Assurez-vous que le nom et la version sont corrects.
Sachez aussi que les wheels <code>manylinux_x_y</code> sont ignorés.


You can also verify that the package is available from the wheelhouse with [[Python#Available_wheels|avail_wheels]] command or by searching on [[Available Python wheels]] page.
Vous pouvez aussi vérifier si le paquet est disponible avec la commande [[Python/fr#Wheels_disponibles|avail_wheels]] ou en consultant la page  [[Available Python wheels/fr|Wheels disponibles]].


=== Installing many packages ===
=== Installation de plusieurs paquets ===
When installing multiple packages, it is best to install them in one command when possible:
Lorsque possible, il est préférable d'installer plusieurs paquets avec une seule commande.
{{Commands
{{Commands
|prompt=(ENV) [name@server ~]
|prompt=(ENV) [name@server ~]
Line 511: Line 560:
|pip install package1 package2 package3 package4
|pip install package1 package2 package3 package4
}}
}}
as this helps <tt>pip</tt> resolve dependencies issues.
Ainsi, <code>pip</code> peut résoudre plus facilement les problèmes de dépendance.
 
=== Mon environnement virtuel fonctionnait hier, mais pas aujourd'hui ===
Les fréquentes mises à jour des paquets font en sorte qu'un environnement virtuel ne peut souvent pas être reproduit.
 
Il est possible aussi qu'un environnement virtuel créé dans $SCRATCH soit partiellement détruit lors de la purge automatique de ce système de fichiers, ce qui empêcherait l'environnement virtuel de bien fonctionner.


=== My virtual environment was working yesterday but not anymore ===
Pour contrer ceci, gelez les paquets et leurs versions avec
Packages are often updated and this lead to a non-reproducible virtual environment. To remedy that, one should pin the specific packages and their versions with
{{Commands
{{Commands
|prompt=(ENV) [name@server ~]
|prompt=(ENV) [name@server ~]
|pip install --upgrade pip
|pip install --upgrade pip
|pip install --no-index package1{{=}}{{=}}X.Y package2{{=}}{{=}}X.Y.Z package3<X.Y package4>X.Y
|pip install --no-index 'package1{{=}}{{=}}X.Y' 'package2{{=}}{{=}}X.Y.Z' 'package3<X.Y' 'package4>X.Y'
}}
}}
and then create a [[Python#Creating_virtual_environments_inside_of_your_jobs|requirements file]] to install from when submitting jobs.
et créez ensuite un [[Python/fr#Créer_un_environnement_virtuel_dans_vos_tâches|fichier de requis]] qui sera utilisé pour installer ces paquets dans votre tâche.
 
=== Le wheel X n'est pas pris en charge sur cette plateforme ===
À l'installation d'un paquet, vous pourriez obtenir une erreur comme  <code>ERROR: package-3.8.1-cp311-cp311-manylinux_2_28_x86_64.whl is not a supported wheel on this platform.</code>
 
Certains paquets peuvent être incompatibles ou non pris en charge par nos systèmes.
Deux cas fréquents sont :
* installation d'un  paquet <code>manylinux</code>
* ou un paquet Python construit pour une autre version de Python (par exemple, installer un paquet construit pour Python 3.11 quand vous avez Python 3.9).
 
Certains paquets <code>manylinux</code> peuvent se trouver parmi nos [[Available Python wheels/fr|wheels Python]].
 
=== Message AttributeError: module ‘numpy’ has no attribute ‘X’ ===
À l'installation d'un whell, la plus récente version de Numpy est installée si aucune version spécifique n'est demandée.
Plusieurs attributs  ont été déclarés obsolètes dans Numpy v1.20 et  [https://numpy.org/devdocs/release/1.24.0-notes.html#expired-deprecations ne sont plus offerts dans v1.24].
 
Dépendant de l'attribut, une erreur comme <code>AttributeError: module ‘numpy’ has no attribute ‘bool’</code> pourrait survenir.
 
Ceci est résolu avec l'installation d'une version précédente de Numpy avec <code>pip install --no-index 'numpy<1.24'</code>.
 
=== Message ModuleNotFoundError: No module named 'X' ===
Il est possible qu'un module Python que vous voulez importer ne soit pas trouvé. Il y a plusieurs explications pour ceci, mais les plus fréquentes sont que
* le paquet n'est pas installé ou encore il n'est pas visible pour l'interpréteur Python;
* le nom du module ne correspond pas au nom réel;
* l'environnement virtuel est défectueux.
 
Pour contrer ceci, évitez de
* modifier la variable d'environnement <code>PYTHONPATH</code>;
* modifier la variable d'environnement <code>PATH</code>;
* charger un module alors qu'un environnement virtuel est activé; chargez d'abord tous les modules avant d'activer l'environnement virtuel.
 
Si vous avez ce problème,
* avec <code>pip list</code>, vérifiez si le paquet est installé;
* vérifiez encore si le nom que vous entrez correspond exactement au nom du module (majuscules, minuscules, traits de soulignement, etc.);
* vérifiez si le module est importé au bon niveau quand il provient de son répertoire source.
 
Dans le doute, recommencez avec un nouvel environnement.
 
=== Message ImportError: numpy.core.multiarray failed to import ===
 
Ce message peut survenir quand vous tentez d'importer un module Python qui dépend de Numpy.
 
Ceci se produit quand une version incompatible de Numpy est installée ou utilisée; vous devez installer une version compatible.
 
Le cas type est  [https://numpy.org/devdocs/dev/depending_on_numpy.html#numpy-2-0-specific-advice la version 2.0 de Numpy qui brise l'ABI.]
Dans le cas d'un wheel construit avec une version 1.x mais installé avec une version 2.x, vous devez installer une version antérieure avec <code>pip install --no-index 'numpy<2.0'</code>.

Latest revision as of 19:46, 17 October 2024

Other languages:

Description

Python est un langage de programmation interprété dont la philosophie de design repose principalement sur la lisibilité du code. Sa syntaxe est simple et expressive et sa bibliothèque de modules standards est très étendue.

Les capacités du langage Python peuvent être étendues à l'aide de paquets développés par des tiers. En général, nous n'installons pas les paquets de tiers dans le répertoire de logiciels disponibles afin de simplifier le plus possible les opérations; il vous revient donc de les installer. En revanche, nous mettons à votre disposition plusieurs versions de l'interpréteur Python et les outils nécessaires pour que vous puissiez facilement installer les paquets dont vous avez besoin.

Les sections suivantes présentent l'interpréteur Python et expliquent comment installer et utiliser les paquets.

Charger l'interpréteur

Version par défaut

Une version est disponible quand vous vous connectez à nos grappes, mais vous aurez souvent besoin d'une version différente, surtout si vous voulez installer des paquets. Trouvez la version de Python dont vous avez besoin et chargez le module approprié. En cas de doute, vous pouvez utiliser la plus récente version disponible.mpi4py comme dépendance d'un autre paquet.

Charger un module Python

Pour connaître les versions disponibles, utilisez

Question.png
[name@server ~]$ module avail python

Vous pouvez ensuite charger la version de votre choix avec la commande module load, par exemple, pour charger Python 3.10 avec

Question.png
[name@server ~]$ module load python/3.10

Version supportée

En règle générale dans l'écosystème Python, la transition vers des versions plus modernes s'accélère et plusieurs paquets ne supportent que les quelques dernières versions de Python 3.x. Dans notre cas, nous offrons uniquement des paquets préconstruits (wheels Python) pour les trois versions les plus récentes disponibles sur nos systèmes. Des problèmes de dépendance se présenteront quand vous tentez d'installer ces paquets avec les plus anciennes versions de Python. Voir la section Dépannage.

Le tableau suivant montre les dates auxquelles nous avons cessé de construire des wheels pour les versions de Python.

Version Date
3.10
3.9
3.8
3.7 2022-02
3.6 2021-02
3.5 2020-02
2.7 2020-01

Pile logicielle SciPy

En plus du module Python de base, le paquet SciPy est aussi disponible comme module d'environnement. Le module scipy-stack comprend

  • NumPy
  • SciPy
  • Matplotlib
    • dateutil
    • pytz
  • IPython
    • pyzmq
    • tornado
  • pandas
  • Sympy
  • nose

Pour utiliser un de ces paquets, chargez une version de Python, puis module load scipy-stack.

Pour la liste et les numéros de version des paquets contenus dans scipy-stack, lancez module spider scipy-stack/2020a (en remplaçant 2020a par la version que vous voulez).

Créer et utiliser un environnement virtuel

Avec chaque version de Python vient l'outil virtualenv qui permet de créer des environnements virtuels à l'intérieur desquels vous pourrez installer facilement vos paquets Python. Ces environnements permettent par exemple d'installer plusieurs versions d'un même paquet, ou encore de compartimenter les installations en fonction des besoins ou des expériences à réaliser. Vous créeriez habituellement vos environnements virtuels Python dans votre répertoire /home ou dans un de vos répertoires /project. Pour une troisième option, voyez ci-dessous la section Créer un environnement virtuel dans vos tâches.


Où créer un environnement virtuel

Ne créez pas votre environnement virtuel dans $SCRATCH à cause du risque qu'il soit en partie détruit. Voyez plutôt Créer un environnement virtuel dans vos tâches ci-dessous.



Pour créer un environnement virtuel, sélectionnez d'abord une version de Python avec module load python/X.Y.Z, comme indiqué ci-dessus dans Charger un module Python. Si vous voulez utiliser les paquets listés dans Pile logicielle SciPy, lancez aussi module load scipy-stack/X.Y.Z. Entrez ensuite la prochaine commande, où ENV est le nom du répertoire pour votre nouvel environnement.

Question.png
[name@server ~]$ virtualenv --no-download ~/ENV

Une fois l'environnement virtuel créé, il ne vous reste plus qu'à l'activer avec

Question.png
[name@server ~]$ source ~/ENV/bin/activate

Vous devriez aussi faire la mise à jour de pip dans l'environnement.

Question.png
[name@server ~]$ pip install --no-index --upgrade pip

Pour quitter l'environnement virtuel, entrez simplement la commande

Question.png
(ENV) [name@server ~] deactivate

Pour réutiliser l'environnement virtuel :

  1. Chargez les mêmes modules d'environnement que vous avez chargés quand l'environnement virtuel a été créé, soit module load python scipy-stack.
  2. Activez l'environnement avec source ENV/bin/activate.

Installer des paquets

Une fois que vous avez chargé un environnement virtuel, vous pouvez lancer la commande pip. Cette commande prend en charge la compilation et l'installation de la plupart des paquets Python et de leurs dépendances. Consultez l'index complet des paquets Python.

Les commandes disponibles sont expliquées dans le manuel d'utilisation pip. Nous mentionnons ici les commandes les plus importantes en présentant un exemple d'installation du paquet NumPy.

Chargeons d'abord l'interpréteur Python avec

Question.png
[name@server ~]$ module load python/3.10

Ensuite, activons l'environnement virtuel créé précédemment avec la commande virtualenv.

Question.png
[name@server ~]$ source ~/ENV/bin/activate

Enfin, nous pouvons installer la dernière version stable de NumPy avec

Question.png
(ENV) [name@server ~] pip install numpy --no-index

La commande pip peut installer des paquets à partir de plusieurs sources, dont PyPI et les paquets de distribution préconstruits appelés Python wheels. Nous fournissons des wheels Python pour plusieurs paquets. Dans l'exemple ci-dessus, l'option --no-index demande à pip de ne pas installer à partir de PyPI, mais plutôt de n'installer qu'à partir de paquets de source locale, soit de nos wheels.

Si un de nos wheels est disponible pour un paquet que vous voulez, nous vous recommandons fortement de l'utiliser avec l'option --no-index. Contrairement aux paquets de PyPI, les wheels compilés par notre personnel évitent les problèmes de dépendances manquantes ou conflictuelles et sont de plus optimisés pour nos grappes et nos bibliothèques. Voyez Wheels disponibles.

Si vous omettez l'option --no-index, pip cherchera les paquets PyPI et les paquets locaux et utilisera la version la plus récente. Si celle-ci est de PyPI, elle sera installée plutôt la nôtre et vous aurez possiblement des problèmes. Si vous préférez télécharger un paquet PyPI plutôt que d'utiliser un wheel, utilisez l'option --no-binary qui demande à pip de ne considérer aucun paquet préconstruit; ainsi, les wheels distribués via PyPI ne seront pas considérés et le paquet sera toujours compilé de la source.

Pour savoir d'où provient le paquet Python installé par pip, ajoutez l'option -vvv. Lorsque vous installez plusieurs paquets Python, il est préférable de les installer en une seule étape, puisque pip peut alors résoudre les dépendances croisées.

Créer un environnement virtuel dans vos tâches

Les systèmes de fichiers parallèles comme ceux qui sont installés sur nos grappes sont très efficaces lorsqu'il s'agit de lire ou d'écrire de grandes portions de données, mais pas pour une utilisation intensive de petits fichiers. Pour cette raison, le lancement d'un logiciel et le chargement de bibliothèques peuvent être lents, ce qui se produit quand on lance Python et qu'on charge un environnement virtuel.

Pour contrer ce genre de ralentissement, particulièrement pour les tâches Python sur un nœud unique, vous pouvez créer votre environnement virtuel à l'intérieur de votre tâche en utilisant le disque local du nœud de calcul. Il peut sembler déraisonnable de recréer votre environnement pour chacune de vos tâches, mais c'est souvent plus rapide et plus efficace que d'utiliser le système de fichiers parallèles. Il faut créer un virtualenv localement sur chacun des nœuds utilisés par la tâche puisque l'accès à virtualenv se fait par nœud. Le script suivant en est un exemple


File : submit_venv.sh

#!/bin/bash
#SBATCH --account=def-someuser
#SBATCH --mem-per-cpu=1.5G      # increase as needed
#SBATCH --time=1:00:00

module load python/3.10
virtualenv --no-download $SLURM_TMPDIR/env
source $SLURM_TMPDIR/env/bin/activate
pip install --no-index --upgrade pip

pip install --no-index -r requirements.txt
python ...


où le fichier requirements.txt aura été créé dans un environnement de test. Par exemple, pour créer un environnement pour TensorFlow, utilisez les commandes suivantes dans un nœud de connexion :

[name@server ~]$ module load python/3.10
[name@server ~]$ ENVDIR=/tmp/$RANDOM
[name@server ~]$ virtualenv --no-download $ENVDIR
[name@server ~]$ source $ENVDIR/bin/activate
[name@server ~]$ pip install --no-index --upgrade pip
[name@server ~]$ pip install --no-index tensorflow
[name@server ~]$ pip freeze --local > requirements.txt
[name@server ~]$ deactivate
[name@server ~]$ rm -rf $ENVDIR


Ceci produit le fichier requirements.txt dont le contenu ressemble à ceci :

File : requirements.txt

absl_py==1.2.0+computecanada
astunparse==1.6.3+computecanada
cachetools==5.2.0+computecanada
certifi==2022.6.15+computecanada
charset_normalizer==2.1.0+computecanada
flatbuffers==1.12+computecanada
gast==0.4.0+computecanada
google-pasta==0.2.0+computecanada
google_auth==2.9.1+computecanada
google_auth_oauthlib==0.4.6+computecanada
grpcio==1.47.0+computecanada
h5py==3.6.0+computecanada
idna==3.3+computecanada
keras==2.9.0+computecanada
Keras-Preprocessing==1.1.2+computecanada
libclang==14.0.1+computecanada
Markdown==3.4.1+computecanada
numpy==1.23.0+computecanada
oauthlib==3.2.0+computecanada
opt-einsum==3.3.0+computecanada
packaging==21.3+computecanada
protobuf==3.19.4+computecanada
pyasn1==0.4.8+computecanada
pyasn1-modules==0.2.8+computecanada
pyparsing==3.0.9+computecanada
requests==2.28.1+computecanada
requests_oauthlib==1.3.1+computecanada
rsa==4.8+computecanada
six==1.16.0+computecanada
tensorboard==2.9.1+computecanada
tensorboard-data-server==0.6.1+computecanada
tensorboard_plugin_wit==1.8.1+computecanada
tensorflow==2.9.0+computecanada
tensorflow_estimator==2.9.0+computecanada
tensorflow_io_gcs_filesystem==0.23.1+computecanada
termcolor==1.1.0+computecanada
typing_extensions==4.3.0+computecanada
urllib3==1.26.11+computecanada
Werkzeug==2.1.2+computecanada
wrapt==1.13.3+computecanada


Ce fichier fait en sorte que votre environnement puisse être reproduit pour les autres tâches.

Remarquez que les directives ci-dessus exigent que tous les paquets dont vous avez besoin soient disponibles dans les wheels Python que nous fournissons. Si ce n'est pas le cas, vous pouvez le prétélécharger (voir Prétélécharger des paquets ci-dessous). Si vous croyez que les wheels devraient être fournis, faites-en la demande au soutien technique

Créer un environnement virtuel dans vos tâches (plusieurs nœuds)

Pour que vos scripts utilisent plusieurs nœuds, chacun doit avoir son propre environnement activé.

1. Dans votre script de soumission de la tâche, créez l'environnement virtuel pour chacun des nœuds alloués.

srun --ntasks $SLURM_NNODES --tasks-per-node=1 bash << EOF

virtualenv --no-download $SLURM_TMPDIR/env
source $SLURM_TMPDIR/env/bin/activate

pip install --no-index --upgrade pip
pip install --no-index -r requirements.txt

EOF

2. Activez l'environnement virtuel du nœud principal.

source $SLURM_TMPDIR/env/bin/activate;

3. Exécutez le script avec

srun python myscript.py;

Exemple (plusieurs nœuds)

File : submit-nnodes-venv.sh

#!/bin/bash
#SBATCH --account=<your account>
#SBATCH --time=00:30:00
#SBATCH --nodes=2
#SBATCH --ntasks=2
#SBATCH --mem-per-cpu=2000M

module load StdEnv/2023 python/3.11 mpi4py

# créer l'environnement virtuel pour chacun des nœuds.
srun --ntasks $SLURM_NNODES --tasks-per-node=1 bash << EOF
virtualenv --no-download $SLURM_TMPDIR/env
source $SLURM_TMPDIR/env/bin/activate

pip install --no-index --upgrade pip
pip install --no-index -r requirements.txt
EOF

# activer uniquement sur le nœud principal                                                               
source $SLURM_TMPDIR/env/bin/activate;
# srun exporte l'environnement actuel qui contient
 $VIRTUAL_ENV and $PATH variables
srun python myscript-mpi.py;


Wheels disponibles

Les wheels présentement disponibles sont listés sur la page Wheels Python. Vous pouvez aussi utiliser la commande avail_wheels sur la grappe. Par défaut, cette commande montre seulement

  • la plus récente version d'un paquet en particulier, à moins qu'une version particulière n'ait été spécifiée;
  • les versions compatibles avec le module Python chargé ou l'environnement virtuel activé; autrement, toutes les versions sont affichées;
  • les versions compatibles avec l'architecture CPU et l'environnement logiciel (StdEnv) que vous utilisez à ce moment.

Noms

Pour la liste des wheels qui contiennent cdf (insensible à la casse) dans leur nom, lancez

Question.png
[name@server ~]$ avail_wheels "*cdf*"
name      version    python    arch
--------  ---------  --------  -------
h5netcdf  0.7.4      py2,py3   generic
netCDF4   1.5.8      cp39      avx2
netCDF4   1.5.8      cp38      avx2
netCDF4   1.5.8      cp310     avx2

ou utilisez le nom exact, par exemple

Question.png
[name@server ~]$ avail_wheels numpy
name    version    python    arch
------  ---------  --------  -------
numpy   1.23.0     cp39      generic
numpy   1.23.0     cp38      generic
numpy   1.23.0     cp310     generic

Version

Pour la liste d'une version particulière, vous pouvez utiliser le même format qu'avec `pip`:

Question.png
[name@server ~]$ avail_wheels numpy==1.23
name    version    python    arch
------  ---------  --------  -------
numpy   1.23.0     cp39      generic
numpy   1.23.0     cp38      generic
numpy   1.23.0     cp310     generic

ou employer la version plus longue, comme

Question.png
[name@server ~]$ avail_wheels numpy --version 1.23
name    version    python    arch
------  ---------  --------  -------
numpy   1.23.0     cp39      generic
numpy   1.23.0     cp38      generic
numpy   1.23.0     cp310     generic

Avec le format pip, vous pouvez utiliser différents opérateurs%nbsp: ==, <, >, ~=, <=,>=, !=. Par exemple, pour lister les versions précédentes,

Question.png
[name@server ~]$ avail_wheels 'numpy<1.23'
name    version    python    arch
------  ---------  --------  -------
numpy   1.22.2     cp39      generic
numpy   1.22.2     cp38      generic
numpy   1.22.2     cp310     generic

et pour lister toutes les versions disponibles,

Question.png
[name@server ~]$ avail_wheels "*cdf*" --all-version
name      version    python    arch
--------  ---------  --------  -------
h5netcdf  0.7.4      py2,py3   generic
netCDF4   1.5.8      cp39      avx2
netCDF4   1.5.8      cp38      avx2
netCDF4   1.5.8      cp310     avx2
netCDF4   1.5.6      cp38      avx2
netCDF4   1.5.6      cp37      avx2
netCDF4   1.5.4      cp38      avx2
netCDF4   1.5.4      cp37      avx2
netCDF4   1.5.4      cp36      avx2

Python

Pour lister une version particulière de Python, lancez

Question.png
[name@server ~]$ avail_wheels 'numpy<1.23' --python 3.9
name    version    python    arch
------  ---------  --------  -------
numpy   1.22.2     cp39      generic

La colonne python montre la version de Python pour laquelle le wheel est disponible, où cp39 est utilisé pour cpython 3.9.

Requirements file

Pour savoir si les wheels disponibles incluent ceux qui sont indiqués dans le fichier requirements.txt, lancez

Question.png
[name@server ~]$ avail_wheels -r requirements.txt 
name       version    python    arch
---------  ---------  --------  -------
packaging  21.3       py3       generic
tabulate   0.8.10     py3       generic

Pour la liste de ceux qui ne sont pas disponibles, la commande est

Question.png
[name@server ~]$ avail_wheels -r requirements.txt --not-available
name       version    python    arch
---------  ---------  --------  -------
packaging  21.3       py3       generic
pip
tabulate   0.8.10     py3       generic

Prétélécharger des paquets

La procédure suivante prétélécharge le paquet tensorboardX sur un nœud de connexion et l'installe sur un nœud de calcul :

  1. Lancez pip download --no-deps tensorboardX pour télécharger le paquet tensorboardX-1.9-py2.py3-none-any.whl (ou semblable) dans le répertoire de travail. La syntaxe pour pip download est la même que celle pour pip install.
  2. Si le nom du fichier ne se termine pas pas none-any, mais par linux_x86_64 ou manylinux*_x86_64, il est possible que le wheel ne fonctionnera pas correctement. Contactez le soutien technique pour que nous compilions le wheel et le rendre disponible sur nos superordinateurs.
  3. À l'installation, utilisez le chemin du fichier pip install tensorboardX-1.9-py2.py3-none-any.whl.

Programmation parallèle avec le module multiprocessing

La programmation parallèle avec Python est un moyen facile d'obtenir des résultats plus rapidement, ce qui est habituellement accompli avec l'utilisation du module multiprocessing. La classe Pool de ce module est particulièrement intéressante car elle permet de contrôler le nombre de processus lancés en parallèle pour exécuter le même calcul avec des données multiples. Supposons que nous voulons calculer le <codet>cube d'une liste de nombres; le code série serait semblable à :

File : cubes_sequential.py

def cube(x):
    return x**3

data = [1, 2, 3, 4, 5, 6]
cubes = [cube(x) for x in data]
print(cubes)


File : cubes_sequential.py

def cube(x):
    return x**3

data = [1, 2, 3, 4, 5, 6]
cubes = list(map(cube,data))
print(cubes)


Avec la classe Pool le code parallèle devient :

File : cubes_parallel.py

import multiprocessing as mp

def cube(x):
    return x**3

pool = mp.Pool(processes=4)
data = [1, 2, 3, 4, 5, 6]
results = [pool.apply_async(cube, args=(x,)) for x in data]
cubes = [p.get() for p in results]
print(cubes)


File : cubes_parallel.py

import multiprocessing as mp

def cube(x):
    return x**3

pool = mp.Pool(processes=4)
data = [1, 2, 3, 4, 5, 6]
cubes = pool.map(cube, data)
print(cubes)


Dans les exemples précédents, nous sommes toutefois limités à quatre processus. Avec une grappe, il est très important d'utiliser les cœurs qui sont alloués à la tâche. Si le nombre de processus exécutés dépasse le nombre de cœurs demandés pour la tâche, les calculs s'effectueront plus lentement et le nœud de calcul sera possiblement surchargé. Si le nombre de processus exécutés est inférieur au nombre de cœurs demandés, certains cœurs resteront inactifs et les ressources ne seront pas utilisées de façon optimale. Votre code devrait faire appel à autant de cœurs que la quantité de ressources demandées à l'ordonnanceur. Par exemple, pour exécuter le même calcul sur des dizaines de données ou plus, il serait sensé d'utiliser tous les cœurs d'un nœud. Dans ce cas, le script de soumission de la tâche aurait l'en-tête suivant :

File : submit.sh

#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=32

python cubes_parallel.py


Le code serait alors :

File : cubes_parallel.py

import multiprocessing as mp
import os

def cube(x):
    return x**3

ncpus = int(os.environ.get('SLURM_CPUS_PER_TASK',default=1))
pool = mp.Pool(processes=ncpus)
data = [1, 2, 3, 4, 5, 6]
results = [pool.apply_async(cube, args=(x,)) for x in data]
cubes = [p.get() for p in results]
print(cubes)


File : cubes_parallel.py

import multiprocessing as mp
import os

def cube(x):
    return x**3

ncpus = int(os.environ.get('SLURM_CPUS_PER_TASK',default=1))
pool = mp.Pool(processes=ncpus)
data = [1, 2, 3, 4, 5, 6]
cubes = pool.map(cube, data)
print(cubes)


Remarquez que dans cet exemple, la fonction cube est en elle-même séquentielle. Il est possible qu'une fonction appelée d'une bibliothèque externe comme numpy soit en elle-même parallèle. Pour distribuer des processus avec la technique précédente, vérifiez d'abord si les fonctions appelées sont en elles-mêmes parallèles et si c'est le cas, vous devrez contrôler le nombre de fils qu'elles utiliseront. Si comme dans l'exemple les fonctions utilisent la totalité des cœurs disponibles (ici 32) et que vous lancez 32 processus, votre code sera plus lent et le nœud sera possiblement surchargé.

Comme le module multiprocessing ne peut utiliser qu'un seul nœud de calcul, le gain en performance est habituellement limité au nombre de cœurs CPU du nœud. Si vous voulez dépasser cette limite et utiliser plusieurs nœuds, considérez mpi4py ou PySpark. Il existe d'autres méthodes de parallélisation, mais elles ne peuvent pas toutes être utilisées avec nos grappes. Souvenez-vous toutefois qu'un code de qualité fournira toujours la meilleure performance; avant de le paralléliser, assurez-vous donc que votre code est optimal. Si vous doutez de l'efficacité de votre code, contactez le soutien technique.

Anaconda

Voir la page sur Anaconda.

Jupyter

Voir la page sur Jupyter Notebook.

Dépannage

Script gelé

Avec le module faulthandler, vous pouvez modifier votre script pour qu'une trace de l'origine du problème soit fournie après une certaine durée; voir l'information sur la commande faulthandler.dump_traceback_later(timeout, repeat=False, file=sys.stderr, exit=False).

Vous pouvez aussi inspecter un processus Python pendant l'exécution d'une tâche sans avoir à le modifier au préalable avec py-spy :

  1. Installez py-spy dans un environnement virtuel de votre répertoire /home.
  2. Connectez-vous à une tâche en cours avec srun --pty --jobid JOBID bash.
  3. Trouvez l'ID du processus du script Python avec htop -u $USER.
  4. Activez l'environnement virtuel où py-spy est installé.
  5. Lancez py-spy top --pid PID pour visionner en direct les endroits où le code utilise beaucoup de temps.
  6. Lancez py-spy dump --pid PID pour obtenir une trace de l'état de votre code.

Message Package 'X' requires a different Python: X.Y.Z not in '>=X.Y'

En installant un paquet, vous pourriez avoir une erreur comme ERROR: Package 'X' requires a different Python: 3.6.10 not in '>=3.7'.

Dans ce cas, le module Python 3.6.10 qui est chargé n'est pas supporté par le paquet. Vous pouvez utiliser une version de Python plus récente, comme le dernier module disponible, ou encore installer une version moins récente du paquet X.

Message Package has requirement X, but you'll have Y which is incompatible

En installant un paquet, vous pourriez avoir une erreur comme ERROR: Package has requirement X, but you'll have Y which is incompatible..

Pour utiliser le nouveau résolveur de dépendances, installez la plus récente version de pip ou une version supérieure à [21.3].

Question.png
(ENV) [name@server ~] pip install --no-index --upgrade pip

Lancez ensuite de nouveau la commande d'installation.

Message No matching distribution found for X

À l'installation d'un paquet, vous pouvez obtenir un message semblable à

Question.png
(ENV) [name@server ~] pip install X
ERROR: Could not find a version that satisfies the requirement X (from versions: none)
ERROR: No matching distribution found for X

pip n'a trouvé aucun paquet à installer qui rencontre les exigences (nom, version ou tags). Assurez-vous que le nom et la version sont corrects. Sachez aussi que les wheels manylinux_x_y sont ignorés.

Vous pouvez aussi vérifier si le paquet est disponible avec la commande avail_wheels ou en consultant la page Wheels disponibles.

Installation de plusieurs paquets

Lorsque possible, il est préférable d'installer plusieurs paquets avec une seule commande.

(ENV) [name@server ~] pip install --upgrade pip
(ENV) [name@server ~] pip install package1 package2 package3 package4

Ainsi, pip peut résoudre plus facilement les problèmes de dépendance.

Mon environnement virtuel fonctionnait hier, mais pas aujourd'hui

Les fréquentes mises à jour des paquets font en sorte qu'un environnement virtuel ne peut souvent pas être reproduit.

Il est possible aussi qu'un environnement virtuel créé dans $SCRATCH soit partiellement détruit lors de la purge automatique de ce système de fichiers, ce qui empêcherait l'environnement virtuel de bien fonctionner.

Pour contrer ceci, gelez les paquets et leurs versions avec

(ENV) [name@server ~] pip install --upgrade pip
(ENV) [name@server ~] pip install --no-index 'package1==X.Y' 'package2==X.Y.Z' 'package3<X.Y' 'package4>X.Y'

et créez ensuite un fichier de requis qui sera utilisé pour installer ces paquets dans votre tâche.

Le wheel X n'est pas pris en charge sur cette plateforme

À l'installation d'un paquet, vous pourriez obtenir une erreur comme ERROR: package-3.8.1-cp311-cp311-manylinux_2_28_x86_64.whl is not a supported wheel on this platform.

Certains paquets peuvent être incompatibles ou non pris en charge par nos systèmes. Deux cas fréquents sont :

  • installation d'un paquet manylinux
  • ou un paquet Python construit pour une autre version de Python (par exemple, installer un paquet construit pour Python 3.11 quand vous avez Python 3.9).

Certains paquets manylinux peuvent se trouver parmi nos wheels Python.

Message AttributeError: module ‘numpy’ has no attribute ‘X’

À l'installation d'un whell, la plus récente version de Numpy est installée si aucune version spécifique n'est demandée. Plusieurs attributs ont été déclarés obsolètes dans Numpy v1.20 et ne sont plus offerts dans v1.24.

Dépendant de l'attribut, une erreur comme AttributeError: module ‘numpy’ has no attribute ‘bool’ pourrait survenir.

Ceci est résolu avec l'installation d'une version précédente de Numpy avec pip install --no-index 'numpy<1.24'.

Message ModuleNotFoundError: No module named 'X'

Il est possible qu'un module Python que vous voulez importer ne soit pas trouvé. Il y a plusieurs explications pour ceci, mais les plus fréquentes sont que

  • le paquet n'est pas installé ou encore il n'est pas visible pour l'interpréteur Python;
  • le nom du module ne correspond pas au nom réel;
  • l'environnement virtuel est défectueux.

Pour contrer ceci, évitez de

  • modifier la variable d'environnement PYTHONPATH;
  • modifier la variable d'environnement PATH;
  • charger un module alors qu'un environnement virtuel est activé; chargez d'abord tous les modules avant d'activer l'environnement virtuel.

Si vous avez ce problème,

  • avec pip list, vérifiez si le paquet est installé;
  • vérifiez encore si le nom que vous entrez correspond exactement au nom du module (majuscules, minuscules, traits de soulignement, etc.);
  • vérifiez si le module est importé au bon niveau quand il provient de son répertoire source.

Dans le doute, recommencez avec un nouvel environnement.

Message ImportError: numpy.core.multiarray failed to import

Ce message peut survenir quand vous tentez d'importer un module Python qui dépend de Numpy.

Ceci se produit quand une version incompatible de Numpy est installée ou utilisée; vous devez installer une version compatible.

Le cas type est la version 2.0 de Numpy qui brise l'ABI. Dans le cas d'un wheel construit avec une version 1.x mais installé avec une version 2.x, vous devez installer une version antérieure avec pip install --no-index 'numpy<2.0'.