This shows you the differences between two versions of the page.
asc:laboratoare:04 [2024/03/25 19:55] emil.slusanschi [Referinte] |
asc:laboratoare:04 [2025/03/26 11:44] (current) alexandru.bala [Aplicatie compute CUDA] |
||
---|---|---|---|
Line 7: | Line 7: | ||
Succesorul chipurilor de prelucrare grafică din jocurile aracade, procesoarul grafic, acronim **GPU** (**G**raphics **P**rocessing **U**nit), este un circuit electronic, specializat, în crearea și manipularea imaginilor trimise către un afișaj electronic (e.g. monitor). | Succesorul chipurilor de prelucrare grafică din jocurile aracade, procesoarul grafic, acronim **GPU** (**G**raphics **P**rocessing **U**nit), este un circuit electronic, specializat, în crearea și manipularea imaginilor trimise către un afișaj electronic (e.g. monitor). | ||
- | Utilitatea lui s-a extins ulterior către probleme "embarrassingly parallel", iar în astăzi sunt folosite la antrenarea antrenarea rețelelor neurale și minarea de criptomonede. Vorbim aici despre întrebuințarea unui **GPGPU** (**G**eneral **P**urpose GPU), un procesor grafic cu o flexibilitate ridicată de programare, capabil de a rezolva și probleme generale. | + | Utilitatea lui s-a extins ulterior către probleme "embarrassingly parallel", iar astăzi sunt folosite la antrenarea rețelelor neurale și minarea de criptomonede. Vorbim aici despre întrebuințarea unui **GPGPU** (**G**eneral **P**urpose GPU), un procesor grafic cu o flexibilitate ridicată de programare, capabil de a rezolva și probleme generale. |
==== Teorie ==== | ==== Teorie ==== | ||
Line 40: | Line 40: | ||
* Vivante http://en.wikipedia.org/wiki/Vivante_Corporation | * Vivante http://en.wikipedia.org/wiki/Vivante_Corporation | ||
- | Dacă un IP de GPU este integrat pe aceeași //pastilă de siliciu// a unui SoC (**S**ystem-**o**n-a-**C**hip), spunem că este un GPU integrat. Exemple de SoC-uri cu IP de GPU integrat includ procesoarele x86 Intel/AMD, cât și majoritatea SoC-urilor pentru dispozitive mobile bazate pe arhitectura ARM (ex. Qualcomm Snapdragon). Un GPU integrat împarte ierarhia de memorie cu alte IP-uri (exp. controllere PCIe/USB/SATA/ETH). | + | Dacă un IP de GPU este integrat pe aceeași //pastilă de siliciu// a unui SoC (**S**ystem-**o**n-a-**C**hip), spunem că este un GPU integrat. Exemple de SoC-uri cu IP de GPU integrat includ procesoarele x86 Intel/AMD, cât și majoritatea SoC-urilor pentru dispozitive mobile bazate pe arhitectura ARM (ex. Qualcomm Snapdragon). Un GPU integrat împarte ierarhia de memorie cu alte IP-uri (ex. controllere PCIe/USB/SATA/ETH). |
- | De altfel, un GPU dedicat (discrete GPU) presupune valorificarea unei unui spațiu de memorie, mapat peste **VRAM** (**V**ideo **R**andom-**A**ccess **M**emory), cât și o magistrală PCIe/AGP8x/USB pentru comunicare cu sistemul. Exemple de GPU-uri dedicate sunt seriile de plăci grafice Geforce (Nvidia) și Radeon (AMD). | + | De altfel, un GPU dedicat (discrete GPU) presupune valorificarea unei unui spațiu de memorie, mapat peste **VRAM** (**V**ideo **R**andom-**A**ccess **M**emory), cât și o magistrală PCIe/AGP8x/USB pentru comunicarea cu sistemul. Exemple de GPU-uri dedicate sunt seriile de plăci grafice Geforce (Nvidia) și Radeon (AMD). |
{{:asc:lab10:dgpu_igpu.png?direct&750|}} | {{:asc:lab10:dgpu_igpu.png?direct&750|}} | ||
Line 115: | Line 115: | ||
Știind versiunea majoră și cea minoră cunoaștem facilitățile hardware oferite de către arhitectură. | Știind versiunea majoră și cea minoră cunoaștem facilitățile hardware oferite de către arhitectură. | ||
- | O listă a GPU-urile NVIDIA și versiunile lor majore/minore se regăsește [[https://developer.nvidia.com/cuda-gpus|aici]]. | + | O listă a GPU-urilor NVIDIA și versiunile lor majore/minore se regăsește [[https://developer.nvidia.com/cuda-gpus|aici]]. |
===== Programarea in CUDA ===== | ===== Programarea in CUDA ===== | ||
Line 201: | Line 201: | ||
O aplicatie CUDA are ca scop executia de cod pe GPU-uri NVIDIA CUDA. | O aplicatie CUDA are ca scop executia de cod pe GPU-uri NVIDIA CUDA. | ||
In cadrul laboratoarelor partea de CPU (host) va fi folosita exclusiv pentru managementul executiei partii de GPU (device). | In cadrul laboratoarelor partea de CPU (host) va fi folosita exclusiv pentru managementul executiei partii de GPU (device). | ||
- | Aplicatiilor vor viza executia folosind un singur GPU NVIDIA CUDA. | + | Aplicatiile vor viza executia folosind un singur GPU NVIDIA CUDA. |
==== 0. Definire functie kernel ==== | ==== 0. Definire functie kernel ==== | ||
Line 342: | Line 342: | ||
</code> | </code> | ||
- | ===== Compilare si executie ===== | + | ===== Aplicații ===== |
- | + | ||
- | Desi pentru un programator partile de host/CPU respectiv device/GPU pot fi in acelasi fisier *.cu, compilatorul CUDA (nvcc) le separa facand o compilare diferita pentru partea de host/CPU respectiv device/GPU. Figura de mai jos denota acest aspect. | + | |
{{:asc:lab7:cuda-nvcc.png?480|}} | {{:asc:lab7:cuda-nvcc.png?480|}} | ||
- | Intrati pe frontend-ul ''fep8.grid.pub.ro'' folosind contul de pe curs.upb.ro. Executati comanda | + | <note important> |
+ | Pentru editarea fișierelor pe cluster, recomandam sa va montați sistemul de pe fep8 pe mașină locală. Pașii sunt detaliați mai jos - multumiri lui Radu Millo pentru redactare. | ||
- | <code sh> | + | Tutorial chei ssh: https://www.ssh.com/academy/ssh/keygen |
- | srun --pty -p xl --gres gpu:1 /bin/bash | + | |
- | </code> | + | |
- | + | ||
- | pentru a accesa una din statiile cu GPU-uri. Cozile ce au unitati GPU NVIDIA sunt xl si ucsx. | + | |
+ | Pe fep8, din directorul vostru home (''%%~%%''), dați comanda: | ||
<code sh> | <code sh> | ||
- | [@fep8 ~]$ srun --pty -p xl --gres gpu:1 /bin/bash | + | mkdir asc |
- | [@wn-xyz ~]$ nvidia-smi # NVIDIA System Management Interface program | + | cd asc |
- | +---------------------------------------------------------------------------------------+ | + | pwd # acesta va returna <cale_absolută_director_asc_fep8> |
- | | NVIDIA-SMI 535.104.05 Driver Version: 535.104.05 CUDA Version: 12.2 | | + | |
- | |-----------------------------------------+----------------------+----------------------+ | + | |
- | | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | + | |
- | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | + | |
- | | | | MIG M. | | + | |
- | |=========================================+======================+======================| | + | |
- | | 0 Tesla P100-PCIE-16GB On | 00000000:0D:00.0 Off | 0 | | + | |
- | | N/A 28C P0 27W / 250W | 0MiB / 16384MiB | 0% Default | | + | |
- | | | | N/A | | + | |
- | +-----------------------------------------+----------------------+----------------------+ | + | |
- | + | ||
- | +---------------------------------------------------------------------------------------+ | + | |
- | | Processes: | | + | |
- | | GPU GI CI PID Type Process name GPU Memory | | + | |
- | | ID ID Usage | | + | |
- | |=======================================================================================| | + | |
- | | No running processes found | | + | |
- | +---------------------------------------------------------------------------------------+ | + | |
</code> | </code> | ||
- | |||
- | Pentru laboratoarele de GP-GPU Computing vom folosi CUDA 10.2 sau 11.4 [[https://developer.nvidia.com/cuda-11-4-4-download-archive|aici]]. | ||
- | |||
- | SDK-ul CUDA de la NVidia include atat implementarea de CUDA API cat si cea de OpenCL API. In cadrul laboratoarelor vom programa numai folosind CUDA. Verificam mai jos ca scheletul laboratorului compileaza. | ||
- | |||
- | <code sh> | ||
- | [@wn-xyz ~]$ wget -O lab7_skl.tar.gz https://ocw.cs.pub.ro/courses/_media/asc/lab7/lab7_skl.tar.gz | ||
- | --2020-03-22 18:52:14-- http://ocw.cs.pub.ro/courses/_media/asc/lab7/lab7_skl.tar.gz | ||
- | Resolving ocw.cs.pub.ro (ocw.cs.pub.ro)... 141.85.227.65 | ||
- | Connecting to ocw.cs.pub.ro (ocw.cs.pub.ro)|141.85.227.65|:80... connected. | ||
- | HTTP request sent, awaiting response... 302 Found | ||
- | Location: https://ocw.cs.pub.ro/courses/_media/asc/lab7/lab7_skl.tar.gz [following] | ||
- | --2020-03-22 18:52:14-- https://ocw.cs.pub.ro/courses/_media/asc/lab7/lab7_skl.tar.gz | ||
- | Connecting to ocw.cs.pub.ro (ocw.cs.pub.ro)|141.85.227.65|:443... connected. | ||
- | HTTP request sent, awaiting response... 200 OK | ||
- | Length: 4884 (4.8K) [application/octet-stream] | ||
- | Saving to: 'lab7_skl.tar.gz' | ||
- | |||
- | 100%[==================================================================================================>] 4,884 --.-K/s in 0s | ||
- | |||
- | 2020-03-22 18:52:14 (11.1 MB/s) - 'lab7_skl.tar.gz' saved [4884/4884] | ||
- | |||
- | [@wn-xyz ~]$ tar -xvzf lab7_skl.tar.gz | ||
- | task1/ | ||
- | task1/task1.cu | ||
- | task1/Makefile | ||
- | task1/Makefile_Cluster | ||
- | task2/ | ||
- | task2/task2.cu | ||
- | task2/Makefile | ||
- | task2/Makefile_Cluster | ||
- | ... | ||
- | [@wn-xyz ~]$ cd task1/ | ||
- | </code> | ||
- | |||
- | <code sh> | ||
- | [@wn-xyz ~]$ apptainer run --nv docker://gitlab.cs.pub.ro:5050/asc/asc-public/cuda-labs:1.9.1 | ||
- | INFO: Using cached SIF image | ||
- | Apptainer> | ||
- | </code> | ||
- | |||
- | În cadrul imaginei CUDA avem compilatorul nvcc. | ||
- | |||
- | <code Makefile> | ||
- | COMPILER=nvcc | ||
- | LIBS=-lm | ||
- | |||
- | %: %.cu | ||
- | $(COMPILER) $^ -o $@ $(LIBS) | ||
- | |||
- | clean: | ||
- | rm -rf task0 | ||
- | </code> | ||
- | |||
- | Exemplu de compilare si rulare interactiva pe coada xl | ||
- | <code sh> | ||
- | Apptainer> make task1 | ||
- | nvcc task1.cu -o task1 -lm | ||
- | Apptainer> ./task1 | ||
- | [HOST] Hello from the host! | ||
- | [HOST] You have 3 CUDA-capable GPU(s) | ||
- | Apptainer> make clean | ||
- | rm -rf task1 | ||
- | Apptainer> cd ../task2 | ||
- | Apptainer> make task2 | ||
- | nvcc task2.cu -o task2 -lm | ||
- | Apptainer> ./task2 | ||
- | Result 0: 2 * 0.0 + 1.0/(0.0 + 1.0)= 0.000 | ||
- | Result 1: 2 * 1.0 + 1.0/(1.0 + 1.0)= 0.000 | ||
- | Result 2: 2 * 2.0 + 1.0/(2.0 + 1.0)= 0.000 | ||
- | Result 3: 2 * 3.0 + 1.0/(3.0 + 1.0)= 0.000 | ||
- | Result 4: 2 * 4.0 + 1.0/(4.0 + 1.0)= 0.000 | ||
- | Result 5: 2 * 5.0 + 1.0/(5.0 + 1.0)= 0.000 | ||
- | Result 6: 2 * 6.0 + 1.0/(6.0 + 1.0)= 0.000 | ||
- | Result 7: 2 * 7.0 + 1.0/(7.0 + 1.0)= 0.000 | ||
- | Result 8: 2 * 8.0 + 1.0/(8.0 + 1.0)= 0.000 | ||
- | Result 9: 2 * 9.0 + 1.0/(9.0 + 1.0)= 0.000 | ||
- | Apptainer> | ||
- | </code> | ||
- | |||
- | Exemplu executie program CUDA folosind rularea ne-interactiva pe coada de executia xl (apelul trebuie facut de pe fep8.grid.pub.ro): | ||
- | <code sh> | ||
- | [fep8 ~]$ cd task2/ | ||
- | [fep8 task2]$ cat ../utils/batch_run.sh | ||
- | #!/bin/bash | ||
- | apptainer exec --nv $CONTAINER_IMAGE \ | ||
- | ./$TASK | ||
- | [fep8 task2]$ sbatch --time 01:00:00 -p xl --gres gpu:1 --export=TASK=task2,CONTAINER_IMAGE=docker://gitlab.cs.pub.ro:5050/asc/asc-public/cuda-labs:1.9.1 ../utils/batch_run.sh | ||
- | Submitted batch job 1816 | ||
- | [fep8 task2]$ squeue | grep 1816 | ||
- | 1816 xl batch_ru stefan_d R 0:07 1 xl-wn-xyz | ||
- | [fep8 task2]$ cat slurm-1816.out | ||
- | INFO: Using cached SIF image | ||
- | Result 0: 2 * 0.0 + 1.0/(0.0 + 1.0)= 1.000 | ||
- | Result 1: 2 * 1.0 + 1.0/(1.0 + 1.0)= 2.500 | ||
- | Result 2: 2 * 2.0 + 1.0/(2.0 + 1.0)= 4.333 | ||
- | Result 3: 2 * 3.0 + 1.0/(3.0 + 1.0)= 6.250 | ||
- | Result 4: 2 * 4.0 + 1.0/(4.0 + 1.0)= 8.200 | ||
- | Result 5: 2 * 5.0 + 1.0/(5.0 + 1.0)= 10.167 | ||
- | Result 6: 2 * 6.0 + 1.0/(6.0 + 1.0)= 12.143 | ||
- | Result 7: 2 * 7.0 + 1.0/(7.0 + 1.0)= 14.125 | ||
- | Result 8: 2 * 8.0 + 1.0/(8.0 + 1.0)= 16.111 | ||
- | Result 9: 2 * 9.0 + 1.0/(9.0 + 1.0)= 18.100 | ||
- | </code> | ||
- | |||
- | |||
- | Puteți folosi Makefile_Cluster: | ||
- | <code sh> | ||
- | [fep8 ~]$ cd task2/ | ||
- | [fep8 task2]$ make -f Makefile_Cluster clean | ||
- | rm -rf task2 | ||
- | rm -rf slurm-* | ||
- | [fep8 task2]$ make -f Makefile_Cluster task2 | ||
- | sbatch --time 01:00:00 -p xl --gres gpu:1 --export=TASK=task2,CONTAINER_IMAGE=docker://gitlab.cs.pub.ro:5050/asc/asc-public/cuda-labs:1.9.1 ../utils/batch_build.sh | ../utils/batch_wait.sh | ||
- | INFO: Using cached SIF image | ||
- | nvcc task2.cu -o task2 -lm | ||
- | [fep8 task2]$ make -f Makefile_Cluster run_task1 | ||
- | sbatch --time 01:00:00 -p xl --export=TASK=task2,CONTAINER_IMAGE=docker://gitlab.cs.pub.ro:5050/asc/asc-public/cuda-labs:1.9.1 ../utils/batch_run.sh | ../utils/batch_wait.sh | ||
- | INFO: Using cached SIF image | ||
- | Result 0: 2 * 0.0 + 1.0/(0.0 + 1.0)= 1.000 | ||
- | Result 1: 2 * 1.0 + 1.0/(1.0 + 1.0)= 2.500 | ||
- | Result 2: 2 * 2.0 + 1.0/(2.0 + 1.0)= 4.333 | ||
- | Result 3: 2 * 3.0 + 1.0/(3.0 + 1.0)= 6.250 | ||
- | Result 4: 2 * 4.0 + 1.0/(4.0 + 1.0)= 8.200 | ||
- | Result 5: 2 * 5.0 + 1.0/(5.0 + 1.0)= 10.167 | ||
- | Result 6: 2 * 6.0 + 1.0/(6.0 + 1.0)= 12.143 | ||
- | Result 7: 2 * 7.0 + 1.0/(7.0 + 1.0)= 14.125 | ||
- | Result 8: 2 * 8.0 + 1.0/(8.0 + 1.0)= 16.111 | ||
- | Result 9: 2 * 9.0 + 1.0/(9.0 + 1.0)= 18.100 | ||
- | </code> | ||
- | |||
- | <note important> | ||
- | Recomandăm sa va delogati mereu de pe serverele din cluster dupa terminarea sesiunii, utilizand comanda ''exit'' | ||
- | |||
- | Alternativ, daca ati uitat sesiuni deschise, puteti verifica acest lucru de pe fep8.grid.pub.ro, utilizand comanda ''squeue''. In cazul in care identificati astfel de sesiuni "agatate", le puteti sterge (si va rugam sa faceti asta), utilizand comanda ''scancel ID'' unde ID-ul il identificati din comanda anterioara ''squeue''. Puteți folosi mai precis ''squeue -u username'' (username de pe fep8.grid.pub.ro) pentru a vedea doar sesiunile care vă interesează. | ||
- | |||
- | Daca nu veti face aceasta delogare, veti putea ajunge in situatia in care sa nu va mai puteti loga pe nodurile din cluster. | ||
- | </note> | ||
- | |||
- | <note important> | ||
- | Pentru editarea fișierelor pe cluster, recomandam sa va montați sistemul de pe fep8 pe mașină locală. Pașii sunt detaliați mai jos - multumiri lui Radu Millo pentru redactare. | ||
- | |||
- | Tutorial chei ssh: https://www.ssh.com/academy/ssh/keygen | ||
Tutorial montare filesystem din fep pe local - comenzi date pe local: | Tutorial montare filesystem din fep pe local - comenzi date pe local: | ||
<code sh> | <code sh> | ||
- | mkdir /mnt/asc | + | mkdir asc # puteți da comanda din directorul vostru home |
- | sudo chown -R <user> /mnt/asc | + | cd asc |
- | decomentam linia 'user_allow_other' din /etc/fuse.conf | + | pwd # acesta va returna <cale_absolută_director_asc_local> |
- | sshfs -o allow_other <user.moodle>@fep8.grid.pub.ro:/ /mnt/asc | + | sudo chown -R <user> asc # numele user-ului vostru de pe local |
+ | decomentăm linia 'user_allow_other' din /etc/fuse.conf | ||
+ | sshfs -o allow_other <user.moodle>@fep8.grid.pub.ro:<cale_absolută_director_asc_fep8> <cale_absolută_director_asc_local> | ||
</code> | </code> | ||
</note> | </note> | ||
- | ===== Exercitii ===== | + | Urmăriți instrucțiunile de pe GitLab [[https://gitlab.cs.pub.ro/asc/asc-public/-/tree/master/labs/cuda/intro|GitLab]]. |
- | + | ||
- | Pentru inceput: | + | |
- | - Logati-va pe ''fep8.grid.pub.ro'' folosind contul de pe ''curs.upb.ro'' | + | |
- | - Executați comanda: | + | |
- | <code>wget -O lab7_skl.tar.gz http://ocw.cs.pub.ro/courses/_media/asc/lab7/lab7_skl.tar.gz</code> | + | |
- | - Dezarhivati folosind comanda ''tar -xzvf lab7_skl.tar.gz'' | + | |
- | + | ||
- | <note tip> | + | |
- | Debug aplicatii CUDA [[https://docs.nvidia.com/cuda/cuda-gdb/index.html#introduction|aici]] | + | |
- | </note> | + | |
- | + | ||
- | Modificarile se vor face acolo unde este necesar in ''task_<i>.cu'' unde ''<i>'' este numarul taskului. Urmariti indicatiile ''TODO'' din cod. De asemenea, va recomandam sa folositi documentatia oficiala CUDA Toolkit Documentation de la adresa: https://docs.nvidia.com/cuda/. Aici veti gasi informatii despre majoritatea functiilor de care aveti nevoie (folositi functia search). | + | |
- | + | ||
- | **Task 1** - Rulați task1 ca exemplu pentru a verifica funcționalitatea CUDA pe GPU | + | |
- | + | ||
- | **Task 2** - Rulați task2 ca exemplu pentru efectuarea unor operații pe GPU | + | |
- | + | ||
- | **Task 4** - Efectuați adunarea a doi vectori folosind CUDA în task4.cu | + | |
- | * Sugestia este de a face intai taskul 4 si apoi taskul 3 pentru ca are sens dpdv logic - e mai usor de inteles ce se intampla. | + | |
- | + | ||
- | **Task 3** - Urmăriți TODO--uri din taks3.cu | + | |
- | * Listați informații despre device-urile existente și selectați primul device | + | |
- | * Completați și rulați kernelul kernel_parity_id | + | |
- | * Completați și rulați kernelul kernel_block_id; explicați rezultatul | + | |
- | * Completați și rulați kernelul kernel_thread_id; explicați rezultatul | + | |
- | + | ||
- | **Task 5** - Urmăriți instrucțiunile din task5.cu pentru a realiza interschimbarea a doi vectori | + | |
- | + | ||
- | <note important> | + | |
- | Recomandăm sa folosiți pentru compilarea și rularea task-urilor ''sbatch'' sau Makefile_Cluster | + | |
- | </note> | + | |
===== Resurse ===== | ===== Resurse ===== | ||
- | |||
- | {{:asc:lab7:lab7_skl.tar.gz|Schelet Laborator 7}} | ||
<hidden> | <hidden> | ||
Line 575: | Line 377: | ||
</hidden> | </hidden> | ||
- | {{:asc:lab7:asc_lab7.pdf|Enunt Laborator 7}} | + | {{:asc:lab7:asc_lab7.pdf|Enunt Laborator 4}} |
- | * Responsabili laborator: Grigore Lupescu, Ștefan-Dan Ciocîrlan, Costin Carabaș | + | * Responsabili laborator: Costin Carabaș, Tudor Calafeteanu, Grigore Lupescu, Mihnea Mitroi, Irinel Gul, Alex Bala |
==== Referinte ==== | ==== Referinte ==== | ||
Line 591: | Line 393: | ||
* Advanced CUDA | * Advanced CUDA | ||
* [[https://developer.download.nvidia.com/CUDA/training/StreamsAndConcurrencyWebinar.pdf|CUDA Streams]] | * [[https://developer.download.nvidia.com/CUDA/training/StreamsAndConcurrencyWebinar.pdf|CUDA Streams]] | ||
- | |||
- | * Extra | ||
* [[http://www-personal.umich.edu/~smeyer/cuda/grid.pdf | CUDA Thread Basics]] | * [[http://www-personal.umich.edu/~smeyer/cuda/grid.pdf | CUDA Thread Basics]] | ||
* [[https://devblogs.nvidia.com/even-easier-introduction-cuda/ | An Even Easier Introduction to CUDA]] | * [[https://devblogs.nvidia.com/even-easier-introduction-cuda/ | An Even Easier Introduction to CUDA]] | ||