Skip to content
Snippets Groups Projects
Verified Commit f9d21054 authored by Michaël El Kharroubi's avatar Michaël El Kharroubi :satellite:
Browse files

Nvidia STL ok

parent 9b4d4f28
No related branches found
No related tags found
No related merge requests found
......@@ -21,8 +21,8 @@
#slide(
title: "Contenu",
)[
Maintenant que nous avons les bases nous allons voir comment paralléliser notre
code avec le kit HPC de Nvidia.
Maintenant que nous avons les bases, nous allons voir comment paralléliser notre
code avec le kit HPC de Nvidia
]
#new-section-slide("Le SDK HPC de Nvidia")
......@@ -38,7 +38,7 @@
- des librairies de communication (ex : OpenMPI)
En résumé, un grand nombre d'outils pour réaliser une application HPC (basé sur
du matériel Nvidia majoritairement).
du matériel Nvidia majoritairement)
#figure(
image("assets/hpc-sdk_content.png"),
......@@ -49,9 +49,9 @@
#slide(
title: "Le compilateur nvc++",
)[
Dans le cadre de ce cours, nous allons nous concentrer sur le compilateur nvc++.
Dans le cadre de ce cours, nous allons nous concentrer sur le compilateur nvc++
Il permet du compiler du C, C++ ou CUDA.
Il permet du compiler du C, C++ ou CUDA
Ce qui va nous intéresser particulièrement, c'est son support des _Parallel Algorithms_ introduits
avec C++17
......@@ -64,7 +64,7 @@
)[
Depuis C++17, les algorithmes de la STL peuvent prendre en paramètre une
politique d'exécution. Cette politique permet d'indiquer au compilateur comment
paralléliser le traitement des données.
paralléliser le traitement des données
On retrouve 4 politiques :
#box(
......@@ -108,7 +108,7 @@ std::cout << is_sorted << std::endl;
title: "Compiler avec nvc++",
)[
Une fois notre code écrit, il faut le compiler avec nvc++ en indiquant comment
le paralléliser.
le paralléliser
```console
nvc++ -std=c++20 -stdpar=gpu -O3 parallel_sort.cpp -o parallel_sort
......@@ -124,20 +124,21 @@ Nous avons trois paramètres principaux :
#slide(
title: "Les types de parallélisation disponibles",
)[
Le compilateur nvc++ permet de paralléliser son code sur CPU ou sur GPU.
Le compilateur nvc++ permet de paralléliser son code sur CPU ou sur GPU avec le
framework Thrust de Nvidia
Le paramètre `stdpar` prend 2 valeurs :
Le paramètre `stdpar` peut prendre 2 valeurs :
#box(
columns(
2,
gutter: 22pt,
)[
== multicore
Le code est parallélisé sur CPU avec la framework Thrust de Nvidia.
Le code est parallélisé sur un CPU multicore
#colbreak()
== gpu
Le code est parallélisé sur GPU avec la framework Thrust de Nvidia. Nécessite un
GPU Nvidia avec une architecture Pascal (ex: GTX 1080) ou plus récent.
Le code est parallélisé sur GPU. Nécessite un GPU Nvidia avec une architecture
Pascal (ex: GTX 1080) ou plus récent
],
)
]
......@@ -149,15 +150,15 @@ Le paramètre `stdpar` prend 2 valeurs :
#slide(
title: "Communiquer des données au GPU",
)[
Pour rappel, le GPU et CPU ont deux espaces d'adressage distincs. On ne peut
Pour rappel, le GPU et CPU ont deux espaces d'adressage distincts. On ne peut
donc pas directement accéder à des données qui se trouve sur la ram de l'_Host_
depuis le _Device_.
depuis le _Device_
Quand on passe simplement un itérateur à un algorithme STL, il n'y a rien besoin
de faire. Le compilateur va gérer l'allocation, la copie et la libération des
données sur le device.
Quand on passe en paramètre un itérateur à un algorithme STL, il n'y a rien
besoin de faire. Le compilateur va gérer l'allocation, la copie et la libération
des données sur le device
Mais comment faire pour capturer un vecteur par exemple?
Mais comment faire pour capturer un vecteur par exemple ?
]
#slide(title: "Exemple d'accès illégal")[
......@@ -177,11 +178,11 @@ std::for_each(std::execution::par_unseq,
```
Ce code provoque un warning à la compilation et une erreur
`cudaErrorIllegalAddress` à l'exécution.
`cudaErrorIllegalAddress` à l'exécution
]
#slide(title: "Solution")[
Pour régler ce problème, il suffit de capturer la mémoire par copie.
Pour régler ce problème, il suffit de capturer la mémoire par copie
```cpp
std::vector<int> v = {6, 3, 4, 12, 1, 15};
......@@ -202,15 +203,17 @@ std::for_each(std::execution::par_unseq,
#slide(
title: "Le compilateur ne peut pas tout copier",
)[
Attardons nous sur cet extrait de code `[device_v = v.data(), cst]`
Attardons nous sur cet extrait de code "`[device_v = v.data(), cst]`"
Le compilateur ne va pas simplement copier le pointeur `v.data()`, il va
remonter à l'allocation mémoire de la zone pointée et va s'occuper de la rendre
accessible depuis le device.
accessible depuis le device
Par conséquent, il n'est pas possible d'utiliser de la mémoire allouée par du
code qui n'aurait pas été compilé par nvc++ (ex: une librairie paratagée comme
OpenCV).
OpenCV)
#v(20%)
Le compilateur s'appuie principalement sur la CUDA Unified memory. Pour plus
d'information à ce sujet, je vous recommande ce billet de blog :
......@@ -220,18 +223,18 @@ d'information à ce sujet, je vous recommande ce billet de blog :
#new-section-slide("Le futur avec C++23 (views et mdspans)")
#slide(
title: "",
title: "Le futur avec C++23",
)[
La prochaine étape majeure dans ce paradigme apparaît avec C++23. Depuis C++ 20,
les spans et les views ont fait leur apparition.
les spans et les views ont fait leur apparition
Les views sont une forme d'itérateurs à évaluation paresseuse.
Les views sont une forme d'itérateurs à évaluation paresseuse
Dans C++23, on voit apparaître de nouvelles méthodes pour combiner les views
comme par exemple le produit cartésien pour générer les indices d'une matrice.
comme par exemple le produit cartésien pour générer les indices d'une matrice
Et la grande nouveauté, les mdspans qui permettent de gérer des structures de
données multidimensionnelles.
données multidimensionnelles
]
#new-section-slide("Exemple de code C++23 et notions à retenir")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment