TP 0 : Prise en main de l’environnement CUDA
5ème année ingénieur de
Polytech Paris-Sud
Stéphane
Vialle, CentraleSupélec & LISN
Stéphane.Vialle@centralesupelec.fr
(TP conçu par Laércio
Lima Pilla, CNRS)
Objectifs
du TP :
Ce TP a pour objectif de permettre
aux étudiants de se familiariser avec l’utilisation des serveurs
de calculs distants du Data Center d’Enseignement (DCE) de
CentraleSupélec, de s’habituer à la lecture et au débogage
d’un code CUDA, de mesurer des performances sur CPU et sur GPU et de calculer des speedup, puis de compléter le code CUDA initial.
Plate-forme
de développement :
Les
machines utilisées seront celles des clusters Tx ou Cameron du DCE de
CentraleSupélec :
- Tx : chaque machine contient un CPU Intel XEON quad-core
hyperthreadés, et un GPU NVIDIA GTX-2080Ti (architecture Turing)
- Cameron
: chaque machine contient un CPU Intel XEON hexa-core
hyperthreadés, et un GPU NVIDIA GTX-1080 (architecture Pascal)
L'environnement
CUDA C et C++ est disponible sur chaque machine (et donc le
compilateur "nvcc"
et les drivers pour utiliser le GPU).
Vous utiliserez les
comptes de TP "23ppsgpu_i", où i est une valeur entière
entre 1 et 10.
Depuis votre poste de travail en mode graphique avec dcejs :
- allocation de ressource : demandez 1 machine en mode exclusif (configuration par défaut)
- action : démarrez VNC
OU BIEN depuis votre poste de travail en mode alphanumérique :
- vous vous connecterez
par ssh sur la machine chome.metz.supelec.fr en indiquant le login 23ppsgpu_i
- par un simple terminal (xterm depuis Linux, ou powershell depuis Windows), puis en entrant la commande suivante :
ssh -l 23ppsgpu_i chome.metz.supelec.fr
- une fois un terminal ouvert sur chome.metz.supelec.fr vous réserverez UN nœud sur le cluster à l'aide d'une commande slurm:
- Pendant le TP : srun --reservation=XXX -N 1 --exclusive --pty bash
--reservation=XXX : pré-réservation de machines, de nom XXX (demander ce nom à l'enseignant)
-N 1 : UN noeud
--exclusive : être seul sur le noeud et pouvoir utiliser tous les coeurs CPU
--pty bash : lancer un shell (bash) pour une session interactive
- Après le TP (si besoin) :
- pour obtenir un noeud Tx (GTX 2080 Ti): srun -p gpu_tp -C tx -N 1 --exclusive --pty bash
- pour obtenir un noeud Cameron (GTX 1080) : srun -p gpu_tp -C cam -N 1 --exclusive --pty bash
Travail à effectuer :
Remarques
préliminaires :
- La
partie CPU (cpu_kernel.cpp)
est complète et sans erreur. Elle servira de calcul de référence
(pour vérifier les résultats obtenus avec la version GPU et pour
la comparaison des performances).
- La
partie GPU (gpu_kernel.cu) contient plusieurs erreurs qui
seront corrigées pendant les étapes du TP.
- des images de
base (inputs/),
- des images pour la vérification (output_examples/),
- un programme pour comparer
deux images (comparison/)
- des programmes pour la mesure et comparaison des performances
(et la validation des sorties).
- Vous
pouvez vérifier des résultats avec les versions CPU et GPU du
programme avec ./test_cpu.sh et ./test_gpu.sh. Vous
pouvez également regarder les images de sortie.
1 – Correction de la compilation du programme :
- Récupérez
le programme de "filtre de flou" depuis votre terminal connecté au DCE :
cp
~vialle/PPS-GPU/ImageFiltering-enonce.zip .
- Compilez le programme avec la commande make ... et corrigez l’erreur dans le Makefile.
2 – Correction
de l’exécution du programme :
A chaque étape, vous compilerez et testerez le programme dans sa
version GPU. Vous
pourrez vérifier que la sortie ne sera pas du tout ou pas exactement
égale à la
sortie de la version CPU (ou aux images de références dans le
répertoire "output_examples/". Après chaque correction, vous pourrez
voir les résultats évoluer et se rapprocher des images de références.
-
Testez le
programme :
- entrez : filter pour obtenir des informations sur les arguments attendus.
- entrez : filter ..... 1 gpu, pour lancer des filtrages avec un seul niveau de filtrage
- Notez les messages d’erreur pendant l’exécution.
Examinez, dans le fichier gpu_kernel.cu, les lignes pointées par les messages d'erreur.
Corrigez les problèmes.
-
Visualisez
les images de sortie qui ont en fait moins d’une ligne de pixels filtrés.
Examinez le début du kernel gpuBlur dans le fichier
gpu_kernel.cu, trouvez le problème et corrigez-le.
Si besoin, en mode alphanumérique vous pouvez rapatrier les images de sorties avec une commande scp sur votre laptop :
scp 23ppsgpu_i@chome.metz.supelec.fr:remotedirectory/yyy.png localdirectory/
-
Visualisez les images de sortie qui ne devraient avoir maintenant qu’un tiers des pixels filtrés. Examinez le
code, trouvez le problème et corrigez-le.
-
Vérifier
les images de sortie qui ne devraient avoir maintenant que la moitie des pixels filtrés.
Examinez le code, trouvez le problème et corrigez-le.
-
Lancez des filtrages avec un niveau de filtrage supérieur à 1. Si vous obtenez des images regardez-les avec un niveau de zoom
élevé pour trouver les différences, sinon notez les messages d'erreurs affichés. Dans tous les cas examinez le code, trouvez le
problème et corrigez-le.
Rmq : Il est plus facile de voir les différences entre les images avec
un niveau de filtrage élevé (ex :10)
-
Pour valider complètement votre code :
-
Compilez
le progamme comparison dans le répertoire comparison (utilisez make), et comparez des
images résultas obtenues avec le cpu et avec le gpu. Les images doivent
être rigoureusement identiques.
-
Faites un chmod 700 test_*.sh,
puis exécutez test_gpu.sh qui générera 3 images filtrées sur le GPU et
les comparera aux images de référence du répertoire output_examples/.
Les images doivent être rigoureusement identiques.
3 - Etude
des performances :
- Générez
des images filtrées sur CPU et sur GPU avec les niveaux de filtre : 1, 10, 20, et notez les temps d'exécutio
- Calculez le speedup entre les versions
CPU et GPU pour les différents scenarios (image + niveau de
filtrage) testés.
4 - Développement de nouveaux kernels :
-
Implantez
un nouveau filtre qui fait l’inversion des couleurs des images.
L’inversion d’une couleur est égal a 255 moins sa valeur
actuelle.
- Réimplantez
le kernel gpuBlur en utilisant de blocs 2D et une
grille de blocs 2D (à la place du code avec un grille 1D des blocs
1D actuel).