| Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente |
| formation:gpu4cbp [2023/03/10 15:32] – [Comparaison de toutes les implémentations : victoire incontestée de OpenCL] equemene | formation:gpu4cbp [2024/02/22 10:47] (Version actuelle) – [Récupération des sources] equemene |
|---|
| svn checkout https://forge.cbp.ens-lyon.fr/svn/bench4gpu/ | svn checkout https://forge.cbp.ens-lyon.fr/svn/bench4gpu/ |
| </code> | </code> |
| | |
| | Si l'accès par subversion c'est pas possible, voici une version //tarball// de l'ensemble de l'archive : [[https://www.cbp.ens-lyon.fr/emmanuel.quemener/documents/bench4gpu.tgz|bench4gpu.tgz]] |
| |
| Dans ce dossier ''bench4gpu'', il y a plusieurs dossiers : | Dans ce dossier ''bench4gpu'', il y a plusieurs dossiers : |
| - la OpenACC reste supérieure aux implémentations OpenCL/CPU et OpenCL/GPU d'un facteur 3 | - la OpenACC reste supérieure aux implémentations OpenCL/CPU et OpenCL/GPU d'un facteur 3 |
| |
| Se contenter uniquement de ce test inviterait à fuire Python/OpenCL. Cependant, nous avons vu dans sur ''MySteps_2.py'' que la charge calculatoire doit être "vraiement" significative pour que le Python/OpenCL l'emporte de manière significative. Nous reviendrons donc dans la suite sur des versions modifiées de ces programmes C intégrant la fonction de Mylq ''MySillyFunction'', appelée plusieurs fois, pour juger si "vraiment" Python/OpenCL reste compétitif face à OpenMP et OpenACC. | Se contenter uniquement de ce test inviterait à fuire Python/OpenCL. Cependant, nous avons vu dans sur ''MySteps_2.py'' que la charge calculatoire doit être "vraiment" significative pour que le Python/OpenCL l'emporte de manière significative. Nous reviendrons donc dans la suite sur des versions modifiées de ces programmes C intégrant la fonction de Mylq ''MySillyFunction'', appelée plusieurs fois, pour juger si Python/OpenCL reste compétitif face à OpenMP et OpenACC. |
| ===== Un intermède CUDA et son implémentation PyCUDA ===== | ===== Un intermède CUDA et son implémentation PyCUDA ===== |
| |
| La difficulté viendra du temps d'exécution de la version séquentielle qui atteint son pallier de performances pour une taille croissante de vecteurs assez rapidement et du choix judicieux de l'inhibition de l'exécution séquentielle pour permettre d'atteindre des tailles de vecteurs significatives. | La difficulté viendra du temps d'exécution de la version séquentielle qui atteint son pallier de performances pour une taille croissante de vecteurs assez rapidement et du choix judicieux de l'inhibition de l'exécution séquentielle pour permettre d'atteindre des tailles de vecteurs significatives. |
| |
| <note warning>**Exercice #2.4 : exécution des différentes implémentations** | <note warning>**Exercice #4.1 : exécution des différentes implémentations** |
| - Compilez ''MySteps_6.c'' en ''MySteps_6'' | - Compilez ''MySteps_6.c'' en ''MySteps_6'' |
| - Compilez ''MySteps_6_openmp.c'' en ''MySteps_6_openmp'' | - Compilez ''MySteps_6_openmp.c'' en ''MySteps_6_openmp'' |
| Si la performance pour une taille de 2097152 est moins de 5% supérieure à la performance pour une taille de 1048576, vous pouvez considérer que vous avez atteint le quasi-optimum de performance. L'objectif est d'atteindre cette limite. | Si la performance pour une taille de 2097152 est moins de 5% supérieure à la performance pour une taille de 1048576, vous pouvez considérer que vous avez atteint le quasi-optimum de performance. L'objectif est d'atteindre cette limite. |
| |
| <note warning>**Exercice #2.5 : exploration de la meilleure performance OpenCL et CUDA** | <note warning>**Exercice #4.2 : exploration de la meilleure performance OpenCL et CUDA** |
| - Exécutez ''MySteps_6.py'' en OpenCL Intel sur des tailles croissantes avec l'option ''-n'' | - Exécutez ''MySteps_6.py'' en OpenCL Intel sur des tailles croissantes avec l'option ''-n'' |
| - Relevez **OpenCLRate** pour les différentes charges | - Relevez **OpenCLRate** pour les différentes charges |
| Il sera alors possible d'estimer l'erreur numérique à ce calcul. | Il sera alors possible d'estimer l'erreur numérique à ce calcul. |
| |
| <note warning>**Exercice #4.1 : implémentation Python "naïve"** | <note warning>**Exercice #5.1 : implémentation Python "naïve"** |
| - Modifiez ''MyDFT_1.py'' suivant les 7 spécifications ci-dessus | - Modifiez ''MyDFT_1.py'' suivant les 7 spécifications ci-dessus |
| - Exécutez le programme pour une taille de **16** et contrôler la cohérence | - Exécutez le programme pour une taille de **16** et contrôler la cohérence |
| - comparer les résultats entre les deux avec ''linalg.norm'' | - comparer les résultats entre les deux avec ''linalg.norm'' |
| |
| <note warning>**Exercice #4.2 : implémentation Python Numpy** | <note warning>**Exercice #5.2 : implémentation Python Numpy** |
| - Copiez le programme ''MyDFT_1.py'' en ''MyDFT_2.py'' | - Copiez le programme ''MyDFT_1.py'' en ''MyDFT_2.py'' |
| - Modifiez ''MyDFT_2.py'' suivant les 7 spécifications ci-dessus | - Modifiez ''MyDFT_2.py'' suivant les 7 spécifications ci-dessus |
| - changer le domaine d'itération pour la boucle : ''range()'' par ''numba.prange()'' | - changer le domaine d'itération pour la boucle : ''range()'' par ''numba.prange()'' |
| |
| <note warning>**Exercice #4.3 : implémentation Python Numpy** | <note warning>**Exercice #5.3 : implémentation Python Numpy** |
| - Copiez le programme ''MyDFT_2.py'' en ''MyDFT_3.py'' et exploitez ce dernier | - Copiez le programme ''MyDFT_2.py'' en ''MyDFT_3.py'' et exploitez ce dernier |
| - Copiez la fonction ''NumpyDFT'' en ''NumbaDFT'' | - Copiez la fonction ''NumpyDFT'' en ''NumbaDFT'' |
| Pour l'implémentation OpenCL, la version "naïve" de l'implémentation va servir. Pour cela, il suffit de reprendre la définition de la méthode naïve et de l'implémenter en C dans un noyau OpenCL. A noter que Pi n'étant dans une variable définie, il faut explicitement la détailler dans le noyau OpenCL. Autre détail important : le //cast//. De manière a éviter tout effet de bord, il est fortement recommandé de //caster// les opérations dans la précision flottante souhaitée pour des opérations sur des indices entiers. | Pour l'implémentation OpenCL, la version "naïve" de l'implémentation va servir. Pour cela, il suffit de reprendre la définition de la méthode naïve et de l'implémenter en C dans un noyau OpenCL. A noter que Pi n'étant dans une variable définie, il faut explicitement la détailler dans le noyau OpenCL. Autre détail important : le //cast//. De manière a éviter tout effet de bord, il est fortement recommandé de //caster// les opérations dans la précision flottante souhaitée pour des opérations sur des indices entiers. |
| |
| <note warning>**Exercice #4.4 : implémentation Python OpenCL** | <note warning>**Exercice #5.4 : implémentation Python OpenCL** |
| - Copiez le programme ''MyDFT_3.py'' en ''MyDFT_4.py'' et exploitez ce dernier | - Copiez le programme ''MyDFT_3.py'' en ''MyDFT_4.py'' et exploitez ce dernier |
| - Copiez la fonction python ''OpenCLAddition'' en ''OpenCLDFT'' | - Copiez la fonction python ''OpenCLAddition'' en ''OpenCLDFT'' |
| * modifier les vecteurs en sortie (2 vecteurs) | * modifier les vecteurs en sortie (2 vecteurs) |
| |
| <note warning>**Exercice #4.5 : implémentation Python CUDA** | <note warning>**Exercice #5.5 : implémentation Python CUDA** |
| - Copiez le programme ''MyDFT_4.py'' en ''MyDFT_5.py'' et exploitez ce dernier | - Copiez le programme ''MyDFT_4.py'' en ''MyDFT_5.py'' et exploitez ce dernier |
| - Copiez la fonction python ''CUDAAddition'' en ''CUDADFT'' | - Copiez la fonction python ''CUDAAddition'' en ''CUDADFT'' |
| L'objectif est donc de reprendre notre exemple le plus abouti de notre DFT et d'y ajouter ces éléments. Pour cela, les programmes ''PiXPU.py'' et ''TrouNoir.py'' vont être explorés pour voir comment faire. | L'objectif est donc de reprendre notre exemple le plus abouti de notre DFT et d'y ajouter ces éléments. Pour cela, les programmes ''PiXPU.py'' et ''TrouNoir.py'' vont être explorés pour voir comment faire. |
| |
| <note warning>**Exercice #5.1 : exploration de PiXPU.py** | <note warning>**Exercice #6.1 : exploration de PiXPU.py** |
| - Identifiez les lignes correspondant aux paramétrages par défaut | - Identifiez les lignes correspondant aux paramétrages par défaut |
| - Identifiez les lignes sur la découverte des périphériques OpenCL | - Identifiez les lignes sur la découverte des périphériques OpenCL |
| - Sélectionner une exécution sous OpenCL ou CUDA avec l'option ''-g'' | - Sélectionner une exécution sous OpenCL ou CUDA avec l'option ''-g'' |
| |
| <note warning>**Exercice #5.2 : modification du programme ''MyDFT_6.py''** | <note warning>**Exercice #6.2 : modification du programme ''MyDFT_6.py''** |
| - Supprimer la sélection initiale d'argument | - Supprimer la sélection initiale d'argument |
| - Inhiber pour l'instant l'exécution des fonctions | - Inhiber pour l'instant l'exécution des fonctions |
| </code> | </code> |
| |
| <note warning>**Exercice #5.3 : modification du programme ''MyDFT_7.py''** | <note warning>**Exercice #6.3 : modification du programme ''MyDFT_7.py''** |
| - Libérez pour l'appel à la fonction ''OpenCLDFT'' | - Libérez pour l'appel à la fonction ''OpenCLDFT'' |
| - Rajoutez le test exploitant la sélection OpenCL ou CUDA | - Rajoutez le test exploitant la sélection OpenCL ou CUDA |
| |
| <note warning> | <note warning> |
| **Exercice #6.1 : éditez le source du programme ''xGEMM.c'' et repérez les éléments suivants** | **Exercice #7.1 : éditez le source du programme ''xGEMM.c'' et repérez les éléments suivants** |
| |
| * Identifiez dans ''Makefile'' quelles directives (précédées par ''-D'') sont associées aux différentes implémentations | * Identifiez dans ''Makefile'' quelles directives (précédées par ''-D'') sont associées aux différentes implémentations |
| |
| <note warning> | <note warning> |
| **Exercice #6.2 : lancez les ''xGEMM_<precision>_<implementation>'' avec une taille de 1000** | **Exercice #7.2 : lancez les ''xGEMM_<precision>_<implementation>'' avec une taille de 1000** |
| |
| * Variez le nombre d'itérations pour obtenir une durée d'exécution d'une dizaine de secondes ? | * Variez le nombre d'itérations pour obtenir une durée d'exécution d'une dizaine de secondes ? |
| |
| <note warning> | <note warning> |
| **Exercice #6.3 : lancez les programmes précédents pour différentes tailles** | **Exercice #7.3 : lancez les programmes précédents pour différentes tailles** |
| |
| * Diminuez la taille aux valeurs suivantes ''125'', ''250'', ''500'' et exécutez les programmes | * Diminuez la taille aux valeurs suivantes ''125'', ''250'', ''500'' et exécutez les programmes |
| L'objectif est de "jouer" le [[https://www.tensorflow.org/tutorials/images/cnn|tutoriel]] exploitant la base d'images CIFAR10 pour un apprentissage convolutif. | L'objectif est de "jouer" le [[https://www.tensorflow.org/tutorials/images/cnn|tutoriel]] exploitant la base d'images CIFAR10 pour un apprentissage convolutif. |
| |
| <note warning>**Exercice #7.1 :** | <note warning>**Exercice #8.1 :** |
| - chargez l'environnement conda | - chargez l'environnement conda |
| - préparez la variable d'environnement ''TIME'' | - préparez la variable d'environnement ''TIME'' |
| En regardant l'activité du GPU, il apparaît que le gain est substanciel par rapport à une "petite" configuration GPU. Cependant, la nature du réseau créé n'exploitait pas de manière optimale la GPU par rapport à la CPU. Une petite modification de notre réseau va permettre de mettre cela en évidence, en modifiant le nombre de poids d'une des couches neuronales. | En regardant l'activité du GPU, il apparaît que le gain est substanciel par rapport à une "petite" configuration GPU. Cependant, la nature du réseau créé n'exploitait pas de manière optimale la GPU par rapport à la CPU. Une petite modification de notre réseau va permettre de mettre cela en évidence, en modifiant le nombre de poids d'une des couches neuronales. |
| |
| <note warning>**Exercice #7.2 :** | <note warning>**Exercice #8.2 :** |
| - changez **64** en **65536** dans ''model.add(layers.Dense(64, activation='relu'))'' | - changez **64** en **65536** dans ''model.add(layers.Dense(64, activation='relu'))'' |
| - supprimez la référence à ''CUDA_VISIBLE_DEVICES'' avec ''export -n CUDA_VISIBLE_DEVICES'' | - supprimez la référence à ''CUDA_VISIBLE_DEVICES'' avec ''export -n CUDA_VISIBLE_DEVICES'' |
| Le code source est accessible à l'adresse : https://www.r-ccs.riken.jp/labs/cbrt/download/genesis-version-1-5/ | Le code source est accessible à l'adresse : https://www.r-ccs.riken.jp/labs/cbrt/download/genesis-version-1-5/ |
| |
| <note warning>**Exercice #8.1 : Récupérez et compilez le code suivant la documentation fournie** | <note warning>**Exercice #9.1 : Récupérez et compilez le code suivant la documentation fournie** |
| * Lisez la [[https://www.r-ccs.riken.jp/labs/cbrt/installation/|documentation]] d'installation | * Lisez la [[https://www.r-ccs.riken.jp/labs/cbrt/installation/|documentation]] d'installation |
| * Placez les sources dans le dossier ''/local/$USER/GENESIS'' créé pour l'occasion | * Placez les sources dans le dossier ''/local/$USER/GENESIS'' créé pour l'occasion |
| Pour finir, dans comme ce programme est "aussi" //gépufié// (porté sur GPU), il risque d'y avoir un goulet d'étranglement pour l'accès au GPU pour les 64 tâches simultanées. Ainsi, les programmes "fortement" parallélisés exigent de choisir judicieusement les différents paramètres de parallélisation tout comme nous avons vue que, pour les GPU, il fallait découper la tâche en un nombre optimal de sous-tâches. | Pour finir, dans comme ce programme est "aussi" //gépufié// (porté sur GPU), il risque d'y avoir un goulet d'étranglement pour l'accès au GPU pour les 64 tâches simultanées. Ainsi, les programmes "fortement" parallélisés exigent de choisir judicieusement les différents paramètres de parallélisation tout comme nous avons vue que, pour les GPU, il fallait découper la tâche en un nombre optimal de sous-tâches. |
| |
| <note warning>**Exercice #8.2 : Exécutez l'exemple ''alad_water''** | <note warning>**Exercice #9.2 : Exécutez l'exemple ''alad_water''** |
| * Récupérez [[http://www.cbp.ens-lyon.fr/emmanuel.quemener/documents/alad_water.tgz|l'exemple d'exécution]] | * Récupérez [[http://www.cbp.ens-lyon.fr/emmanuel.quemener/documents/alad_water.tgz|l'exemple d'exécution]] |
| * Décompressez l'archive dans ''/local/$USER/GENESIS'' | * Décompressez l'archive dans ''/local/$USER/GENESIS'' |
| 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]]. | 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 #9.1 : appliquez la "recette" de Nvidia** | <note warning>**Exercice #10.1 : appliquez la "recette" de Nvidia** |
| * La documentation offre ceci : | * La documentation offre ceci : |
| - récupérez le source | - récupérez le source |
| En cas de difficultés, appliquez la [[formation:insa2020gpu:insa2020gromacs4buster|recette de Gromacs pour Debian Buster]] ;-) | En cas de difficultés, appliquez la [[formation:insa2020gpu:insa2020gromacs4buster|recette de Gromacs pour Debian Buster]] ;-) |
| |
| <note warning>**Exercice #9.2 : Exécutez l'exemple ''1536''** | <note warning>**Exercice #10.2 : 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 ? |