Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
formation:insa2018gpu [2018/11/26 18:48]
equemene [CQQCOQP : Comment ? Qui ? Quand ? Combien ? Où ? Qioi ? Pourquoi ?]
formation:insa2018gpu [2018/12/09 10:42] (Version actuelle)
equemene [Implémentation C/OpenCL]
Ligne 1: Ligne 1:
-====== ​Session ​pratique du cours sur les GPU ======+====== ​INSA 2018 : session ​pratique du cours sur les GPU ======
  
-Session ​pratique ​du [[http://​www.cbp.ens-lyon.fr/​emmanuel.quemener/​documents/​CoursINSA_GPU_181112.pdf|cours du 12/​11/​2018]] réalisé par Emmanuel Quémener.+Cette session ​pratique ​accompagne le [[http://​www.cbp.ens-lyon.fr/​emmanuel.quemener/​documents/​CoursINSA_GPU_181112.pdf|cours du 12/​11/​2018]] réalisé par Emmanuel Quémener.
  
 ===== CQQCOQP : Comment ? Qui ? Quand ? Combien ? Où ? Quoi ? Pourquoi ? ===== ===== CQQCOQP : Comment ? Qui ? Quand ? Combien ? Où ? Quoi ? Pourquoi ? =====
  
-  * **Pourquoi ?** Faire un tour d'​horizon des GPUs et appréhender des méthodes d'investigations+  * **Pourquoi ?** Faire un tour d'​horizon des GPUs et appréhender des méthodes d'investigation
   * **Quoi ?** Tester les GPU sur des exemples simples et les modifier   * **Quoi ?** Tester les GPU sur des exemples simples et les modifier
   * **Quand ?** Lundi, les 3 et 10 décembre 2018 de 14h à 18h   * **Quand ?** Lundi, les 3 et 10 décembre 2018 de 14h à 18h
Ligne 15: Ligne 15:
 ===== But de la session ===== ===== But de la session =====
    
-C'est de prendre en main les GPU dans les machines, de comparer les performances avec des CPU classiques ​au travers ​de quelques exemples simples et des codes de production. +C'est de prendre en main les GPU dans les machines, de comparer les performances avec des CPU classiques ​par l'​intermédiaire ​de quelques exemples simples et des codes de production.
  
 ===== Démarrage de la session ===== ===== Démarrage de la session =====
Ligne 22: Ligne 21:
 ==== Prérequis en matériel, logiciel et humain ==== ==== Prérequis en matériel, logiciel et humain ====
  
-De manière à proposer un environnement pleinement fonctionnel,​ le Centre Blaise Pascal fournit ​les matériels, les logiciels et un OS correctement intégré. Les personnes qui veulent réaliser cette session sur leur laptop doivent disposer d'un "​vrai"​ système d'​exploitation de type Unix, équipé de tout l'​environnement adéquat.+De manière à proposer un environnement pleinement fonctionnel,​ le Centre Blaise Pascal fournit ​le matériel, les logiciels et un OS correctement intégré. Les personnes qui veulent réaliser cette session sur leur laptop doivent disposer d'un "​vrai"​ système d'​exploitation de type Unix, équipé de tout l'​environnement adéquat.
  
 === Prérequis pour le matériel === === Prérequis pour le matériel ===
Ligne 32: Ligne 31:
  
   * Une session graphique sur une station de travail, plusieurs terminaux et votre navigateur favori   * Une session graphique sur une station de travail, plusieurs terminaux et votre navigateur favori
-  * Si vous n'​utilisez pas le CBP, un OS GNU/Linux correctement configuré pour le GPU embarqué avec les tous les composants Nvidia, OpenCL, PyOpenCL, PyCUDA.+  * Si vous n'​utilisez pas le CBP, un OS GNU/Linux correctement configuré pour le GPU embarqué avec tous les composants Nvidia, OpenCL, PyOpenCL, PyCUDA.
  
-Pour les personnes voulant exploiter de gros GPU ou GPGPU, ou même un accélérateur Xeon Phi peuvent se connecter sur les machines suivantes :+Les personnes voulant exploiter de gros GPU ou GPGPU, ou même un accélérateur Xeon Phi peuvent se connecter sur les machines suivantes :
   * **gtx1080alpha**,​ **gtx1080beta**,​ **gtx1080gamma**,​ **gtx1080delta** : stations virtuelles disposant de Nvidia GTX 1080   * **gtx1080alpha**,​ **gtx1080beta**,​ **gtx1080gamma**,​ **gtx1080delta** : stations virtuelles disposant de Nvidia GTX 1080
-  * **k80alpha**,​ **k80beta**,​ **k80gamma** : stations virtuelles disposant ​de unun et 2 GPU de Nvidia Tesla K80+  * **k80alpha**,​ **k80beta**,​ **k80gamma** : stations virtuelles disposant ​d'1et 2 GPU de Nvidia Tesla K80
   * **p100alpha**,​ **p100beta** : stations virtuelles disposant d'une Nvidia Tesla P100   * **p100alpha**,​ **p100beta** : stations virtuelles disposant d'une Nvidia Tesla P100
   * **k40m** : station virtuelle disposant d'une Nvidia Tesla K40m   * **k40m** : station virtuelle disposant d'une Nvidia Tesla K40m
Ligne 46: Ligne 45:
  
   * Une allergie à la commande en ligne peut dramatiquement réduire la portée de cette session pratique   * Une allergie à la commande en ligne peut dramatiquement réduire la portée de cette session pratique
-  * Une pratique des scripts shell sera un avantage, ​mais vous avez cette session pour parfaire vos connaissances.+  * Une pratique des scripts shell sera un avantage, ​sinon vous avez cette session pour parfaire vos connaissances.
  
 ===== Investiguer le matériel GPU ===== ===== Investiguer le matériel GPU =====
  
-==== Qui y-a-t-il dans ma machine ? ====+==== Qu'y a-t-il dans ma machine ? ====
  
-Le matériel en Informatique Scientifique est définit ​par [[https://​upload.wikimedia.org/​wikipedia/​commons/​e/​e5/​Von_Neumann_Architecture.svg|l'​architecture de Von Neumann]]:+Le matériel en Informatique Scientifique est défini ​par [[https://​upload.wikimedia.org/​wikipedia/​commons/​e/​e5/​Von_Neumann_Architecture.svg|l'​architecture de Von Neumann]]:
   * CPU (Unité Centrale de Traitement) avec CU (Unité de Contrôle) et ALU (Unité Arithmétique & Logique)   * CPU (Unité Centrale de Traitement) avec CU (Unité de Contrôle) et ALU (Unité Arithmétique & Logique)
   * MU (Unité de Mémoire)   * MU (Unité de Mémoire)
   * Input and Output Devices : Périphériques d'​Entrée et Sortie   * Input and Output Devices : Périphériques d'​Entrée et Sortie
  
-GPU sont généralement considérés comme des périphériques d'​Entrée/​Sortie. Comme la plupart des périphériques installés dans les machines, ils exploitement ​un bus d'​interconnexion [[https://​en.wikipedia.org/​wiki/​Conventional_PCI|PCI]] ou [[https://​en.wikipedia.org/​wiki/​PCI_Express|PCI Express]].+Les GPU sont généralement considérés comme des périphériques d'​Entrée/​Sortie. Comme la plupart des périphériques installés dans les machines, ils exploitent ​un bus d'​interconnexion [[https://​en.wikipedia.org/​wiki/​Conventional_PCI|PCI]] ou [[https://​en.wikipedia.org/​wiki/​PCI_Express|PCI Express]].
  
 Pour récupérer la liste des périphériques PCI, utilisez la commande ''​lspci -nn''​. A l'​intérieur d'une longue liste apparaissent quelques périphériques **VGA** ou **3D**. Ce sont les périphériques GPU ou GPGPU. Pour récupérer la liste des périphériques PCI, utilisez la commande ''​lspci -nn''​. A l'​intérieur d'une longue liste apparaissent quelques périphériques **VGA** ou **3D**. Ce sont les périphériques GPU ou GPGPU.
Ligne 74: Ligne 73:
   * Récupérez le modèle du circuit de GPU, dans son nom étendu.   * Récupérez le modèle du circuit de GPU, dans son nom étendu.
   * Récupérez sur le web les informations suivantes pour chaque GPU :   * Récupérez sur le web les informations suivantes pour chaque GPU :
-    * le nombre d'​unités de calcul (les "cudacores" ou les "streamprocessor")+    * le nombre d'​unités de calcul (les "cuda cores" ou les "stream processors")
     * la fréquence de base des coeurs de calcul     * la fréquence de base des coeurs de calcul
     * la fréquence de la mémoire     * la fréquence de la mémoire
Ligne 81: Ligne 80:
 La totalité des stations de travail contiennent des cartes Nvidia. La totalité des stations de travail contiennent des cartes Nvidia.
  
-Dans les systèmes Posix (Unix dans le langage courant), tout est fichier. Les informations sur les circuits Nvidia et leur découverte par le système d'​exploitation peuvent être récupérés ​avec un ''​grep''​ dans la commande ''​dmesg''​.+Dans les systèmes ​**Posix** (**Unix** dans le langage courant), tout est fichier. Les informations sur les circuits Nvidia et leur découverte par le système d'​exploitation peuvent être récupérées ​avec un ''​grep''​ dans la commande ''​dmesg''​.
  
 Si le démarrage de la machine n'est pas trop ancien, vous disposez des informations comparables aux suivantes : Si le démarrage de la machine n'est pas trop ancien, vous disposez des informations comparables aux suivantes :
Ligne 116: Ligne 115:
 **Exercice #2 : récupérez les informations de votre machine avec ''​dmesg | grep -i nvidia''​** **Exercice #2 : récupérez les informations de votre machine avec ''​dmesg | grep -i nvidia''​**
   * Quelle est la version de pilote chargée par le noyau ?   * Quelle est la version de pilote chargée par le noyau ?
-  * Que représente, ​si cela existe, le  périphérique ''​input:​ HDA NVidia''​ ? +  * Que représente, ​s'​il ​existe, le  périphérique ''​input:​ HDA NVidia''​ ? 
   * Est-ce un périphérique graphique ?   * Est-ce un périphérique graphique ?
 </​note>​ </​note>​
Ligne 133: Ligne 132:
 </​code>​ </​code>​
  
-Nous voyons que 4 modules sont chargés. La dernière colonne (vide pour les deux premières lignes) liste les dépendances entre les modules. Ici ''​nvidia_modeset''​ and ''​nvidia_uvm'' ​dependent ​du module ''​nvidia''​.+Nous voyons que 4 modules sont chargés. La dernière colonne (vide pour les deux premières lignes) liste les dépendances entre les modules. Ici ''​nvidia_modeset''​ and ''​nvidia_uvm'' ​dépendent ​du module ''​nvidia''​.
  
 <note warning> <note warning>
Ligne 190: Ligne 189:
   * sa vitesse de ventilateur   * sa vitesse de ventilateur
   * sa température   * sa température
-  * ses puissances instantanée et maximale +  * ses puissances ​instantanée et maximale 
-  * ses "​occupations"​ mémoire instantanée et maximale+  * ses "​occupations"​ mémoire ​instantanée et maximale
   * les processus les exploitant, leur consommation de mémoire et le GPU associé   * les processus les exploitant, leur consommation de mémoire et le GPU associé
  
Ligne 201: Ligne 200:
 </​note>​ </​note>​
  
-Comme nous l'​avons vu dans l'​introduction sur le GPU, leur programmation peut-être réalisée par différentes voies. La première, pour les périphériques Nvidia, est d'​utiliser l'​environnement CUDA. Le problème sera qu'il est impossible de réexploiter votre programme sur une autre plate-forme (un CPU) ou la comparer avec d'​autres GPU. [[https://​www.khronos.org/​opencl/​|OpenCL]] reste une approche ​beacuoup ​plus agnostique ​!+Comme nous l'​avons vu dans l'​introduction sur le GPU, leur programmation peut-être réalisée par différentes voies. La première, pour les périphériques Nvidia, est d'​utiliser l'​environnement CUDA. Le problème sera qu'il est impossible de réexploiter votre programme sur une autre plate-forme (un CPU) ou la comparer avec d'​autres GPU. [[https://​www.khronos.org/​opencl/​|OpenCL]] reste une approche ​beaucoup ​plus polyvalente ​!
  
-Sur les stations du CBP, la majorité des implémentations de OpenCL ​son disponibles,​ autant sur CBP que sur GPU.+Sur les stations du CBP, la majorité des implémentations de OpenCL ​sont disponibles,​ autant sur CBP que sur GPU.
  
 La commande ''​clinfo''​ récupère des informations liées à tous les périphériques OpenCL disponibles. ​ La commande ''​clinfo''​ récupère des informations liées à tous les périphériques OpenCL disponibles. ​
Ligne 237: Ligne 236:
 </​note>​ </​note>​
  
-L'​appel de la commande ''​clinfo''​ fournit également de nombreuses informations. ​Il n'est malheureusement pas possible ​avec cette commande de ne récupérer les informations que d'un seul périphérique : la commande ''​egrep''​ permet alors de restreindre seulement certains attributs, par exemple ''​Platform Name'',''​Device Name'',''​Max compute'',''​Max clock''​+L'​appel de la commande ''​clinfo''​ fournit également de nombreuses informations. ​Cependant, il est impossible ​avec cette commande de ne récupérer les informations que d'un seul périphérique : la commande ''​egrep''​ permet alors de restreindre seulement certains attributs, par exemple ''​Platform Name'',''​Device Name'',''​Max compute'',''​Max clock''​
  
 Sur la plateforme précédente,​ la commande ''​clinfo | egrep '​(Platform Name|Device Name|Max compute|Max clock)'​ ''​ offre comme sortie:<​code>​ Sur la plateforme précédente,​ la commande ''​clinfo | egrep '​(Platform Name|Device Name|Max compute|Max clock)'​ ''​ offre comme sortie:<​code>​
Ligne 265: Ligne 264:
 </​code>​ </​code>​
  
-Nous distinguons bien les éléments des 5 périphériques OpenCL déjà identifiés au dessus (3 pour les 3 implémentations de CPU, respectivement d'AMD, PortableCL et Intel) et les deux GPU Nvidia (GTX 1080 Ti et Quadro K420). ​+Nous distinguons bien les éléments des 5 périphériques OpenCL déjà identifiés au-dessus (3 pour les 3 implémentations de CPU, respectivement d'AMD, PortableCL et Intel) et les deux GPU Nvidia (GTX 1080 Ti et Quadro K420). ​
  
 Nous constatons par exemple que les nombres d'​unités de traitement sont identiques pour les implémentations CPU (16) mais que leurs fréquences ne le sont pas (1200, 3501, 3500 MHz).  Nous constatons par exemple que les nombres d'​unités de traitement sont identiques pour les implémentations CPU (16) mais que leurs fréquences ne le sont pas (1200, 3501, 3500 MHz). 
  
-Ainsi, l'​implémentation AMD récupère-t-elle la fréquence instantanée ​alors que les deux autres la fréquence maximale. ​+L'​implémentation AMD récupèreellela fréquence instantanée, et les deux autres la fréquence maximale. ​
  
 Pour les GPU, nous constatons que les fréquences sont bien inférieures à celles des GPU (1582 et 875 MHz).  Pour les GPU, nous constatons que les fréquences sont bien inférieures à celles des GPU (1582 et 875 MHz). 
Ligne 281: Ligne 280:
 Ces unités de traitement disposent (autant pour les GPU que les CPU) d'​unités arithmétiques et logiques (//​Arithmetic and Login Unit//) lesquelles sont //​vraiment//​ en charge du traitement des opérations. ​ Ces unités de traitement disposent (autant pour les GPU que les CPU) d'​unités arithmétiques et logiques (//​Arithmetic and Login Unit//) lesquelles sont //​vraiment//​ en charge du traitement des opérations. ​
  
-Ainsi, le nombre d'ALU dans chaque //Compute Unit// varie de 64 à 128 selon les générations de GPU. Ainsi, pour le GPU ci-dessus GTX 1080 Ti, le nombre de //Compute Unit// mentionné est 28, et le nombre d'ALU (appelé également //cudacore// par Nvidia) est de 3584 soit 28*128. Le schéma du constructeur du circuit GP102 suivant est trompeur : en fait, il dispose de 30 unités SM, mais sur un GP102, seuls 28 sont activés.+Ainsi, le nombre d'ALU dans chaque //Compute Unit// varie de 64 à 192 selon les générations de GPU. Ainsi, pour le GPU ci-dessus GTX 1080 Ti, le nombre de //Compute Unit// mentionné est 28, et le nombre d'ALU (appelé également //cuda core// par Nvidia) est de 3584 soit 28*128. Le schéma du constructeur du circuit GP102 suivant est trompeur : en fait, il dispose de 30 unités SM, mais sur un GP102, seuls 28 sont activés.
 {{ :​formation:​gp102-block-diagram.jpg?​direct&​400 |GP102}} {{ :​formation:​gp102-block-diagram.jpg?​direct&​400 |GP102}}
  
 <note warning> <note warning>
-**Exercice #7 : récupérez les informations à l'​aide ​deux deux commandes précédentes utilisant ''​clinfo''​ **+**Exercice #7 : récupérez les informations à l'​aide ​de deux commandes précédentes utilisant ''​clinfo''​ **
  
   * Comparez les informations entre les implémentations CPU. Pourquoi ces différences ?   * Comparez les informations entre les implémentations CPU. Pourquoi ces différences ?
Ligne 291: Ligne 290:
   * Comparez le nombre d'​unités de traitement des GPU avec celles du Web : site [[https://​www.nvidia.com/​page/​products.html#​Architectures|spécifications]] de Nvidia ou Wikipedia   * Comparez le nombre d'​unités de traitement des GPU avec celles du Web : site [[https://​www.nvidia.com/​page/​products.html#​Architectures|spécifications]] de Nvidia ou Wikipedia
   * Comparez les fréquences identifiées avec celles trouvées sur le Web.   * Comparez les fréquences identifiées avec celles trouvées sur le Web.
-  * Retrouvez vous une cohérence entre le nombre de //Compute Units// et le nombre de //cudacores// ?  +  * Retrouvez-vous une cohérence entre le nombre de //Compute Units// et le nombre de //cuda cores// ?  
-  * Combien de //cudacores// contient chaque //Compute Unit// ?+  * Combien de //cuda cores// contient chaque //Compute Unit// ?
 </​note>​ </​note>​
  
Ligne 309: Ligne 308:
 Sur les CPU, Intel propose son implémentation largement optimisée pour ses processeurs au sein des [[https://​software.intel.com/​en-us/​mkl|librairies MKL]] mais les versions Open Sourcen notamment [[http://​www.openblas.net/​|OpenBLAS]],​ n'ont rien à leur envier. D'​autres implémentations sont installées au CBP : l'​[[http://​math-atlas.sourceforge.net/​|ATLAS]] et la [[https://​www.gnu.org/​software/​gsl/​|GSL]]. Sur les CPU, Intel propose son implémentation largement optimisée pour ses processeurs au sein des [[https://​software.intel.com/​en-us/​mkl|librairies MKL]] mais les versions Open Sourcen notamment [[http://​www.openblas.net/​|OpenBLAS]],​ n'ont rien à leur envier. D'​autres implémentations sont installées au CBP : l'​[[http://​math-atlas.sourceforge.net/​|ATLAS]] et la [[https://​www.gnu.org/​software/​gsl/​|GSL]].
  
-Les librairies BLAS sont dans 3 catégories : celles manipulant exclusivement les vecteurs (1 dimension), manipulant les matrices et les vecteurs (1 et 2 dimensions),​ manipulant exclusivement les matrices (2 dimensions).+Les librairies BLAS sont dans 3 catégories : celles manipulant exclusivement les vecteurs (1 dimension), ​celles ​manipulant les matrices et les vecteurs (1 et 2 dimensions), ​enfin celles ​manipulant exclusivement les matrices (2 dimensions).
  
-L'​implémentation de la multiplication de matrice ​dans les libairies BLAS est la ''​xGEMM'',​ avec ''​x''​ à remplacer par ''​S'',​ ''​D'',​ ''​C''​ et ''​Z''​ respectivement pour la **S**imple précision (32 bits), la **D**ouble précision (64 bits), la **C**omplexe & simple ​precision ​et complexe & double ​precision.+L'​implémentation de la multiplication de matrices ​dans les libairies BLAS est la ''​xGEMM'',​ avec ''​x''​ à remplacer par ''​S'',​ ''​D'',​ ''​C''​ et ''​Z''​ respectivement pour la **S**imple précision (32 bits), la **D**ouble précision (64 bits), la **C**omplexe & simple ​précision ​et complexe & double ​précision (**Z**).
  
 L'​objectif de cette première manipulation est de commencer à comparer les GPU et les CPU avec cette opération simple. L'​objectif de cette première manipulation est de commencer à comparer les GPU et les CPU avec cette opération simple.
Ligne 332: Ligne 331:
   * ''​Splutter''​ : un modèle de ''​postillonneur mémoire'',​ très utile pour évaluer les //fonctions atomiques//   * ''​Splutter''​ : un modèle de ''​postillonneur mémoire'',​ très utile pour évaluer les //fonctions atomiques//
  
-De tous ces programmes, seuls ceux présents dans ''​BLAS'',​ ''​NBody''​ et ''​Pi''​ seront exploités dans le cadre de ces travau ​pratiques.+De tous ces programmes, seuls ceux présents dans ''​BLAS'',​ ''​NBody''​ et ''​Pi''​ seront exploités dans le cadre de ces travaux ​pratiques.
  
-==== Exploitations ​des xGEMM  ====+==== Exploitations ​de xGEMM  ====
  
-Le dossier ''​bench4gpu/​xGEMM''​ contient peu de fichiers dont les importants sont : un unique programme source, ''​xGEMM.c'',​ et un fichier de construction,​ ''​Makefile''​. C'est ce fichier qui va ''​construire''​ tous les exécutables d'un coup, à la fois pour les différentes implémentations de BLAS, mais aussi pour les deux précisions **SP** (simple précision sur 32 bits) et **DP** (double précision sur 64 bits).+Le dossier ''​bench4gpu/BLAS/​xGEMM''​ contient peu de fichiers dont les importants sont : un unique programme source, ''​xGEMM.c'',​ et un fichier de construction,​ ''​Makefile''​. C'est ce fichier qui va ''​construire''​ tous les exécutables d'un coup, à la fois pour les différentes implémentations de BLAS, mais aussi pour les deux précisions **SP** (simple précision sur 32 bits) et **DP** (double précision sur 64 bits).
  
 === Le source === === Le source ===
  
-Le programme source ''​xGEMM.c''​ a été conçu pour être agnostique de toute implémentation. Si vous l'​éditez,​ vous réalisez qu'il n'est pas si simple d'​avoir un programme qui s'​exécute indifféremment quelle que soit la librairie. Même si les appels sont comparables (même nombre d'​attributs dans les fonctions), leur nom change de librairie à librairie. Pour n'​avoir qu'un seul source, les directives sont largement exploitées. C'est donc le ''​Makefile''​ qui va permettre de ne compiler que telle ou telle portion du programme source.+Le programme source ''​xGEMM.c''​ a été conçu pour fonctionner avec n'​importe quelle ​implémentation. Si vous l'​éditez,​ vous réalisez qu'il n'est pas si simple d'​avoir un programme qui s'​exécute indifféremment quelle que soit la librairie. Même si les appels sont comparables (même nombre d'​attributs dans les fonctions), leur nom change de librairie à librairie. Pour n'​avoir qu'un seul source, les directives sont largement exploitées. C'est donc le ''​Makefile''​ qui va permettre de ne compiler que telle ou telle portion du programme source.
  
 <note warning> <note warning>
Ligne 355: Ligne 354:
 === Les exécutables === === Les exécutables ===
  
-En simplement lançant la commande ''​make''​ dans le dossier que la compilation s'​opère. Ainsi, tous les exécutables commencent par ''​xGEMM_SP_''​ ou ''​xGEMM_DP_''​. Ils sont ensuite suffixés par l'​implémentation BLAS :+C'​est ​simplement ​en lançant la commande ''​make''​ dans le dossier que la compilation s'​opère. Ainsi, tous les exécutables commencent par ''​xGEMM_SP_''​ ou ''​xGEMM_DP_''​. Ils sont ensuite suffixés par l'​implémentation BLAS :
  
 Nous avons alors 12 exécutables de la forme ''​xGEMM_SP_<​version>''​ ou ''​xGEMM_DP_<​version>''​ :  ​ Nous avons alors 12 exécutables de la forme ''​xGEMM_SP_<​version>''​ ou ''​xGEMM_DP_<​version>''​ :  ​
Ligne 376: Ligne 375:
   * l'ID de la plateforme   * l'ID de la plateforme
   * l'ID du périphérique   * l'ID du périphérique
 +
 En appelant ces deux exécutables avec l'​option ''​-h'',​ le programme détecte les plates-formes et périphériques. En appelant ces deux exécutables avec l'​option ''​-h'',​ le programme détecte les plates-formes et périphériques.
  
Ligne 443: Ligne 443:
 </​code>​ </​code>​
  
-Il faut donc prendre certaines précautions dans ses évaluations ​de performances,​ notamment lorsque les durées d'​exécution sont trop courtes.+Il faut donc prendre certaines précautions dans chaque évaluation ​de performances,​ notamment lorsque les durées d'​exécution sont trop courtes.
  
-Nous avons vu que plusieurs GPU peuvent coexister dans la machine. La question est de savoir lequel est sollicité lors d'un lancement de programme. Par défaut, avec les librairies CUDA, un seul GPU est sollicité, souvent le premier découvert. Pour savoir fait le travail, nous pouvons exploiter la commande ''​nvidia-smi''​ présentée ci-dessus pendant l'​exécution du programme.+Nous avons vu que plusieurs GPU peuvent coexister dans la machine. La question est de savoir lequel est sollicité lors d'un lancement de programme. Par défaut, avec les librairies CUDA, un seul GPU est sollicité, souvent le premier découvert. Pour savoir ​lequel a fait le travail, nous pouvons exploiter la commande ''​nvidia-smi''​ présentée ci-dessus pendant l'​exécution du programme.
  
-Dans le premier terminalqui nous sert à l'​exécution des programmes, nous avons :+Dans le premier terminal qui nous sert à l'​exécution des programmes, nous avons :
 <​code>​ <​code>​
 root@opencluster2:/​local/​tests/​bench4gpu/​BLAS/​xGEMM#​ ./​xGEMM_SP_cublas 1000 100000 ​ root@opencluster2:/​local/​tests/​bench4gpu/​BLAS/​xGEMM#​ ./​xGEMM_SP_cublas 1000 100000 ​
Ligne 487: Ligne 487:
 Nous voyons que le GPU #0, identifié comme la GTX 1080 Ti, exécute 2 tâches : ''/​usr/​lib/​xorg/​Xorg''​ et ''​./​xGEMM_SP_cublas''​. Nous avons également l'​empreinte mémoire de chacun des processus : 36MiB pour le ''​Xorg''​ et 199MiB pour notre programme ''​xGEMM_SP_cublas''​. ​ Nous voyons que le GPU #0, identifié comme la GTX 1080 Ti, exécute 2 tâches : ''/​usr/​lib/​xorg/​Xorg''​ et ''​./​xGEMM_SP_cublas''​. Nous avons également l'​empreinte mémoire de chacun des processus : 36MiB pour le ''​Xorg''​ et 199MiB pour notre programme ''​xGEMM_SP_cublas''​. ​
  
-La question légitime est de se demander, dans le cas d'une machine multi-gpu, comment "​contrôler"​ sur quel GPU est exécuté le programme. Il existe des méthodes assez comparables à celles de OpenCL pour la découverte des périphériques,​ mais elles sont généralement peu exploitées dans les programmes. La technique la plus classique reste l'​utilisation d'une variable d'​environnement laquelle va "​contraindre"​ l'​exploitation d'un (ou plusieurs) GPU(s) : ''​CUDA_VISIBLE_DEVICES''​.+La question légitime est de se demander, dans le cas d'une machine multi-gpu, comment "​contrôler"​ sur quel GPU est exécuté le programme. Il existe des méthodes assez comparables à celles de OpenCL pour la découverte des périphériques,​ mais elles sont généralement peu exploitées dans les programmes. La technique la plus classique reste l'​utilisation d'une variable d'​environnementlaquelle va "​contraindre"​ l'​exploitation d'un (ou plusieurs) GPU(s) : ''​CUDA_VISIBLE_DEVICES''​.
  
 Par exemple, si nous précisons que cette variable vaut ''​1'',​ le périphérique Nvidia ''#​1''​ sera le seul sollicité. Ainsi, en lançant la commande préfixée de cette variable valuée, nous avons : Par exemple, si nous précisons que cette variable vaut ''​1'',​ le périphérique Nvidia ''#​1''​ sera le seul sollicité. Ainsi, en lançant la commande préfixée de cette variable valuée, nous avons :
Ligne 616: Ligne 616:
   * Laquelle des implémentations CPU est la plus performante ?   * Laquelle des implémentations CPU est la plus performante ?
   * Laquelle des implémentations GPU est la plus performante ?   * Laquelle des implémentations GPU est la plus performante ?
-  * Exécutez à nouveau en passant la précision (de SP à DP) sur CPU +  * Exécutez à nouveau ​la performance ​en passant la précision (de SP à DP) sur CPU 
-  * Evaluez ​la performance ​le rapport de performance ​entre SP et DP sur CPU +  * Evaluez le rapport de performances ​entre SP et DP sur CPU 
-  * Exécutez à nouveau en passant la précision (de SP à DP) sur GPU +  * Exécutez à nouveau ​la performance ​en passant la précision (de SP à DP) sur GPU 
-  * Evaluez ​la performance ​le rapport de performance ​entre SP et DP sur GPU+  * Evaluez le rapport de performances ​entre SP et DP sur GPU
   * Présentez les performances entre implémentations en simple précision   * Présentez les performances entre implémentations en simple précision
   * Présentez les performances entre implémentations en double précision ​   * Présentez les performances entre implémentations en double précision ​
Ligne 646: Ligne 646:
  
 Le calcul de Pi par la  [[https://​fr.wikipedia.org/​wiki/​M%C3%A9thode_de_Monte-Carlo|méthode de Monte Carlo]] est exemplaire à plusieurs titres : Le calcul de Pi par la  [[https://​fr.wikipedia.org/​wiki/​M%C3%A9thode_de_Monte-Carlo|méthode de Monte Carlo]] est exemplaire à plusieurs titres :
-  * elle est simple : un générateur de nombre aléatoire, un mécanisme de test et un compteur ​suffise+  * elle est simple : un générateur de nombres aléatoires, un mécanisme de test et un compteur ​suffisent
   * elle est parallélisable : en distribuant le nombre d'​itérations sur les unités de calcul   * elle est parallélisable : en distribuant le nombre d'​itérations sur les unités de calcul
   * elle est //compute bound// : en n'​ayant quasiment aucun accès mémoire (reste dans les registres de calcul)   * elle est //compute bound// : en n'​ayant quasiment aucun accès mémoire (reste dans les registres de calcul)
Ligne 654: Ligne 654:
   * le nombre total d’itérations   * le nombre total d’itérations
   * le régime de Parallélisme (PR) : le ''​découpage''​ du travail vers les unités de traitement ​   * le régime de Parallélisme (PR) : le ''​découpage''​ du travail vers les unités de traitement ​
-  * le type de variable ​: INT32, INT64, FP32, FP64 +  * le type de variables ​: INT32, INT64, FP32, FP64 
   * le type de //Random Number Generator// : MWC, CONG, SHR3, KISS    * le type de //Random Number Generator// : MWC, CONG, SHR3, KISS 
  
Ligne 661: Ligne 661:
 Le type de variable va permettre de juger de l'​efficacité des //Compute Units// en fonction des données qu'​elles manipulent, notamment lorsque nous passons de 32 à 64 bits. Le type de variable va permettre de juger de l'​efficacité des //Compute Units// en fonction des données qu'​elles manipulent, notamment lorsque nous passons de 32 à 64 bits.
  
-Le type de //RNG// a aussi son importance. Les //RNG// utilisés ici sont ceux de [[https://​en.wikipedia.org/​wiki/​George_Marsaglia|Georges Marsaglia]]. Comme tous les //RNG// pseudo-aléatoires,​ ils nécessitent une "​graine"​ laquelle permet une reproductibilité des tirages. Voici leur code source, d'une effroyable efficacité compte-tenu de leur compacité. <​code>​+Le type de //RNG// a aussi son importance. Les //RNG// utilisés ici sont ceux de [[https://​en.wikipedia.org/​wiki/​George_Marsaglia|Georges Marsaglia]]. Comme tous les //RNG// pseudo-aléatoires,​ ils nécessitent une "​graine"​laquelle permet une reproductibilité des tirages. Voici leur code source, d'une effroyable efficacité compte-tenu de leur compacité. <​code>​
 #define znew  ((z=36969*(z&​65535)+(z>>​16))<<​16) #define znew  ((z=36969*(z&​65535)+(z>>​16))<<​16)
 #define wnew  ((w=18000*(w&​65535)+(w>>​16))&​65535) #define wnew  ((w=18000*(w&​65535)+(w>>​16))&​65535)
Ligne 670: Ligne 670:
 </​code>​ </​code>​
  
-Comme nous divisons un nombre d'​itérations entier par un régime de parallélisme,​ nous approximons dans le code le nombre d'​itérations de chaque calcul ​élémentaires ​à l'​entier supérieur. Lorsque le nombre d'​itérations dépasse le milliard, le nombre d'​itérations supplémentaires ne dépasse pas 7%.+Comme nous divisons un nombre d'​itérations entier par un régime de parallélisme,​ nous approximons dans le code le nombre d'​itérations de chaque calcul ​élémentaire ​à l'​entier supérieur. Lorsque le nombre d'​itérations dépasse le milliard, le nombre d'​itérations supplémentaires ne dépasse pas 7%.
  
 Comme résultat, nous avons deux observables simples : Comme résultat, nous avons deux observables simples :
Ligne 679: Ligne 679:
 Pour évaluer une performance,​ il est toujours intéressant de choisir une métrique maximaliste : nous définissons le **itops** soit le //ITerative Operations Per Second// comme le rapport entre ce nombre total d'​itérations et le temps écoulé. Pour évaluer une performance,​ il est toujours intéressant de choisir une métrique maximaliste : nous définissons le **itops** soit le //ITerative Operations Per Second// comme le rapport entre ce nombre total d'​itérations et le temps écoulé.
  
-==== Les programmes utilisés : OpenMP, ​OpenCL, CUDA ====+==== Les programmes utilisés : OpenCL, CUDA ====
  
 Le dossier ''​bench4gpu''​ contient de nombreuses implémentations de ce calcul élémentaire. Nous nous focaliserons sur 2 d'​entre eux : Le dossier ''​bench4gpu''​ contient de nombreuses implémentations de ce calcul élémentaire. Nous nous focaliserons sur 2 d'​entre eux :
Ligne 690: Ligne 690:
  
 <note warning> <note warning>
-**Exercice # : exploration du code OpenCL**+**Exercice #11 : exploration du code OpenCL**
  
   * Repérez dans le programme source le **noyau** OpenCL réalisant le calcul   * Repérez dans le programme source le **noyau** OpenCL réalisant le calcul
Ligne 699: Ligne 699:
 Le code se compile très simplement uniquement en appliquant la commande ''​gcc -o PiOpenCL PiOpenCL.c -lOpenCL''​. L'​exécutable ''​PiOpenCL''​ est prêt à être utilisé. Le code se compile très simplement uniquement en appliquant la commande ''​gcc -o PiOpenCL PiOpenCL.c -lOpenCL''​. L'​exécutable ''​PiOpenCL''​ est prêt à être utilisé.
  
-Son exécution sans paramètre ne fait qu'une découverte des périphériques OpenCL disponibles et présente la documentation. Par exemple :<​code>​+Son exécution sans paramètre ne fait qu'​une ​"découverte" ​des périphériques OpenCL disponibles et présente la documentation. Par exemple :<​code>​
  
 Performs a Pi estimation by Dart Dash: Performs a Pi estimation by Dart Dash:
Ligne 769: Ligne 769:
   * #1 l'​identifiant de la plateforme   * #1 l'​identifiant de la plateforme
   * #2 l'​identifiant du périphérique pour cette plateforme   * #2 l'​identifiant du périphérique pour cette plateforme
-  * #3 le numbre ​minimum d'​itérations (par défaut 1000000)+  * #3 le nombre ​minimum d'​itérations (par défaut 1000000)
   * #4 le régime de parallélisme PR (par défault 1024)   * #4 le régime de parallélisme PR (par défault 1024)
   * #5 le nombre de boucles (par défault 1) : bien utile pour évaluer la reproductibilité temporelle   * #5 le nombre de boucles (par défault 1) : bien utile pour évaluer la reproductibilité temporelle
Ligne 777: Ligne 777:
  
 <note warning> <note warning>
-**Exercice # : compilation et première exécution**+**Exercice #12 : compilation et première exécution**
  
   * Compilez le programme avec la ligne de compilation précisée ci-dessus   * Compilez le programme avec la ligne de compilation précisée ci-dessus
Ligne 784: Ligne 784:
 </​note>​ </​note>​
  
-Avec ce premier outil, il est possible de juger de la différence fondamentale de performances entre GPU et CPU en fonction du régime de parallélisme.+Avec ce premier outil, il est possible de juger de la différence fondamentale de performances entre GPU et CPUen fonction du régime de parallélisme.
  
 Par exemple, sur les périphériques ci-dessus : Par exemple, sur les périphériques ci-dessus :
Ligne 797: Ligne 797:
 {{:​formation:​opencluster2_qpu1.png?​direct&​400|}} {{:​formation:​opencluster2_qpu1.png?​direct&​400|}}
  
-Il est assez intéressant que les implémentations ​GPU offrent quasiment la même performance. Par contre les GPU offrent une performance bien moindre (6x moins pour la GTX 1080 Ti et presque 30x moins pour la Quadro K420).+Il est assez intéressant que les implémentations ​CPU offrent quasiment la même performance. Par contre les GPU offrent une performance bien moindre (6x moins pour la GTX 1080 Ti et presque 30x moins pour la Quadro K420).
  
 Il est aussi intéressant qu'​étrange que le nombre de "​coups"​ à l'​intérieur du quadrant d'​exploration ne soit pas le même pour toutes les implémentations. C'est un artéfact lié à la multiplication du //RNG// par la constante pour le placer entre 0 et 1.  Il est aussi intéressant qu'​étrange que le nombre de "​coups"​ à l'​intérieur du quadrant d'​exploration ne soit pas le même pour toutes les implémentations. C'est un artéfact lié à la multiplication du //RNG// par la constante pour le placer entre 0 et 1. 
  
 <note warning> <note warning>
-**Exercice # : exécution sur tous les périphériques pour un PR=1**+**Exercice #13 : exécution sur tous les périphériques pour un PR=1**
  
   * Exécutez le programme sur tous (GPU & CPU) avec un nombre d'​itérations de 1 milliard   * Exécutez le programme sur tous (GPU & CPU) avec un nombre d'​itérations de 1 milliard
Ligne 821: Ligne 821:
 {{:​formation:​opencluster2_qpu1024.png?​direct&​400|}} {{:​formation:​opencluster2_qpu1024.png?​direct&​400|}}
  
-Cette seconde expérience montre de manière assez spectaculaire que les GPU ne montrent ​leur puissance "​que"​ pour des régimes de parallélisme élevé. Notons aussi que les implémentations sur CPU ont des performances très très disparates.+Cette seconde expérience montre de manière assez spectaculaire que les GPU ne dévoilent ​leur puissance "​que"​ pour des régimes de parallélisme élevé. Notons aussi que les implémentations sur CPU ont des performances très très disparates.
  
 <note warning> <note warning>
-**Exercice # : exécution sur tous les périphériques pour un PR=1024**+**Exercice #14 : exécution sur tous les périphériques pour un PR=1024**
  
   * Exécutez le programme sur tous (GPU & CPU) avec un nombre d'​itérations de 10 milliards   * Exécutez le programme sur tous (GPU & CPU) avec un nombre d'​itérations de 10 milliards
-  * Repérez les éléments de **durée**, **itops** et le **inside**+  * Repérez les éléments de **durée**, **itops** et **inside**
   * Tracez l'​histogramme correspondant aux performances sur le modèle ci-dessus   * Tracez l'​histogramme correspondant aux performances sur le modèle ci-dessus
   * Quel ratio existe entre le ou les GPU et les processeurs ?   * Quel ratio existe entre le ou les GPU et les processeurs ?
Ligne 834: Ligne 834:
 Dans l'​expérience précédente,​ nous avons exploité un régime de parallélisme sur les processeurs très supérieur au nombre de //Compute Units//, lesquelles sont identifiées comme les coeurs. Il y avait 8 coeurs physiques et nous avons "​chargé"​ chaque coeur à 256 fois leur charge. Que se passe-t-il si nous effectuons la même chose avec les GPU ? Dans l'​expérience précédente,​ nous avons exploité un régime de parallélisme sur les processeurs très supérieur au nombre de //Compute Units//, lesquelles sont identifiées comme les coeurs. Il y avait 8 coeurs physiques et nous avons "​chargé"​ chaque coeur à 256 fois leur charge. Que se passe-t-il si nous effectuons la même chose avec les GPU ?
  
-Dans notre exemple, la GTX 1080 Ti dispose de 3584 //cudacores//. La Quadro K420 de 192 //cudacores//. Explorons ces périphériques avec des  **PR** de 256x ces valeurs (nous sommes obligés de porter les itérations à 1000000000000) :+Dans notre exemple, la GTX 1080 Ti dispose de 3584 //cuda cores//. La Quadro K420 de 192 //cuda cores//. Explorons ces périphériques avec des  **PR** de 256x ces valeurs (nous sommes obligés de porter les itérations à 1000 milliards) :
  
 ^  Périphérique ​ ^  Durée ​ ^  Itops  ^  Inside ​ ^ ^  Périphérique ​ ^  Durée ​ ^  Itops  ^  Inside ​ ^
Ligne 845: Ligne 845:
  
 <note warning> <note warning>
-**Exercice # : exécution sur tous les périphériques pour un PR optimal**+**Exercice #15 : exécution sur tous les périphériques pour un PR optimal**
  
-  * Reprenez les spécifications des GPU et isolez le nombre de //cudacores// +  * Reprenez les spécifications des GPU et isolez le nombre de //cuda cores// 
-  * Exécutez le programme sur les GPU avec un nombre d'​itérations de 100 milliards et un PR de 256x le nombre de //cudacores// +  * Exécutez le programme sur les GPU avec un nombre d'​itérations de 100 milliards et un PR de 256x le nombre de //cuda cores// 
-  * Repérez les éléments de **durée**, **itops** et le **inside**+  * Repérez les éléments de **durée**, **itops** et **inside**
   * Tracez l'​histogramme correspondant aux performances sur le modèle ci-dessus   * Tracez l'​histogramme correspondant aux performances sur le modèle ci-dessus
   * Quel ratio de performance existe entre le GPU le plus puissant et la meilleure implémentation des CPU ?   * Quel ratio de performance existe entre le GPU le plus puissant et la meilleure implémentation des CPU ?
Ligne 869: Ligne 869:
 Nous avons présenté dans le cours qu'un mauvais choix de régime de parallélisme pouvait largement influencer la performance. Nous avons présenté dans le cours qu'un mauvais choix de régime de parallélisme pouvait largement influencer la performance.
  
-Par exemple, regardons pour la meilleure implémentation de CPU et pour le GPU le plus puissant, quelle influence ​cela a le choix du régime de parallélisme autour du régime de parallélisme optimal.+Par exemple, regardons pour la meilleure implémentation de CPU et pour le GPU le plus puissant, quelle influence a le choix du régime de parallélisme autour du régime de parallélisme optimal.
  
 <note warning> <note warning>
-**Exercice # : exécution sur tous les périphériques pour un PR optimal en double précision**+**Exercice #16 : exécution sur tous les périphériques pour un PR optimal en double précision**
  
   * Reprenez les expériences ci-dessus en précisant un calcul en double précision   * Reprenez les expériences ci-dessus en précisant un calcul en double précision
Ligne 879: Ligne 879:
 </​note>​ </​note>​
  
-==== Implémentation Python/​OpenCL/​CUDA ====+==== Implémentation Python/​OpenCL ​Python/CUDA ====
  
-Dans l'​exemple précédent,​ nous avons exploité un programme en C "​pur"​. Nous avons vu comment s'intégrer ​la portion de code (le noyau ou le //kernel//) qui était ​exécuté, soit par les GPU, soit par différentes implémentations pour CPU de OpenCL. Nous avons aussi pu "​juger"​ du côté assez "​compliqué"​ de découvertes des périphériques et des mécanismes d'​entrée/​sortie.+Dans l'​exemple précédent,​ nous avons exploité un programme en C "​pur"​. Nous avons vu comment s'intégrait ​la portion de code (le noyau ou le //kernel//) qui était ​exécutée, soit par les GPU, soit par différentes implémentations pour CPU de OpenCL. Nous avons aussi pu "​juger"​ du côté assez "​compliqué"​ de découvertes des périphériques et des mécanismes d'​entrée/​sortie.
  
 Avec le programme ''​PiXPU.py'',​ nous allons pouvoir exploiter les périphériques de calcul plus simplement, et bénéficier de toutes les facilités d'un langage évolué. Avec le programme ''​PiXPU.py'',​ nous allons pouvoir exploiter les périphériques de calcul plus simplement, et bénéficier de toutes les facilités d'un langage évolué.
Ligne 956: Ligne 956:
 </​code>​ </​code>​
  
-Deux fichiers de sortie sont crées ​et reprennent dans leur titre les données ​d'​entrée :+Deux fichiers de sortie sont créés ​et reprennent dans leur titre les paramètres ​d'​entrée :
   * ''​Pi_FP32_MWC_xPU_OpenCL_1_1_1_1_10000000_Device0_InMetro_opencluster2''​   * ''​Pi_FP32_MWC_xPU_OpenCL_1_1_1_1_10000000_Device0_InMetro_opencluster2''​
   * ''​Pi_FP32_MWC_xPU_OpenCL_1_1_1_1_10000000_Device0_InMetro_opencluster2.npz''​   * ''​Pi_FP32_MWC_xPU_OpenCL_1_1_1_1_10000000_Device0_InMetro_opencluster2.npz''​
Ligne 965: Ligne 965:
  
 <note warning> <note warning>
-Exercice # : récupération des éléments dans le code source+Exercice #17 : récupération des éléments dans le code source
   * Editez le code source avec l'​outil ''​gedit''​   * Editez le code source avec l'​outil ''​gedit''​
   * Identifiez l'​appel de la procédure principale OpenCL : ligne   * Identifiez l'​appel de la procédure principale OpenCL : ligne
Ligne 982: Ligne 982:
 === Exploitation du programme === === Exploitation du programme ===
  
-Ainsi, si nous voulons étudier la scalabilité du CPU en //Work items// de 1 à 16x le nombre de coeurs (ici 8 physiques) en exploitant l'​implémentation AMD de OpenCL, nous appelons la commande : <​code>​python PiXPU.py -d 0 -b 1 -e $((8*16)) -r 10 -i 1000000000'' ​</​code>​+Ainsi, si nous voulons étudier la scalabilité du CPU en //Work items// de 1 à 16x le nombre de coeurs (ici 8 physiques) en exploitant l'​implémentation AMD de OpenCL, nous appelons la commande : <​code>​python PiXPU.py -d 0 -b 1 -e $((8*16)) -r 10 -i 1000000000 </​code>​
  
 Dans notre cas, nous avons les deux fichiers suivants à exploiter :  Dans notre cas, nous avons les deux fichiers suivants à exploiter : 
Ligne 988: Ligne 988:
   * ''​Pi_FP32_MWC_xPU_OpenCL_1_128_1_1_1000000000_Device0_InMetro_opencluster2''​   * ''​Pi_FP32_MWC_xPU_OpenCL_1_128_1_1_1000000000_Device0_InMetro_opencluster2''​
  
-Nous ppuvons ​ensuite exploiter l'​outil simple ''​gnuplot''​ pour afficher nos résultats :+Nous pouvons ​ensuite exploiter l'​outil simple ''​gnuplot''​ pour afficher nos résultats :
 <​code>​ <​code>​
 gnuplot gnuplot
Ligne 1003: Ligne 1003:
  
 <note warning> <note warning>
-Exercice # : étude de la scalabilité d'une implémentation CPU+Exercice #18 : étude de la scalabilité d'une implémentation CPU
   * Identifiez avec ''​python PiXPU.py -h''​ un périphérique CPU   * Identifiez avec ''​python PiXPU.py -h''​ un périphérique CPU
   * Exécutez le d'un PR=1 à un PR égal à 8x le nombre de coeurs physiques   * Exécutez le d'un PR=1 à un PR égal à 8x le nombre de coeurs physiques
Ligne 1009: Ligne 1009:
 </​note>​ </​note>​
  
-Nous pouvons également "​explorer"​ la scalabilité des GPU forts de notre expérience de ''​PiOpenCL''​. Par exemple, du nombre de //cudacores// à ce nombre multiplié par 16, par pas de 128. La commande appelée est la suivante :<​code>​+Nous pouvons également "​explorer"​ la scalabilité des GPU forts de notre expérience de ''​PiOpenCL''​. Par exemple, du nombre de //cuda cores// à ce nombre multiplié par 16, par pas de 128. La commande appelée est la suivante :<​code>​
 python PiXPU.py -d 2 -b 3584 -e $((3584*8)) -s 128 -r 3 -i 100000000000 python PiXPU.py -d 2 -b 3584 -e $((3584*8)) -s 128 -r 3 -i 100000000000
 </​code>​ </​code>​
Ligne 1016: Ligne 1016:
 {{ :​formation:​gtx1080ti_opencluster2_insa.png?​400 |}} {{ :​formation:​gtx1080ti_opencluster2_insa.png?​400 |}}
  
-Nous pouvons constater que la scalabilité est très peu continue, encore moins que pour la scalabilité étudiée des CPU. Nous constatons également ​ces pseudo-périodes ​se chevauchant. Le PR optimal était autour de 4x le nombre de //cudacores// et offrait une performance de **268 Gitops**.+Nous pouvons constater que la scalabilité est très peu continue, encore moins que pour la scalabilité étudiée des CPU. Nous constatons également ​que des pseudo-lignes ​se chevauchent. Le PR optimal était autour de 4x le nombre de //cuda cores// et offrait une performance de **268 Gitops**.
  
 <note warning> <note warning>
-Exercice # : étude de la scalabilité d'un GPU+Exercice #19 : étude de la scalabilité d'un GPU
   * Identifiez avec ''​python PiXPU.py -h''​ un périphérique GPU   * Identifiez avec ''​python PiXPU.py -h''​ un périphérique GPU
-  * Exécutez le d'un PR=<​NbCudaCores>​ à un PR égal à 8x<​NbCudaCores>​ par pas de 128 en OpenCL+  * Exécutez-le d'un PR=<​NbCudaCores>​ à un PR égal à 8x<​NbCudaCores>​ par pas de 128 en OpenCL
   * Tracez les résultats avec GNUplot   * Tracez les résultats avec GNUplot
   * Identifiez pour quel PR la performance est maximale   * Identifiez pour quel PR la performance est maximale
 </​note>​ </​note>​
  
-Comme nous avons également la même implémentation en CUDA, lançons l'​exploration avec CUDA pour le PR optimal, ici identifié à 4x le nombre de //cudacores// :<​code>​python PiXPU.py -g CUDA -d 0 -b $((3584*4)) -e $((3584*4)) -r 3 -i 10000000000</​code>​+Comme nous avons également la même implémentation en CUDA, lançons l'​exploration avec CUDA pour le PR optimal, ici identifié à 4x le nombre de //cuda cores// :<​code>​python PiXPU.py -g CUDA -d 0 -b $((3584*4)) -e $((3584*4)) -r 3 -i 10000000000</​code>​
  
 Comme résultat de cette implémentation CUDA, nous n'​obtenons pas **268 Gitops**, mais seulement **6 Gitops** ! Comme résultat de cette implémentation CUDA, nous n'​obtenons pas **268 Gitops**, mais seulement **6 Gitops** !
Ligne 1032: Ligne 1032:
 La seule manière de retrouver une performance comparable en CUDA est de solliciter le second étage de parallélisme des GPU, les //​Threads//​. Avec la commande suivante, avec 1024 Threads, nous plafonnons à **198 Gitops** :<​code>​python PiXPU.py -g CUDA -d 0 -b $((3584*4)) -e $((3584*4)) -f 1024 -l 1024 -r 3 -i 1000000000000</​code>​ La seule manière de retrouver une performance comparable en CUDA est de solliciter le second étage de parallélisme des GPU, les //​Threads//​. Avec la commande suivante, avec 1024 Threads, nous plafonnons à **198 Gitops** :<​code>​python PiXPU.py -g CUDA -d 0 -b $((3584*4)) -e $((3584*4)) -f 1024 -l 1024 -r 3 -i 1000000000000</​code>​
  
-Et ce n'est pas tout ! La distribtion ​Debian utilisée intègre par défaut un CUDA version 8. Pour l'​intégration d'​applications de //Deep Learning//, nous avons été obligé d'​intégrer un CUDA version 9. Nous pouvons charger l'​environnement pour exploiter cette version avec la commande :<​code>​module load cuda/​9.0</​code>​+Et ce n'est pas tout ! La distribution ​Debian utilisée intègre par défaut un CUDA version 8. Pour l'​intégration d'​applications de //Deep Learning//, nous avons été obligé d'​intégrer un CUDA version 9. Nous pouvons charger l'​environnement pour exploiter cette version avec la commande :<​code>​module load cuda/​9.0</​code>​
  
 En relançant le calcul précédent,​ nous parvenons à **271 Gitops** soit plus que l'​implémentation OpenCL. En relançant le calcul précédent,​ nous parvenons à **271 Gitops** soit plus que l'​implémentation OpenCL.
  
-<note warning> +<note warning>​Exercice #20 : étude de l'​implémentation CUDA autour du PR optimal
-Exercice # : étude de l'​implémentation CUDA autour du PR optimal+
   * Identifiez avec ''​python PiXPU.py -h''​ le périphérique GPU déjà utilisé en CUDA   * Identifiez avec ''​python PiXPU.py -h''​ le périphérique GPU déjà utilisé en CUDA
   * Exécutez le avec le PR optimal des //Blocks// en CUDA   * Exécutez le avec le PR optimal des //Blocks// en CUDA
Ligne 1053: Ligne 1052:
 {{ :​formation:​gtx1080ti_aroundepu_opencluster2_insa.png?​400 |}} {{ :​formation:​gtx1080ti_aroundepu_opencluster2_insa.png?​400 |}}
  
-Alors que l'​optimum de performance est atteint autour d'un PR de 14336 avec **258 Gitops**, nous n'obtenous ​un Itops que de **8.5 Gitops** (soit 30x moins) sur 5 valeurs particulières : 14321, 14323, 14327, 14341, 14347. Le point commun entre ces valeurs de PR est à rechercher sur le site [[http://​www.math.com/​students/​calculators/​source/​prime-number.htm|de mathématiques]]+Alors que l'​optimum de performance est atteint autour d'un PR de 14336 avec **258 Gitops**, nous n'obtenons ​un Itops que de **8.5 Gitops** (soit 30x moins) sur 5 valeurs particulières : 14321, 14323, 14327, 14341, 14347. Le point commun entre ces valeurs de PR est à rechercher sur le site [[http://​www.math.com/​students/​calculators/​source/​prime-number.htm|de mathématiques]]
  
 <note warning> <note warning>
-Exercice # : étude de valeurs particulières de PR +Exercice #21 : étude de valeurs particulières de PR 
-  * Exécutez ''​PiXPU.py''​ autour du PR égal à 4x le nombre de //cudacores// (16 avant et 16 après)+  * Exécutez ''​PiXPU.py''​ autour du PR égal à 4x le nombre de //cuda cores// (16 avant et 16 après)
   * Tracez les résultats avec GNUplot   * Tracez les résultats avec GNUplot
   * Quels sont les PR avec les performances les plus faibles ?   * Quels sont les PR avec les performances les plus faibles ?
Ligne 1066: Ligne 1065:
 Le code de test **Pi Monte Carlo** avait pour avantage de ne solliciter que très peu la mémoire. La seule mémoire sollicitée sur les périphériques se résumait au nombre de tirages dans le quadrant de cercle. De plus, l'​opération de parallélisation divisait un nombre total d'​itérations en un nombre équivalent pour chaque //work item//, chaque //block// ou chaque //thread//. Chaque calcul était indépendant des autres : nous avions non seulement un **code ALU** (ne sollicitant que les unités de traitement) mais aussi un **code gros grain** (indépendance des calculs). Le code de test **Pi Monte Carlo** avait pour avantage de ne solliciter que très peu la mémoire. La seule mémoire sollicitée sur les périphériques se résumait au nombre de tirages dans le quadrant de cercle. De plus, l'​opération de parallélisation divisait un nombre total d'​itérations en un nombre équivalent pour chaque //work item//, chaque //block// ou chaque //thread//. Chaque calcul était indépendant des autres : nous avions non seulement un **code ALU** (ne sollicitant que les unités de traitement) mais aussi un **code gros grain** (indépendance des calculs).
  
-Dans le code ''​NBody.py'',​ le principe est de déterminer dans un modèle newtonien la position et la vitesse de chaque particule en intéraction avec toutes les autres. A chaque itération, chaque position et chaque vitesse de chaque particule ​va être modifiée ​par la proximité de toutes les autres : nous disposons d'un **code grain fin**. De plus, la détermination de la vitesse et la position de chaque particule à chaque instant nécessite un accès à la position de chacune des autres : un accès permanent à la mémoire est donc indispensable.+Dans le code ''​NBody.py'',​ le principe est de déterminer dans un modèle newtonien la position et la vitesse de chaque particule en intéraction avec toutes les autres. A chaque itération, chaque position et chaque vitesse de chaque particule ​vont être modifiées ​par la proximité de toutes les autres : nous disposons d'un **code grain fin**. De plus, la détermination de la vitesse et la position de chaque particule à chaque instant nécessite un accès à la position de chacune des autres : un accès permanent à la mémoire est donc indispensable.
  
 Le programme ''​NBody.py''​ n'est disponible qu'en OpenCL. Son invocation avec l'​option ''​-h''​ offre la sortie suivante : Le programme ''​NBody.py''​ n'est disponible qu'en OpenCL. Son invocation avec l'​option ''​-h''​ offre la sortie suivante :
Ligne 1170: Ligne 1169:
  
 <note warning> <note warning>
-Exercice # : étude du source de ''​NBody.py''​+Exercice #22 : étude du source de ''​NBody.py''​
   * Editez le programme avec gedit   * Editez le programme avec gedit
   * Identifiez le bloc de noyaux OpenCL : lignes   * Identifiez le bloc de noyaux OpenCL : lignes
Ligne 1189: Ligne 1188:
 {{:​formation:​nbody_opencluster2.png?​400|}} {{:​formation:​nbody_opencluster2.png?​400|}}
  
-La figure ci-dessus illustre l'​écrasante ​performances ​de la GTX 1080 Ti en comparaison de toutes les autres implémentations : plus d'un facteur 22 en simple précision et presque un facteur 2 en double précision pour la meilleure des implémentations CPU.+La figure ci-dessus illustre l'​écrasante ​performance ​de la GTX 1080 Ti en comparaison de toutes les autres implémentations : plus d'un facteur 22 en simple précision et presque un facteur 2 en double précision pour la meilleure des implémentations CPU.
  
 {{:​formation:​nbody_log_opencluster2.png?​400|}} {{:​formation:​nbody_log_opencluster2.png?​400|}}
Ligne 1196: Ligne 1195:
  
 <note warning> <note warning>
-Exercice # : lancement de ''​NBody.py''​ pour 32768 particules+Exercice #23 : lancement de ''​NBody.py''​ pour 32768 particules
   * Exécutez le programme pour tous les périphériques détectés   * Exécutez le programme pour tous les périphériques détectés
   * Ajoutez l'​option pour un calcul en 64 bits et réexécutez   * Ajoutez l'​option pour un calcul en 64 bits et réexécutez
Ligne 1221: Ligne 1220:
 {{ :​formation:​nbody_007.png?​400 |}} {{ :​formation:​nbody_007.png?​400 |}}
  
-<note warning> +<note warning>​Exercice #24 : lancement de ''​NBody.py''​ en mode ''​-g''​
-Exercice # : lancement de ''​NBody.py''​ en mode ''​-g''​+
   * Exécutez le programme pour le meilleur des CPU sur 8192 particules   * Exécutez le programme pour le meilleur des CPU sur 8192 particules
   * Appuyez sur ''​s''​ pour passer des positions aux vitesses   * Appuyez sur ''​s''​ pour passer des positions aux vitesses
Ligne 1240: Ligne 1238:
 ==== Introduction à l'​intégration de codes ==== ==== Introduction à l'​intégration de codes ====
  
-Les "codes métiers"​ sont des programmes "de production scientifique"​. Il n'est pas question, pour un utilisateur,​ de modifier le source du programme pour ses activités, notamment de recherche. Le programme est exploité "tel quel" et seul les paramètres d'​entrées changent.+Les "codes métiers"​ sont des programmes "de production scientifique"​. Il n'est pas question, pour un utilisateur,​ de modifier le source du programme pour ses activités, notamment de recherche. Le programme est exploité "tel quel" et seuls les paramètres d'​entrées changent.
  
-Par contre l'​**intégration** d'un code dans un **environnement informatique** (tuple matériel, système d'​exploitation,​ librairies, logiciel, usage) peut s'​avérer compliqué, voire complexe. Cette activité d'​intégration forme une grande partie de l'​activité des personnels des infrastructures de calcul scientifique.+Par contre l'​**intégration** d'un code dans un **environnement informatique** (//tuple// matériel, système d'​exploitation,​ librairies, logiciel, usage) peut s'​avérer compliqué, voire complexe. Cette activité d'​intégration forme une grande partie de l'​activité des personnels des infrastructures de calcul scientifique.
  
 ==== Intégration et exploitation du code Gromacs ==== ==== Intégration et exploitation du code Gromacs ====
  
-Nous allons, dans l'​exercice suivant, ​tenter de reproduire une [[https://​www.nvidia.com/​en-us/​data-center/​gpu-accelerated-applications/​gromacs/​|expérience de Nvidia]] vantant l'​efficacité des GPGPU pour le logiciel de [[https://​fr.wikipedia.org/​wiki/​Dynamique_mol%C3%A9culaire|dynamique moléculaire]] [[http://​www.gromacs.org/​|Gromacs]].+Nous allons tenter de reproduire une [[https://​www.nvidia.com/​en-us/​data-center/​gpu-accelerated-applications/​gromacs/​|expérience de Nvidia]] vantant l'​efficacité des GPGPU pour le logiciel de [[https://​fr.wikipedia.org/​wiki/​Dynamique_mol%C3%A9culaire|dynamique moléculaire]] [[http://​www.gromacs.org/​|Gromacs]].
  
-<note warning>​Exercice # : appliquez la "​recette"​ de Nvidia+<note warning>​Exercice #25 : appliquez la "​recette"​ de Nvidia
   * La documentation offre ceci :   * La documentation offre ceci :
     - récupérez le source     - récupérez le source
Ligne 1261: Ligne 1259:
 </​note>​ </​note>​
  
-En cas de difficultés,​ appliquez la [[formation:​insa2018gpu:​insa2018gromacs4stretch|recette de Gromacs pour Debian Stretch]].+En cas de difficultés,​ appliquez la [[formation:​insa2018gpu:​insa2018gromacs4stretch|recette de Gromacs pour Debian Stretch]] ​;-)
  
-<note warning>​Exécutez l'​exemple ''​1536'' ​+<note warning>Exercice #26 : Exécutez l'​exemple ''​1536'' ​
   * Quel ''​Elapsed Time''​ avez-vous pour l'​exécution sur GPU (et CPU) ?   * Quel ''​Elapsed Time''​ avez-vous pour l'​exécution sur GPU (et CPU) ?
   * Quel ''​Elapsed Time''​ avez-vous pour l'​exécution uniquement sur CPU ?   * Quel ''​Elapsed Time''​ avez-vous pour l'​exécution uniquement sur CPU ?
   * Quel ratio de performances existe entre les deux exécutions ?   * Quel ratio de performances existe entre les deux exécutions ?
 </​note>​ </​note>​
 +
 ==== Intégration et exploitation du code PKDGRAV3 ==== ==== Intégration et exploitation du code PKDGRAV3 ====
  
 +Le code PKDGRAV3 est un logiciel de simulation hydrodynamique à la large couverture médiatique en juin 2017. Présenté comme exploitant massivement les GPU, il est disponible sur [[https://​bitbucket.org/​dpotter/​pkdgrav3/​|bitbucket]].
 +
 +Le code source est accessible par ''​git''​ à l'​adresse : https://​bitbucket.org/​dpotter/​pkdgrav3.git
 +
 +<note warning>​Exercice #27 : Récupérez et compilez le code suivant la documentation fournie
 +  * La documentation offre ceci :
 +    - récupérez le source
 +    - étendez l'​archive
 +    - créez un dossier pour la construction
 +    - passez dans ce dossier
 +    - préparez la compilation
 +    - compilez le code
 +  * A quelle étape est-ce que cela bloque ? Quel message avez-vous ?
 +  * Nouvelle compilation :
 +    - nettoyez le dossier de construction
 +    - préparez la compilation en précisant un autre compilateur
 +    - compilez le code
 +</​note>​
 +
 +L'​exécution du programme s'​effectue en associant l'​exécutable ''​pkdgrav3''​ au fichier de paramètres ''​cosmology.par''​ dans le dossiers ''​examples''​.
 +
 +<note warning>​Exercice #28 : Exécutez l'​exemple ''​cosmology.par'' ​
 +  * Passez dans le dossier ''​examples''​
 +  * Exécutez ''​pkdgrav3''​ sur ''​cosmology.par''​
 +  * L'​exécution se déroule-t-elle correctement ?
 +</​note>​
 +
 +En cas de difficultés,​ appliquez la [[formation:​insa2018gpu:​insa2018pkdgrav4stretch|recette d'un PKDGRAV3 pour Debian Stretch]] ;-)
 +
 +===== Conclusion =====
 +
 +Comme vous l'​aurez remarqué au cours de ces Travaux Pratiques, l'​exploitation peut être pleine de surprises : une métrologie pertinente ne peut se passer de la connaissance du matériel exploité.
  
 +L'​exploitation de "codes métier"​ vous aura aussi permis d'​entrevoir la difficulté d'​intégrer et d'​exécuter des programmes dans des environnements pourtant bien homogènes : toutes les stations exploitées ont exactement le même système d'​exploitation,​ [[developpement:​productions:​SIDUS|SIDUS]]. Les "​astuces"​ permettant de simplement pouvoir exécuter les programmes illustraient aussi que, sans expérience,​ difficile de s'en sortir.
  
  --- //​[[emmanuel.quemener@ens-lyon.fr|Emmanuel Quemener]] CC BY-NC-SA 2018/11/26 15:37//  --- //​[[emmanuel.quemener@ens-lyon.fr|Emmanuel Quemener]] CC BY-NC-SA 2018/11/26 15:37//
formation/insa2018gpu.1543254503.txt.gz · Dernière modification: 2018/11/26 18:48 par equemene