Calcul Parallele
Calcul Parallele
Mars 2025
1 / 488
Généralités autour du calcul parallèle
Mars 2025
2 / 488
Introduction au calcul parallèle - Contexte et motivations
Calcul parallèle ?
Pour quoi faire ?
Comment ?
Quels modèles, quels langages ?
…
Introduction
Les bases, le vocabulaire, les concepts, les
pistes pour aller plus loin, une approche
pratique d’OpenMP et MPI.
3 / 488
Introduction au calcul parallèle - Contexte et motivations
Calcul parallèle ?
Pour quoi faire ?
Comment ?
Quels modèles, quels langages ?
…
Introduction
Les bases, le vocabulaire, les concepts, les
pistes pour aller plus loin, une approche
pratique d’OpenMP et MPI.
Notre but (souhait …)
Concrétiser pour vous ce qu’est le “calcul parallèle”, vous donner les bases et les
pistes pour approfondir et appliquer cela à vos codes.
Vous apprendre à utiliser les ressources en calcul à Grenoble .
3 / 488
Avant de commencer, un peu de contexte ...
4 / 488
Pourquoi ce cours?
Un module :
Introduction au calcul parallèle
... dans un ensemble de formations transverses proposées par le collège doctoral, le bloc
outils numériques et méthodologie pour la recherche.
en partenariat avec et
5 / 488
L’UAR GRICAD - GRenoble Infra CAlcul et Données
Unité multi-tutelles (CNRS, UGA, GINP, INRIA) d’Appui à la Recherche
Missions:
• Accompagnement/conseils aux chercheurs sur les besoins liés au calcul et aux
données
• Mise à disposition d’infrastructures avancées et mutualisées pour le calcul
intensif et l’exploitation des données de la recherche
• Participation aux infrastructures généralistes du site : hébergement, stockage et
virtualisation
• Interaction forte avec les laboratoires
• 2ème étage du batiment IMAG.
• https:// gricad.univ-grenoble-alpes.fr/
• Contact : [email protected]
6 / 488
Les services proposés par GriCAD
7 / 488
Maison de la Modélisation et de la Simulation
Nanosciences et Environnement
8 / 488
Formations transverses CED - Outils pour le traitement de
données, le développement logiciel et le calcul scientifique
9 / 488
Formations transverses CED - D’autres formations qui
peuvent vous intéresser
10 / 488
Contexte et présentation du module
Notre point de départ : une application, un code de calcul, fonctionnel et optimisé , qui
tourne en séquentiel .
Calcul séquentiel :
• exécution d’instructions étape par étape,
• que les opérations soient indépendantes ou non,
• a priori sur une seule ressource.
11 / 488
Contexte et présentation du module
Mais …
• Ce code a atteint ses limites de performances ?
• trop coûteux (Temps de calcul, mémoire ...),
• les volumes de données à traiter sont trop importants, trop longs à écrire,
• les performances sont moins bonnes que sur des machines plus vieilles, …
• Volonté ou nécessité d’exploiter de nouvelles ressources ?
• mutualisation de ressources (cluster …),
• problématique du coût financier et/ou environnemental (conso électrique etc),
Bref votre code n’est plus adapté aux nouvelles ressources et/ou ses performances ne
sont pas satisfaisantes.
Quelles solutions ? ⇒ HPC et calcul parallèle .
12 / 488
Contexte et présentation du module
13 / 488
Contexte et présentation du module
14 / 488
Contexte et présentation du module
15 / 488
Contexte et présentation du module
16 / 488
Contexte et présentation du module
Organisation de la séance
Pourquoi ?
2 Avant de paralléliser : connaitre et comprendre les ressources
18 / 488
Contexte et présentation du module
Infos pratiques
19 / 488
Contexte et présentation du module
Tour de table
21 / 488
Avant de paralléliser : connaitre et comprendre les ressources
4 Impact environnemental
1 Contexte et présentation du module
5 Les modèles de programmation
parallèle
2 Avant de paralléliser : connaitre et
comprendre les ressources
6 Comment paralléliser ?
3 Quelles architectures aujourd’hui ?
7 Conclusion
22 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Comment paralléliser ?
Première étape indispensable : connaître et comprendre les ressources, les architectures.
Architecture, hardware, ressources
24 / 488
Avant de paralléliser : connaitre et comprendre les ressources
L’objectif
Connaître les éléments d’un supercalculateur
27 / 488
Avant de paralléliser : connaitre et comprendre les ressources
L’objectif
Connaître les éléments d’un supercalculateur
28 / 488
Avant de paralléliser : connaitre et comprendre les ressources
L’objectif
Connaître les éléments d’un supercalculateur
29 / 488
Avant de paralléliser : connaitre et comprendre les ressources
L’objectif
Connaître les éléments d’un supercalculateur
30 / 488
Avant de paralléliser : connaitre et comprendre les ressources
L’objectif
Connaître les éléments d’un supercalculateur
31 / 488
Avant de paralléliser : connaitre et comprendre les ressources
L’objectif
Connaître les éléments d’un supercalculateur
32 / 488
Avant de paralléliser : connaitre et comprendre les ressources
L’objectif
Connaître les éléments d’un supercalculateur
33 / 488
Avant de paralléliser : connaitre et comprendre les ressources
37 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Pour résumer
38 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Pour résumer
Si on veut aller plus loin
le cœur inclus beaucoup de mécanismes d’optimisation complexes :
• Pipelining, processeur superscalaire : pour pouvoir traiter plusieurs choses en
même temps.
• Exécution spéculative, prédiction de branchement : pour prendre de l’avance sur les
instructions du programme.
• Hyperthreading : deux processeurs logiques sur une seule puce, permettant
d’utiliser au mieux les ressources du processeur.
• Instructions vectorielles : le processeur, en fonction de son jeu d’instructions, est
capable d’appliquer la même instruction simultanément à plusieurs données (SSE,
AVX).
39 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Travail du processeur :
for i=1,n
load x[i] to the floating−point register
calculate the square root
Algorithme : write the result from the register to memory
for i=1,n
x[i] = sqrt (x[i]) Avec SSE :
for {i1,i2,i3,i4} in {1:n}
load x[i1],x[i2],x[i3],x[i4] to the SSE register
calculate 4 square roots in one operation
write the result from the register to memory
Conclusion : hardware mais à garder en tête pour optimisations
40 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Il existe différents types de mémoires qui se distinguent par leur capacité, leur rapidité,
leur prix, leur technologie, la manière d’y accéder, …
• Les registres: Extrêmement rapides, ils fonctionnent à la vitesse des CPU mais
leur capacité est minimale (qq Ko)
• La mémoire cache (L1, L2, L3) : très rapides et mettent à disposition du CPU les
copies de quelques données et instructions prise dans la mémoire centrale (qq Ko
∼ qq 100aines Mo). Le cache L1 est le plus rapide mais de taille plus restreinte.
• La RAM/mémoire centrale: vitesse de réaction très lente. Les données y sont
lues par bloc et mis à portée de main du CPU grâce à la mémoire cache (Qq Go∼
1 à 2 To)
• Mémoire de masse : les disques, les bandes magnétiques (Qq To)
42 / 488
Avant de paralléliser : connaitre et comprendre les ressources
43 / 488
Avant de paralléliser : connaitre et comprendre les ressources
:
sum=sum+vec(i)
end do
accès fréquent
end subroutine
>cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 79
model name : Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
...
• Taille de la RAM
>free -m
total used free shared buff/cache available
Mem: 128850 1945 11592 4 10980 125861 46 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Du processeur au nœud
• Nouvelles problématiques :
• Complexification de l’accès à la mémoire
• Présence d’accélérateur (GPU), et question des flux de données entre CPU et GPU
47 / 488
Avant de paralléliser : connaitre et comprendre les ressources
48 / 488
Avant de paralléliser : connaitre et comprendre les ressources
49 / 488
Avant de paralléliser : connaitre et comprendre les ressources
50 / 488
Avant de paralléliser : connaitre et comprendre les ressources
51 / 488
Avant de paralléliser : connaitre et comprendre les ressources
La gestion des IO est rendue possible par l’utilisation d’un système de fichiers
53 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Système de fichiers
Rôles:
• Organiser le stockage des données sur un support physique
• Gérer l’espace de nommage et les attributs
Types d’information traitées:
• Données: contenu des fichiers
• Méta-données: ensemble d’informations sur le fichier : nom, position du fichier sur
le support physique, taille, attributs (propriétaire, groupe, …)
• Journal: enregistrement des opérations avant leur exécution pour assurer la
cohérence en cas de crash (coupure d’alimentation par exemple).
54 / 488
Avant de paralléliser : connaitre et comprendre les ressources
56 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Les accès aléatoires ou concurrents sur des petits blocks peuvent poser problème!
• Gestion des “locks” (Conflits d’accès sur la même portion de fichier).
• Préférer les écritures et lectures séquentielles.
57 / 488
Avant de paralléliser : connaitre et comprendre les ressources
Résumé
• Cœur : ressource qui fournit la puissance de
calcul.
• Processeur/CPU : composé d’un ou de
plusieurs cœurs.
• Mémoire : organisée de façon hiérarchique.
• Nœud : ressource contenant plusieurs
processeurs qui partagent une même
mémoire (NUMA).
• Réseau rapide infiniband, Omnipath,…:
technologie qui relie les nœuds stockés dans
des racks.
• Filesystem : entrées / sorties sur disques.
58 / 488
Quelles architectures aujourd’hui ?
4 Impact environnemental
1 Contexte et présentation du module
5 Les modèles de programmation
parallèle
2 Avant de paralléliser : connaitre et
comprendre les ressources
6 Comment paralléliser ?
3 Quelles architectures aujourd’hui ?
7 Conclusion
59 / 488
Quelles architectures aujourd’hui ?
61 / 488
Quelles architectures aujourd’hui ?
Un espace mémoire global, accessible simultanément par plusieurs CPUs et donc par
plusieurs programmes.
• Tous les CPUs accèdent à toute la mémoire
globale, avec un même espace d’adressage.
Chaque CPU est autonome mais les
modifications effectuées dans la mémoire
partagée sont visibles par tous.
• Les processeurs ont leur propre mémoire locale
(cache, …) dans laquelle sera copiée une partie
de la mémoire globale.
62 / 488
Quelles architectures aujourd’hui ?
Quelques remarques pour anticiper les points forts et faibles des modèles de
programmation basés sur ce type de système.
• Accès rapides à la mémoire et partage des données
• Accès concurrents , risque d’embouteillage
• Cohérence des caches ? (Voir ci-après) répercution des écritures faites par un
processeur dans son cache vers les autres processeurs.
• Limites de ces systèmes = taille de la mémoire et nombre de CPUs disponibles.
Parallélisme sur un seul noeud !
63 / 488
Quelles architectures aujourd’hui ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Cohérence de cache
Comment est gérée la cohérence de données modifiées par plusieurs processeurs ?
Principe de localité : si une donnée (zone mémoire) est utilisée, elle a des chances
d’être référencée à nouveau dans un futur proche ( localité temporelle ) et les zones
voisines ont des chances d’être également utilisées ( localité spatiale ).
False sharing
False sharing : dégradation des performances due à la gestion de la cohérence des
caches.
66 / 488
Quelles architectures aujourd’hui ?
False sharing
False sharing : dégradation des performances due à la gestion de la cohérence des
caches.
66 / 488
Quelles architectures aujourd’hui ?
False sharing
False sharing : dégradation des performances due à la gestion de la cohérence des
caches.
66 / 488
Quelles architectures aujourd’hui ?
False sharing
False sharing : dégradation des performances due à la gestion de la cohérence des
caches.
66 / 488
Quelles architectures aujourd’hui ?
False sharing
False sharing : dégradation des performances due à la gestion de la cohérence des
caches.
66 / 488
Quelles architectures aujourd’hui ?
Comparaisons …
68 / 488
Quelles architectures aujourd’hui ?
Comparaisons …
Taille et coût du système ?
Mémoire partagée Mémoire distribuée
• Très coûteux de • Accès à plus de ressources. La mémoire totale disponible
construire des peut augmenter proportionnellement avec le nombre de
architectures à processeurs.
mémoire partagée • Coût réduit, plus facile à construire
avec beaucoup de • Les procs opèrent indépendamment les uns des autres.
CPUs
Programmation plus complexe : risques d’erreurs,
complexité des algorithmes, gestion des données
distribuées …
• Les performances vont fortement dépendre du réseau
d’interconnexion (potentiellement coûteux).
69 / 488
Quelles architectures aujourd’hui ?
Accélérateurs
Principe : chargement d’une partie du programme sur un support (co-processeur,
device) spécialisé, capable de traiter plus efficacement la partie ciblée. On parlera
d”’offloading” entre le CPU (host) et l’accélérateur (device).
GPUs, Graphics Processing Unit
A noter que ce type d’infrastructure est très utilisé pour le machine learning et le deep
learning.
70 / 488
Quelles architectures aujourd’hui ?
72 / 488
Quelles architectures aujourd’hui ?
73 / 488
Quelles architectures aujourd’hui ?
Quelques commentaires
• Sortie du classement du
numéro 1 : ≈ 8 ans.
• Complexité croissante
(manycores, machines
hétérogènes deviennent
majoritaires …).
• Consommation énergétique
(très !) conséquente.
74 / 488
Quelles architectures aujourd’hui ?
Exemple
Une machine de l’IDRIS : Jean Zay
• Machine dite convergée : noeuds hybrides CPU - GPU
• A la fois pour le HPC et le Deep Learning
• Performance crête : 126 PFLop/s (extension avril 2024)
75 / 488
Impact environnemental
4 Impact environnemental
1 Contexte et présentation du module
5 Les modèles de programmation
parallèle
2 Avant de paralléliser : connaitre et
comprendre les ressources
6 Comment paralléliser ?
3 Quelles architectures aujourd’hui ?
7 Conclusion
76 / 488
Impact environnemental
Température observée
Facteurs humains + naturels (simu)
Facteurs naturels seulement (simu)
scénario
RCP 8.5
Impact environnemental
2’
Neutralité carbone en
2050 en France :
~2 t CO2eq. / pers. / an
Neutralité carbone d’ici 2050 : 2t CO2eq. / pers. / an Bilan des gaz à effet de serre (BGES) médian des labos en 2019 :
Le service public doit faire sa part 6,6 t CO2eq. / agent / an
Empreinte individuelle sur https://nosgestesclimat.fr/ 1155 laboratoires en France utilisateurs de GES1point5 (avril 2024)
Impact environnemental
1’
(8 kT de CO2e)
Émission (8 Mt CO2eq.)
30 minutes de Émission (15 Gt CO2eq.)
1 steak haché annuelle Émission
≈ 10 zoom (caméra annuelle d'un Émissions des
(160g) moyenne d'un annuelle
ouverte) bateau pays de l'OCDE
français d'Easy Jet
porte-conteneur
Etes vous capables de répondre à la question ”Est-ce que les résultats de nos
recherches participent à la construction d’un monde qui correspond à nos valeurs ?”
79 / 488
Impact environnemental
80 / 488
Impact environnemental
81 / 488
Impact environnemental
82 / 488
Impact environnemental
83 / 488
Impact environnemental
84 / 488
Impact environnemental
85 / 488
Les modèles de programmation parallèle
4 Impact environnemental
1 Contexte et présentation du module
5 Les modèles de programmation
parallèle
2 Avant de paralléliser : connaitre et
comprendre les ressources
6 Comment paralléliser ?
3 Quelles architectures aujourd’hui ?
7 Conclusion
86 / 488
Les modèles de programmation parallèle
Comment paralléliser?
87 / 488
Les modèles de programmation parallèle
88 / 488
Les modèles de programmation parallèle
89 / 488
Les modèles de programmation parallèle
89 / 488
Les modèles de programmation parallèle
90 / 488
Les modèles de programmation parallèle
Quelques références.
MPI (Message Passing Interface). Voir cours plus loin.
OpenMP (Open Multi-Processing). Voir cours plus loin.
OpenACC (Open Accelerators, https:// www.openacc.org),
OpenCL (Open Computing language, https:// www.khronos.org/ opencl/ ) :
standards conçus pour le calcul parallèle sur systèmes hétérogènes (avec accélérateurs).
Cuda. Voir cours plus loin.
91 / 488
Comment paralléliser ?
4 Impact environnemental
1 Contexte et présentation du module
5 Les modèles de programmation
parallèle
2 Avant de paralléliser : connaitre et
comprendre les ressources
6 Comment paralléliser ?
3 Quelles architectures aujourd’hui ?
7 Conclusion
92 / 488
Comment paralléliser ?
93 / 488
Comment paralléliser ?
Speedup
Un premier indicateur de performance : la comparaison des temps d’exécution.
Soit Tref un temps de référence et Tp le temps de calcul sur l’architecture à évaluer. On
définit l’accélération relative (speedup) comme :
Tref
S=
Tp
Remarques :
• S et Tp vont bien entendu dépendre des ressources impliquées, par exemple du
nombre de coeurs utilisés.
• Tref n’est pas nécessairement le temps en séquentiel. On peut vouloir par exemple
obtenir l’accélération d’un calcul sur un GPU, relativement au même calcul sur
plusieurs CPUs.
95 / 488
Comment paralléliser ?
Speedup
A retenir :
quels que soient les efforts, le speedup est toujours limité par la partie de code
non parallélisable
Voir le cours sur le profiling (des sources à l’exécutable) pour identifier les parties
coûteuses.
96 / 488
Comment paralléliser ?
Efficacité
On définit l’efficacité comme le rapport entre l’accélération globale (le speedup) et celle
de la partie optimisée (la fraction de code parallélisable).
S(n)
efficiency =
n
L’efficacité fournit une sorte de rendement du calcul parallèle : une valeur de 1 signifie
que 100% des ressources ont été utilisées pour du calcul utile.
En général :
0 ≤ Speedup(n) ≤ n, 0 ≤ Efficacite ≤ 1
Cas particuliers
• speedup/efficacité lineaire : e = 1, S(n) = n
• superlinear speedup/efficiency : e > 1, S(n) > n.
Une explication possible : effets de cache. Plus de ressources ⇒ plus de données
stockées dans des mémoires rapides.
97 / 488
Comment paralléliser ?
Scaling
Tref (N)
Ŝ(n) =
Tp (n, n ∗ N)
Si Ŝ(n) est proche de 1, alors le code est apte à gérer la montée en charge. On parlera de
scalability : capacité du système à traiter un volume de travail croissant lorsqu’on augmente
les ressources.
99 / 488
Comment paralléliser ?
Intensité arithmétique
La majorité des applications scientifiques sont
dominées par des opérations d’arithmétique flottante .
Intensité arithmétique - IA
Prend aussi en considération les accès mémoire : ratio entre le nombre d’opérations
sur les nombre flottants (FLOPS) et le volume de données transférées (en Bytes)
pendant l’exécution [FLOPS/Byte].
IA = #FLOP / #Bytes
Rappel : l’accès aux données, leurs déplacements en mémoire est coûteux. Une
IA élevée signifie une utilisation optimale des données du point de vue du coût en
mémoire.
100 / 488
Comment paralléliser ?
return sum;
}
3n2
= O(n).
102 / 488
Conclusion
4 Impact environnemental
1 Contexte et présentation du module
5 Les modèles de programmation
parallèle
2 Avant de paralléliser : connaitre et
comprendre les ressources
6 Comment paralléliser ?
3 Quelles architectures aujourd’hui ?
7 Conclusion
103 / 488
Conclusion
105 / 488
Conclusion
106 / 488
Calcul et contexte grenoblois
Mars 2025
107 / 488
Accès et utilisation des ressources grenobloises
1 Contexte européen
Généralités
Les centres nationaux
Les projets régionaux
Les ressources locales
2 Accès aux plateformes de calcul et leur utilisation
Présentation des ressources locales
Présentation des espaces de stockage
Gestion de l’environnement logiciel
Gestion des jobs sur les plateformes
Conclusions
108 / 488
Contexte européen
109 / 488
Contexte européen Généralités
110 / 488
Contexte européen Généralités
Nombreuses thématiques
Pyramide du calcul intensif:
• Autour de la recherche
fondamentale,
• Autour de la recherche appliquée
112 / 488
Contexte européen Les centres nationaux
• PRACE
• EOSC
• Ces projets ont pour mission de structurer les offres autour du HPC (matériels,
formations, solutions logicielles, etc ...) : listes de diffusion
114 / 488
Contexte européen Les projets régionaux
115 / 488
Contexte européen Les projets régionaux
116 / 488
Contexte européen Les ressources locales
117 / 488
Contexte européen Les ressources locales
118 / 488
Contexte européen Les ressources locales
119 / 488
Accès aux plateformes de calcul et leur utilisation
120 / 488
Accès aux plateformes de calcul et leur utilisation Présentation des ressources locales
121 / 488
Accès aux plateformes de calcul et leur utilisation Présentation des ressources locales
Plateforme Dahu
Particulièrement adaptée au calcul parallèle
• Machine mise en production en décembre 2018
• Adaptée au calcul parallèle
• Évolutive par ajout de nœuds
• 11696 coeurs pour environ 39To de mémoire
• 4192 Xeon SKL Gold 6130 @ 2.10GHz
• 2048 Xeon SKL Gold 5218 @ 2.30GHz
• 432 Xeon SKL Gold 6126 @ 2.60GHz
• 256 Xeon SKL Gold 6244 @ 3.60GHz
• 64 Xeon SKL Silver 4216 @ 2.1GHz
• Réseau Omnipath 100Gb
Supercalculateur: Système informatique très puissant utiliser pour des applications
scientifiques complexes (calculs numériques intensifs)
122 / 488
Accès aux plateformes de calcul et leur utilisation Présentation des ressources locales
La prochaine machine...
Définition technique :
• 10000 cœurs de calculs avec AMD GENOA 96 cœurs
• Nœuds à 2 cpus, 192 cœurs, 768 Go, 10% de nœuds avec 1,5To
• Mellanox à 200Gb/s (1 seul switch)
• GPUs H100
• Stockage : /bettik workdir + beegfs scratch full flash NVME 100To
124 / 488
Accès aux plateformes de calcul et leur utilisation Présentation des ressources locales
127 / 488
Accès aux plateformes de calcul et leur utilisation Présentation des espaces de stockage
Quels sont les différents espaces de stockage ? Pour quel usage ? Et où stocker mes
données et résultats ?
Les différents types d’espaces de stockage
• Stockage local : les partitions locales sur les disques de chaque noeud de calcul.
Accessible uniquement sur le noeud.
• Stockage cloud : plateforme Mantis
• Stockage distribué : points de montages, accessibles par tous les noeuds de
calcul.
128 / 488
Accès aux plateformes de calcul et leur utilisation Présentation des espaces de stockage
Stockage cloud
• plateforme Mantis
• accessible via iRODS ou webDav (default quota 1To/user).
• pour les jobs grilles notamment.
129 / 488
Accès aux plateformes de calcul et leur utilisation Présentation des espaces de stockage
130 / 488
Accès aux plateformes de calcul et leur utilisation Présentation des espaces de stockage
131 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
132 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
133 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
Intérêts
135 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
Reproductible ?
• L’environnement de base est (presque) vide
• On contrôle la version des logiciels installés et celle des dépendances
• Les anciens paquets restent disponibles même si il y a des nouvelles versions qui
sont ajoutées
• A l’installation, on peut préciser la version exacte souhaitée
• Un fichier de conf (manifest Guix ...) où tout est stocké (nom et numéro de
version de tous les logiciels installés ...)
136 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
Nix
• Sorti en 2003
• Projet OpenSource
• NixOS
• Spécificités
• Paquets écrits en langage fonctionnel nix
(https:// nixos.wiki/ wiki/ Nix_Expression_Language)
• Documentation un peu dense
• Peut gérer des logiciels non-libres
• Importants nombre de paquets disponibles (+ 80 000 actuellement)
• Disponible sous Linux et MacOS
137 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
Guix
• 2012
• Intégré au projet GNU (logiciel libre)
• GuixOS
• Initiative Guix-HPC (https:// hpc.guix.info/ )
• Spécificité
• Paquets écrits en langage fonctionnel GNU/Guile
• Ne propose que des logiciels libres
• Dépôt plus réduit (≈21 000 paquets)
• Disponible sous Linux
138 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
Caractéristiques communes
• Dépôt centralisé de paquets (store : /nix/store et /gnu/store)
• Chaque paquet a plusieurs versions qui peuvent être installées et désinstallées
indépendemment (avec les dépendances)
• L’installation d’un logiciel est en fait une création de liens symboliques vers une
installation centralisée
• Permet à un développeur de packager et de distribuer son logiciel
139 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
Nix et Guix
140 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
name: gcc
version: 11.2.0
outputs: out lib debug
systems: x86_64-linux i686-linux
dependencies: [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
location: gnu/packages/gcc.scm:625:2
homepage: https://gcc.gnu.org/
license: GPL 3+
synopsis: GNU Compiler Collection
description: GCC is the GNU Compiler Collection. It provides compiler front-ends for several languages, including C, C++, Objective-C,
+ Fortran, Ada, and Go. It also includes runtime support libraries for these languages.
relevance: 27 141 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
Activation du profil
#f-dahu%:refresh_guix ced2023
Activate profile /var/guix/profiles/per-user/cacar/ced2023
The following packages are currently installed in /var/guix/profiles/per-user/cacar/ced2023:
gcc-toolchain 10.3.0 out /gnu/store/bxh206gz379wkn8cvb2ghlkvpqgwfd2v-gcc-toolchain-
142 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
• Une alternative plus légère pour gérer des environnement type Conda
• Un gestionnaire d’environnement incontournable (nombreux exemples, tutoriels
d’utilisation basés sur des environnements conda)
• Courbe d’apprentissage assez directe
• La reproductibilité des environnements conda/mamba n’est pas toujours garantie
sur le long terme
143 / 488
Accès aux plateformes de calcul et leur utilisation Gestion de l’environnement logiciel
# Activer
source /applis/environments/mamba.sh
# Charger l'environnement choisi
micromamba activate mon_env
# Installer des paquets
micromamba install numpy
# Mieux : utiliser des fichiers de conf, voir TP
146 / 488
Accès aux plateformes de calcul et leur utilisation Gestion des jobs sur les plateformes
147 / 488
Accès aux plateformes de calcul et leur utilisation Gestion des jobs sur les plateformes
Rôle
• permet d’optimiser la gestion des ressources en classant les demandes / ressources
(scoring)
• fournit une interface de soumission, avec une demande de ressource
• attribue le job sur la ressource demandée lorsque celle-ci devient disponible de
façon exclusive
148 / 488
Accès aux plateformes de calcul et leur utilisation Gestion des jobs sur les plateformes
149 / 488
Accès aux plateformes de calcul et leur utilisation Gestion des jobs sur les plateformes
150 / 488
Accès aux plateformes de calcul et leur utilisation Gestion des jobs sur les plateformes
cacar@f-dahu:chandler
152 / 488
Accès aux plateformes de calcul et leur utilisation Gestion des jobs sur les plateformes
153 / 488
Accès aux plateformes de calcul et leur utilisation Gestion des jobs sur les plateformes
154 / 488
Accès aux plateformes de calcul et leur utilisation Conclusions
155 / 488
Accès aux plateformes de calcul et leur utilisation Conclusions
Utilisation
0. Documentation: https:// gricad-doc.univ-grenoble-alpes.fr
SOS: https:// gricad-doc.univ-grenoble-alpes.fr/ support/
1. Passerelles de connexion: Trinity, Rotule −→ Aucune activité !
2. Espaces de stockage: scratch(bettik, silenus), home, tmp, Mantis −→
Connaitre leurs usages!
3. Environnements de calcul : nix, guix, conda, singularity
4. Soumission de jobs (interactif, batch): OAR
156 / 488
Accès aux plateformes de calcul et leur utilisation Conclusions
158 / 488
Calcul en mémoire partagée - Introduction à OpenMP -
GPGPU
Mars 2025
159 / 488
Systèmes à mémoire partagée, rappels
Un espace mémoire global, accessible simultanément par plusieurs “coeurs”/unité de
calcul
• Tous les CPUs
accèdent à toute la mémoire globale ,
avec un même espace d’adressage.
• Chaque CPU est autonome et dispose
de sa propre mémoire locale
• Toute
modification dans la mémoire partagée
est vue par tous les CPUs.
160 / 488
Système à mémoire partagée, rappels
161 / 488
CPU et GPU
162 / 488
OpenMP
163 / 488
OpenMP Introduction et rappels
164 / 488
OpenMP Introduction et rappels
A propos d’OpenMP
OpenMP est une interface de programmation dédiée au calcul parallèle sur
architecture à mémoire partagée.
• Specs définies par un consortium
(http:// www.openmp.org/ specifications/ ).
• Membres permanents : AMD, ARM, Cavium, CRAY, Fujitsu, IBM, Intel, Micron,
NEC, NVIDIA, Oracle, Red Hat, Texas instruments.
• Multi-plateformes (Linux, OSX, Windows).
• Disponible pour C, C++, Fortran.
165 / 488
OpenMP Introduction et rappels
A propos d’OpenMP
Définition d’un langage et d’une bibliothèque de fonctions qui vont vous permettre
d’exploiter le parallélisme en mémoire partagée.
166 / 488
OpenMP Introduction et rappels
A propos d’OpenMP
En pratique
• Plusieurs versions de la norme , chacune apportant de nouvelles fonctionnalités.
• OpenMP 1.0 pour Fortran (1997) puis C/C++ (1998)
• ...
• OpenMP 4.0 (2013) : support accélérateurs, programmation SIMD, …
• OpenMP 5.2 (nov. 2021)
• Différentes implémentations , pour chaque version, selon le fournisseur du
compilateur.
OpenMP 4.5 pour GNU (>6.1), llvm, intel, …
Voir https:// www.openmp.org/ resources/ openmp-compilers-tools/ .
au compilateur choisi et à la version disponible ! Il peut y avoir une différence entre
la théorie, la norme et la réalité de ce qui est disponible/implémenté.
167 / 488
OpenMP Introduction et rappels
OpenMP
Une interface de programmation parallèle pour systèmes à mémoire partagée.
Principe : gestion de threads pouvant s’exécuter simultanément.
OpenMP
169 / 488
OpenMP Introduction et rappels
OpenMP
170 / 488
OpenMP Introduction et rappels
171 / 488
OpenMP Introduction et rappels
Résumons …
Fonctionnement d’un programme OpenMP
• Un thread “maître” au démarrage. Apparition/disparition (fork-join) de threads
“esclaves” au fil des régions séquentielles/parallèles.
• Chaque thread exécute sa séquence d’instructions, indépendamment des autres.
• Il a sa propre mémoire locale avec ses variables dites privées.
• Il accède à l’ensemble de la mémoire partagée et donc des variables partagées.
• L’ordre d’exécution des threads est défini par le système d’exploitation : il faut
s’assurer que l’accès aux variables partagées est correct : besoin éventuel de
synchronisations.
• Race condition : mauvaise gestion de l’accès aux données pouvant entrainer
des résultats variables d’une exécution à l’autre.
172 / 488
OpenMP Introduction et rappels
Elements de bibliographie
173 / 488
OpenMP Premiers pas avec OpenMP
174 / 488
OpenMP Premiers pas avec OpenMP
175 / 488
OpenMP Premiers pas avec OpenMP
175 / 488
OpenMP Premiers pas avec OpenMP
175 / 488
OpenMP Premiers pas avec OpenMP
• avec un pilotage par des variables d’environnement qui seront initialisées avant
l’exécution du programme. Les variables d’environnement OpenMP (ICV dans la
doc officielle) contrôleront l’exécution globale des régions parallèles. 175 / 488
OpenMP Premiers pas avec OpenMP
Directives OpenMP
OpenMP utilise des directives (pragmas) pour le compilateur/pré-processeur afin de
définir le comportement à l’exécution de certaines régions de code.
Syntaxe des directives :
sentinelle omp nom-directive [clause[ [,] clause] ... ]
• La “sentinelle” est la chaîne de caractères en début de ligne qui annonce une
instruction OpenMP :
!$omp en fortran / #pragma omp en C/C++ .
• Les clauses permettent de définir les options de la directive utilisée.
C/C++ Fortran
178 / 488
OpenMP Premiers pas avec OpenMP
180 / 488
OpenMP Premiers pas avec OpenMP
Rappel : pour une liste complète des directives, fonctions et variables d’environnement,
voir les aides mémoire OpenMP :
https:
// www.openmp.org/ wp-content/ uploads/ OpenMPRefGuide-5.2-Web-2024.pdf
181 / 488
OpenMP Premiers pas avec OpenMP
Compilation
182 / 488
OpenMP Premiers pas avec OpenMP
Execution
• Exécution : choix du nombre de threads à utiliser puis exécution.
export OMP_NUM_THREADS=4
./exemple
183 / 488
OpenMP Premiers pas avec OpenMP
Compilation conditionnelle
OpenMP : conçu de manière à permettre, pour un même code, une compilation et une
exécution correcte en parallèle ou en séquentiel.
compilation conditionnelle : écrivez votre code pour qu’il fonctionne dans tous les
cas
184 / 488
OpenMP Premiers pas avec OpenMP
Compilation conditionnelle
185 / 488
OpenMP Premiers pas avec OpenMP
Résumons …
186 / 488
OpenMP Régions parallèles
187 / 488
OpenMP Régions parallèles
Le rôle principal d’OpenMP est de partager une charge de travail , décrite dans un
programme, entre des threads. Deux approches principales pour gérer ce partage :
• La distribution de tâches autonomes sur plusieurs threads (≈ coarse-grain, task
parallelism).
• La parallélisation de boucles , (≈ fine-grain, data parallelism) distribution des
itérations entre les threads. On découpe et distribue une tâche (la boucle) sur
plusieurs threads.
188 / 488
OpenMP Régions parallèles
program parallel
implicit none
write(*,*) "Partie sequentielle"
!$OMP PARALLEL
write(*,*) "Hello"
!$OMP END PARALLEL
end program parallel
• Création implicite d’une tâche par thread.
• Dans la région parallèle, tous les threads exécutent la même portion de code .
• Pas d’ordre a priori.
• Synchronisation implicite en fin de région. 189 / 488
OpenMP Régions parallèles
On retrouvera cette construction (OMP DIRECTIVE ... OMP END DIRECTIVE) pour
la plupart des directives.
En C/C++, pas de ”end”, on utilisera les { } pour délimiter les portées des directives.
Par exemple
191 / 488
OpenMP Régions parallèles
Chaque thread recoit un numéro par lequel il sera identifié tout au long de l’exécution
du programme. Ce numéro est appelé “rang” , obtenu via la fonction :
192 / 488
OpenMP Régions parallèles
193 / 488
OpenMP Régions parallèles
Résumons …
196 / 488
OpenMP Régions parallèles
197 / 488
OpenMP Parallélisation des boucles
198 / 488
OpenMP Parallélisation des boucles
Parallélisation de boucles
Nous avons vu comment créer une région parallèle et faire exécuter une tâche par une
équipe de threads via la directive parallel .
199 / 488
OpenMP Parallélisation des boucles
Parallélisation de boucles
Cela consiste à :
• Définir une région parallèle contenant la ou les boucles, via la directive parallel
que nous avons déja vue,
• Puis à répartir les itérations de la boucle entre les threads en utilisant la directive
DO / for .
• Il est possible d’utiliser directement une seule directive
PARALLEL DO / parallel for , contraction des deux précédentes.
200 / 488
OpenMP Parallélisation des boucles
Remarque : à titre d’exemple, le nombre de threads est ici fixé explicitement, ce qui est en général à proscrire pour des
questions de portabilité , on préfèrera initialiser la variable d’environnement OMP_NUM_THREADS.
201 / 488
OpenMP Parallélisation des boucles
203 / 488
OpenMP Parallélisation des boucles
206 / 488
OpenMP Parallélisation des boucles
export OMP_CHEDULE="GUIDED,4"
207 / 488
OpenMP Parallélisation des boucles
208 / 488
OpenMP Parallélisation des boucles
209 / 488
OpenMP Parallélisation des boucles
Imbrications de boucles
Par défaut, la directive DO / for permet de paralléliser uniquement la boucle qui suit la
directive : dans cet exemple, seule la boucle externe est parallélisée.
210 / 488
OpenMP Parallélisation des boucles
Imbrications de boucles
Il est possible d’imbriquer les zones parallèles pour répartir les itérations des deux
boucles. Pour paralléliser une deuxième boucle interne à la première on crée une
deuxième zone parallèle (N’oubliez pas l’ICV OMP_NESTED !).
Notre exemple devient :
211 / 488
OpenMP Parallélisation des boucles
Il existe une autre solution, plus optimale, pour imbriquer des boucles : la clause
collapse(N) , N étant le nombre de boucles à paralléliser.
• Il s’agit de fusionner les boucles imbriquées et de répartir ensuite les itérations pour
potentiellement améliorer les performances
212 / 488
OpenMP Parallélisation des boucles
Résumons …
Parallélisation de boucles
• On insère les directives de parallélisation de boucles : PARALLEL DO / parallel for
• La répartition des itérations est paramétrable par l’utilisateur
• L’imbrication de boucles se fait soit par l’imbrication de régions parallèles ou par la
clause COLLAPSE plus optimale
213 / 488
OpenMP Gestion du statut des variables
214 / 488
OpenMP Gestion du statut des variables
Dans un programme Openmp, il est possible (et nécessaire !) de fixer le statut d’une
variable pour déterminer son appartenance à une zone ou une autre.
Ce statut (shared ou private) est un paramètre fondamental dans un programme
OpenMP. Il impactera les résultats (valeur des variables, race condition) les
performances (false sharing …)
• Par défaut les variables sont allouées dans la zone partagée par les threads.
• Une variable avec un statut privée sera allouée dans la pile du thread.
Le statut d’une variable est piloté via les clauses shared , private et les clauses
similaires pour une gestion plus fine du contenu de la variable : initialisation, transfert
shared/private etc.
216 / 488
OpenMP Gestion du statut des variables
217 / 488
OpenMP Gestion du statut des variables
217 / 488
OpenMP Gestion du statut des variables
217 / 488
OpenMP Gestion du statut des variables
Le même nom de variable dans le programme peut désigner deux zones mémoires
différentes.
Une variable privée n’est pas initialisée (contenu indéterminé !) à l’entrée de la zone
parallèle. Voir y dans l’exemple ci-dessus.
217 / 488
OpenMP Gestion du statut des variables
219 / 488
OpenMP Gestion du statut des variables
220 / 488
OpenMP Gestion du statut des variables
221 / 488
OpenMP Gestion du statut des variables
DEFAULT(arg) : impose un comportement par défaut pour le statut des variables, s’il
n’est pas explicite.
arg = (NONE|SHARED|PRIVATE|firstprivate) / (none|shared)
222 / 488
OpenMP Gestion du statut des variables
• L’influence (ou la portée) d’une région parallèle s’étend aussi bien au code contenu
lexicalement dans cette région (étendue statique), qu’au code des sous-programmes
appelés. L’union des deux représente l’étendue dynamique.
• Dans un sous-programme appelé dans une région parallèle, les variables locales et
tableaux automatiques sont implicitement privés à chaque tâche.
• Dans une procédure, toutes les variables transmises par argument héritent du statut
défini dans l’étendue lexicale (statique) de la région.
224 / 488
OpenMP Gestion du statut des variables
225 / 488
OpenMP Gestion du statut des variables
Réductions
#pragma omp parallel reduction(+:var1, var2) // opération '+', appliquée à var1 et var2
{
// var est initialisée localement à 0
change(var1, var2) // modifications locales
}
// en sortie, var1 = somme de sa valeur sur chaque thread. Idem pour var2.
s = 5 ; p = 32 ; r = 243
227 / 488
OpenMP Gestion du statut des variables
Résumons …
228 / 488
OpenMP Gestion du statut des variables
Exercices
229 / 488
OpenMP Autres directives de partage du travail
230 / 488
OpenMP Autres directives de partage du travail
Partage du travail
Nous avons vu jusqu’à présent une seule méthode de partage du travail, do / for . Il en
existe d’autres que nous allons passer en revue :
• Sections
• Single / Master
• Workshare (Fortran only !)
• Tasks (voir section suivante)
Chacune de ces construction :
• doit faire partie d’une région parallèle (et est donc associé à une équipe de threads),
• doit être “vue “ par tous les threads (ou aucun) de la région,
Les synchronisations dépendent de chaque directive.
231 / 488
OpenMP Autres directives de partage du travail
232 / 488
OpenMP Autres directives de partage du travail
233 / 488
OpenMP Autres directives de partage du travail
234 / 488
OpenMP Autres directives de partage du travail
235 / 488
OpenMP Autres directives de partage du travail
Fortran only !
• Rôle : permet la répartition du travail dans certains cas liés à l’utilisation du
Fortran 95
• Ne s’utilise qu’au sein d’une région parallèle
• Fonctions intrinsèques portant sur des tableaux (exemples: MATMUL,
DOT_PRODUCT, SUM, COUNT, etc ...)
• Instructions de type FORALL et WHERE
• N’admet que la clause NOWAIT en fin de construction
236 / 488
OpenMP Autres directives de partage du travail
237 / 488
OpenMP Autres directives de partage du travail
238 / 488
OpenMP Autres directives de partage du travail
Résumons …
239 / 488
OpenMP Tâches OpenMP
240 / 488
OpenMP Tâches OpenMP
241 / 488
OpenMP Tâches OpenMP
Exemple déja rencontré : tâches crées implicitement dans une région parallèle
#pragma omp parallel num_threads(3)
{
// Création de trois tâches implicites, affectées à trois threads
}
242 / 488
OpenMP Tâches OpenMP
243 / 488
OpenMP Tâches OpenMP
autres_calculs();
Dès qu’un thread de la région sera disponible, il exécutera une des tâches do_task(i)
245 / 488
OpenMP Tâches OpenMP
246 / 488
OpenMP Tâches OpenMP
Directive TASKWAIT
• Spécifie un point d’attente de terminaison des tâches créées avant l’appel à la
directive
• Il s’agit d’une barrière spécifique aux tâches.
• Dans l’exemple ci-dessous : la tache 4 sera effectuée après les taches 1, 2 et 3
!$omp parallel
!$omp single
!$omp task
printf("Task 1\n");
!$omp task
printf("Task 2\n");
!$omp task
printf("Task 3\n");
!$omp taskwait
!$omp task
printf("Task 4!\n");
247 / 488
OpenMP Tâches OpenMP
Résumons …
248 / 488
OpenMP Synchronisation
249 / 488
OpenMP Synchronisation
Synchronisation
En mémoire partagée, il peut être nécessaire d’introduire une synchronisation entre les
tâches. Cela évite par exemple la modification d’une valeur partagée dans un ordre
aléatoire (race condition)
Nous avons vu que de nombreuses directives impliquent une synchronisation implicite en
fin de région ( parallel , sections …).
Il existe d’autres moyens de gérer la synchronisation :
• Directives de synchronisation explicites : exemple BARRIER
• Directives qui permettent la synchronisation de données : FLUSH
• Directives qui permettent d’exécuter des portions de code dans un certain ordre
pour aboutir à une forme de synchronisation : ORDERED
• Directives ATOMIC et CRITICAL
• Les routines spécifiques de la bibliothèque
250 / 488
OpenMP Synchronisation
directive BARRIER
Barrière de synchronisation : chaque threads attend que tous les autres aient terminé
leur travail.
• La directive doit être exécutée par tous les threads avant de passer à la tâche
suivante.
• : si le code est écrit de telle façon que tous les threads ne soient pas en mesure
d’exécuter l’instruction, possibilité de deadlock, le programme se bloque en cours
d’exécution.
Exemple :
!$OMP PARALLEL
if (mythreadnum < 5) then
!$OMP BARRIER
endif
!$OMP END PARALLEL
251 / 488
OpenMP Synchronisation
Flush
Flush : opération qui rend la mémoire temporaire d’un thread consistante avec la
mémoire partagée.
252 / 488
OpenMP Synchronisation
Flush
• Assure que le contenu en tmp est bien celui en shared (e.g. en cas d’écriture en
shared par un autre thread).
• Assure que le contenu en shared est bien celui de la dernière écriture en tmp sur le
thread courant.
• ne concerne que le thread qui flush ! Ce n’est pas une synchronisation complète
Exemple
253 / 488
OpenMP Synchronisation
Flush
• Assure que le contenu en tmp est bien celui en shared (e.g. en cas d’écriture en
shared par un autre thread).
• Assure que le contenu en shared est bien celui de la dernière écriture en tmp sur le
thread courant.
• ne concerne que le thread qui flush ! Ce n’est pas une synchronisation complète
Exemple
253 / 488
OpenMP Synchronisation
Flush
• Assure que le contenu en tmp est bien celui en shared (e.g. en cas d’écriture en
shared par un autre thread).
• Assure que le contenu en shared est bien celui de la dernière écriture en tmp sur le
thread courant.
• ne concerne que le thread qui flush ! Ce n’est pas une synchronisation complète
Exemple
253 / 488
OpenMP Synchronisation
Flush
Quand flusher ?
Mais : utiliser flush pour la gestion de la synchronisation des variables est compliquée et
sources de bugs.
254 / 488
OpenMP Synchronisation
255 / 488
OpenMP Synchronisation
Directive CRITICAL
Définition d’une region “critique” qui ne sera exécutée que par un seul thread à la fois.
: différent de single !
#pragma omp parallel for private(b), shared(res)
for(i=1;i<niters;i++)
{
b = doit(i)
#pragma omp critical
{ // Région critique
combine (b, res)
}
}
260 / 488
OpenMP Synchronisation
Exercice
261 / 488
OpenMP Optimisations
262 / 488
OpenMP Optimisations
263 / 488
OpenMP Optimisations
263 / 488
OpenMP Optimisations
263 / 488
OpenMP Optimisations
264 / 488
OpenMP Optimisations
Outils de profiling
• analyse des tâches thread par thread
• identification les threads qui attendent/calculent, etc ...
266 / 488
OpenMP Conclusion
267 / 488
OpenMP Conclusion
268 / 488
OpenMP Conclusion
269 / 488
GPGPU
2 GPGPU
1 OpenMP
270 / 488
Introduction au GPGPU
[Introduction au calcul parallèle]
1
Plan du cours
2
Le contexte
Historique
A l’origine de leur création, les cartes graphiques (GPU) avaient pour but d’accélérer le pipeline
de rendu1 des scènes 3D. Les premières générations de GPU implémentaient tout ou partie de
ce pipeline de manière hardware. L’histoire des GPU connait un tournant majeur avec
l’introduction en 2001 d’un pipeline programmable. Cette évolution de la pile logicielle aboutie
en 2007 à la naissance du premier kit de développement CUDA et au début de l’ère du :
On commence alors à exploiter la puissance de calcul des GPUs en calcul scientifique, pour le
traitement des tâches massivement parallèles.
1
Ensemble des étapes de création d’une scène 3D, du chargement des données, au dessin en passant par la
rasterisation et l’application de textures.
3
L’évolution de la pile logicielle
þ Avant 1995 : les rendus 3D sont calculés sur CPU. Lenteur, et possiblités trés limitées.
þ 1996 : Diamond sort la 3Dfx VooDoo (premier succès 50 à 80% du marché, accélération
matérielle d’une partie du pipeline)
þ 1999 : Nvidia lance les premières cartes “GPU” (GeForce 256) qui accélèrent l’intégralité du
pipeline de rendu de manière hardware (non-programmable). Augmentation des
résolutions d’écrans, et de la complexité des modèles 3D (nombre de triangles).
þ 2001 : Avec la GeForce 3, Nvidia introduit le pipeline programmable via une fonction
“shader”. Début de l’ère des GPGPU. Premières utilisations pour le calcul scientifique,
programmation trés complexe.
þ 2006 : Nvidia introduit la GeForce 8800 et sort une API dédiée au calcul scientifique
(programmation en C). Naissance de CUDA.
4
L’évolution de la pile logicielle: chronologie, naissance du GPGPU
5
L’évolution du matériel: une affaire de design
2
Constatation selon laquelle le nombre de transistors d’un CPU double tous les 2 ans.
6
L’évolution du matériel: les différentes gammes de GPU (Nvidia)
S’il existe d’autres constructeurs de cartes GPU (AMD, Intel, etc…), nous nous focaliserons sur les
cartes Nvidia (utilisées sur les machines de GRICAD) et en particulier les V100 et A100 de la
gamme Tesla conçues spécifiquement pour l’IA et le HPC.
þ GeForce : cartes graphiques pour usage grand public : jeux, infographie, calcul parallèle
þ Quadro : cartes graphiques dédiées aux professionnels : création de contenu digital, CAO,
DAO
þ Tesla : cartes graphiques dédiées uniquement au calcul scientifique
þ Tegra : liées aux systèmes mobiles (smartphones, tablettes)
7
L’évolution du matériel: Nvidia Tesla A100
8
Le contexte : pourquoi le GPU ?
Pour comprendre pourquoi le GPU à pris une large importance dans le paysage de la simulation
numérique, il est important de comparer ces deux architectures pour bien cerner les limitations
et les capacités de chacunes d’entres elles.
9
L’architecture
Rappel: architecture CPU
þ fréquence d’horloge élevée pour effectuer plus d’opérations pour éviter d’attendre
þ différents niveaux de mémoires cache (à faible latence) pour réduire et maitriser la latence
des accès à la RAM du système
þ système de contrôle sophistiqué (prédiction de branchement, exécution out-of-order, etc…)
pour l’optimisation de l’accès aux données
11
Architecture CPU : limitations
12
Architecture GPU : un design orienté débit
CPU : GPU
Applications Applications
Concept Concept
Les premiers noeuds ‘bigfoot’ équipés d’accélérateurs GPU, précédement hébergés dans le
cluster Dahu, ont rejoint le cluster GPGPU Bigfoot en 2022. Bigfoot est donc aujourd’hui
composé de noeuds de types différents :
Noeuds à base de V100 :
þ CPUs: 2 x Xeon Gold 6130 2.1Ghz (16c) soit 32 coeurs
ou 2 x Xeon Gold 5218R 2.10GHz (20c) soit 40 coeurs
þ RAM: 192Go
þ GPUs: 4 x Nvidia Tesla V100 32Go HBM2 par noeud
þ Interconnection des GPU via le bus NvLink : 300GB/s
þ Interconnection des noeuds via le réseau OmniPath :
100GB/s
Z Noeuds à privilégier pour les projets qui veulent
exploiter le multi-GPU grâce à la forte bande passante du
15
SXM2.
Présentation des ressources : le cluster IA/DeepLearning ‘Bigfoot’
18
Utilisation des ressources GPU
Avant d’exploiter la puissance des GPUs, il est important d’avoir à l’esprit les principales étapes
pour y parvenir. Il faudra donc :
1.activer la couche logicielle nécessaire à l’interaction avec les GPUs (Kit de développement),
sauf dans le cas d’utilisation d’un container qui embarque cette couche (images issues du
cloud Nvidia NGC notamment).
2.activer le gestionnaire d’environnements adapté à vos besoins/critères (reproductibilté,
facilité de mise en oeuvre, etc…)
3.activer l’environnement adéquat pour utiliser les bibliothèques choisies (lancer le
container qui intègre les bibliothèques dont vous avez besoin)
19
Utilisation des ressources GPU : rappel gestion de l’environnement
Plusieurs gestionnaires d’environnements sont disponibles sur les machines de GRICAD. Dans
ce module, nous parlerons uniquement des gestionnaires d’environnements préconisés pour
l’usage des GPUs (Micromamba et Apptainer). Ci-dessous un bref rappel des commandes pour
activer Micromamba.
Pour utiliser les containers via Apptainer, utiliser la version présente sur les noeuds :
20
Utilisation des ressources GPU : choisir son gestionnaire d’environnements
Les containers lancés via Apptainer ont généralement accès à vos données sur /home et sur /bettik, et
il est aussi possible de compléter les montages selon vos besoins.
21
Utilisation des ressources GPU : réservation OAR
L’exploitation des noeuds GPU nécessite une syntaxe particulière au niveau de la réservation de
ressources avec OAR. Il est en effet indispensable de préciser au gestionnaire de Jobs de quelles
ressources GPU vous avez besoin pour votre job.
Les ressources GPU sont identifiées par les mots clé : gpu et migdevice.
Vous pouvez utiliser ces mots clé pour réserver vos ressources :
# Réserver 1 GPU
> oarsub -I -l /nodes=1/gpu=1
22
Utilisation des ressources GPU : réservation OAR
# Réserver 1 GPU T4
> oarsub -I -l /nodes=1/gpu=1 -p "fall='YES'"
Attention Z :Il est recommandé de ne pas spécifier le nombre de coeurs pour les noeuds GPU,
car cela peut entrainer des problèmes de réservation.
23
Introduction à CUDA
Séquençage d’un code CUDA
24
Séquençage d’un code CUDA
25
Exemple de code CUDA
Compilation et exécution :
$ nvcc main.cu
$ ./a.out
Hello World!
26
Compilation avec nvcc
Documentation utile
27
Les threads: processus et parallèlisme
28
Visualiser l’utilisation du GPU
29
Visualiser l’utilisation du GPU
nvidia-smi --query-gpu=utilization.gpu,utilization.memory \
--format=csv --loop-ms=1000 -i 3
nvidia-smi -q -i 3
þ Pour plus de détails sur toutes les options de cette commande : nvidia-smi -h
30
Introduction à OpenACC
Origine, définition
Origine :
Né en 2011 et développé par le consortium : Cray, Nvidia, CAPS, et PGI ; OpenACC est un standard
de programmation qui permet le calcul parallèle sur des systèmes hétérogènes CPU/GPGPU.
Définition :
þ OpenACC est pris en charge par les compilateurs de PGI (>=12.6), Cray et CAPS (>=3.1), GCC
(récent).
31
Syntaxe des directives et clauses
Syntaxe C :
Syntaxe Fortran :
!$acc directive-name[clause[[,]clause]...]
...
!$acc end directive-name
32
Directives
33
Clauses et niveaux de parallélisme :
34
Clauses et niveaux de parallélisme :
35
Synthèse
Bande passante: désigne le débit binaire maximal d’une voix de transmission. Elle représente la
quantité d’informations (en GB/s) qui peut être transmise sur une voie de transmission.
Bus: dispositif de transmission de données partagé entre plusieurs composants d’un système
numérique. ex: bus PCIe, Nvlink, etc…
Double précision: Le format double précision est le plus couramment utilisé sur les ordinateurs
actuels pour représenter les nombres en virgule flottante. Stocké sur 64 bits, il correspond à
une mantisse de 53 bits, soit environ 16 chiffres décimaux, et permet de représenter des
nombres de valeur absolue comprise entre 4, 94 ∗ 10−324 et 1, 80 ∗ 10308 .
HBM2: [High Bandwidth Memory 2] nouvelle génération de la mémoire vidéo (GDDR5) qui
possède un plus grande capacité (empilement de couches), une fréquence et donc une
consommation réduite, et un large bus de données.
37
Glossaire
Pipeline de rendu 3D: ensemble des étapes qui conduit à l’affichage d’une scène 3D à partir de
données (maillages, textures).
Puissance crête: mesure les performances des unités de calcul en virgule flottante (FPU)
contenues dans le cœur.
Kernel: Un kernel est une portion parallèle de code à exécuter sur le périphérique (GPU).
Chacune de ses instances s’appelle un thread. 38
Merci de votre attention.
Références:
þ https://www.saagie.com/fr/blog/l-histoire-du-deep-learning/
þ https://perso.liris.cnrs.fr/christian.wolf/teaching/
þ https://fr.wikipedia.org/wiki/Compute_Unified_Device_Architecture
þ https://www.malekal.com/cpu-vs-gpu-les-differences/
þ http://developer.download.nvidia.com/compute/DCGM/docs/nvidia-smi-367.38.pdf
þ https://www.science-et-vie.com/science-et-culture/1965-2020-la-loi-de-moore-est-morte-53613
þ http://lyoncalcul.univ-lyon1.fr/events/2013/cours_archi.pdf
þ https://www.labri.fr/perso/pbenard/teaching/pghp/slides/Cours_PGHP_2016_08_Cuda.pdf
þ https://people.duke.edu/~ccc14/sta-663/GPUsAndCUDAC.html
þ https://overclocking.com/comment-organise-un-gpu/
þ https://overclocking.com/quelles-sont-les-unites-de-base-dun-gpu/
þ https://www.malekal.com/cpu-vs-gpu-les-differences/
þ https://moodle.insa-lyon.fr/mod/resource/view.php?id=38316
þ http://developer.download.nvidia.com/compute/DCGM/docs/nvidia-smi-367.38.pdf
þ https://docs.computecanada.ca/wiki/OpenACC_Tutorial_-_Adding_directives
þ https://developer.download.nvidia.com/video/gputechconf/gtc/2019/presentation/s9262-zero-to-gpu-hero-with-openacc.pdf
39
Les grilles de calcul
Mars 2025
317 / 488
Le cours sur les grilles de calcul et CiGri
318 / 488
Programmation parallèle par échange de messages - MPI
Mars 2025
319 / 488
Introduction
3 Communications
1 Introduction
Quelques rappels sur le parallélisme 4 Types dérivés
Modèle de programmation parallèle
par échange de messages 5 Groupes, communicateurs et topologies
Le standard MPI
6 Autres fonctionnalités
2 Premiers pas avec MPI
320 / 488
Introduction Quelques rappels sur le parallélisme
3 Communications
1 Introduction
Quelques rappels sur le parallélisme 4 Types dérivés
Modèle de programmation parallèle
par échange de messages 5 Groupes, communicateurs et topologies
Le standard MPI
6 Autres fonctionnalités
2 Premiers pas avec MPI
321 / 488
Introduction Quelques rappels sur le parallélisme
Paralléliser?
“Réorganiser” le problème pour pouvoir traiter simultanément des données et des
calculs, en utilisant plusieurs ressources de calcul.
Pourquoi?
• Améliorer les performances ⇒ calculer plus vite.
• Traiter un volume de données plus important ⇒ utiliser la mémoire de plusieurs
noeuds de calcul.
Points importants :
• connaître l’ architecture matérielle : voir introduction de ce cours,
• choisir un modèle de programmation.
322 / 488
Introduction Quelques rappels sur le parallélisme
323 / 488
Introduction Quelques rappels sur le parallélisme
⇒ OpenMP
323 / 488
Introduction Quelques rappels sur le parallélisme
324 / 488
Introduction Quelques rappels sur le parallélisme
⇒ MPI
324 / 488
Introduction Quelques rappels sur le parallélisme
327 / 488
Introduction Modèle de programmation parallèle par échange de messages
3 Communications
1 Introduction
Quelques rappels sur le parallélisme 4 Types dérivés
Modèle de programmation parallèle
par échange de messages 5 Groupes, communicateurs et topologies
Le standard MPI
6 Autres fonctionnalités
2 Premiers pas avec MPI
328 / 488
Introduction Modèle de programmation parallèle par échange de messages
Modèle séquentiel
331 / 488
Introduction Modèle de programmation parallèle par échange de messages
332 / 488
Introduction Modèle de programmation parallèle par échange de messages
332 / 488
Introduction Modèle de programmation parallèle par échange de messages
Modèle SPMD
• SPMD, modèle le plus courant : chaque processus fait tourner le même exécutable
sur des données différentes.
• Autre modèle : Multiple Program, Multiple Data (MPMD). Chaque processus fait
tourner un programme différent sur des données différentes.
333 / 488
Introduction Modèle de programmation parallèle par échange de messages
(relativement à OpenMP …)
Avantages
• Peut être implémenté sur une grande variété de plates-formes :
• calculateur à mémoire distribuée,
• calculateur à mémoire partagée,
• architecture parallèle hétérogène.
• Permet en général un plus grand contrôle de la localisation des données et par
conséquent une meilleure performance des accès aux données.
• Passage à l’échelle pour des volumes de données importants.
334 / 488
Introduction Modèle de programmation parallèle par échange de messages
Inconvénients
• Nécessite de repenser et réécrire le code existant . Mise en oeuvre potentiellement
plus compliquée qu’avec OpenMP.
• Le coût des communications peut devenir important.
• Attention à la répartition des tâches.
335 / 488
Introduction Modèle de programmation parallèle par échange de messages
Comment paralléliser?
Que faire pour passer d’un code séquentiel à un code parallèle avec un modèle par
échange de message?
• Identifier un type de parallélisme adapté au problème à traiter :
• “data parallelism” : décomposition des données . Les données peuvent être
découpées et distribuées sur différentes zones mémoires.
• “task parallelism” : répartition des tâches sur les différents processus.
• Revoir la structure de donnée.
• Revoir/modifier l’ordre des calculs.
• Identifier les tâches indépendantes.
• Gérer les communications.
• …
336 / 488
Introduction Modèle de programmation parallèle par échange de messages
337 / 488
Introduction Le standard MPI
3 Communications
1 Introduction
Quelques rappels sur le parallélisme 4 Types dérivés
Modèle de programmation parallèle
par échange de messages 5 Groupes, communicateurs et topologies
Le standard MPI
6 Autres fonctionnalités
2 Premiers pas avec MPI
338 / 488
Introduction Le standard MPI
339 / 488
Introduction Le standard MPI
340 / 488
Introduction Le standard MPI
341 / 488
Introduction Le standard MPI
Bibliographie
• Message Passing Interface Forum, http:// www.mpi-forum.org/ index.html
• “MPI: A Message-Passing Interface Standard, Version 4.0”, Message Passing
Interface Forum, june 2021 - http:// mpi-forum.org/ docs/
• Gropp, W., E. Lusk, and A. Skjellum. 1999. Using MPI: Portable Parallel
Programming with the Message Passing. 2nd Edition. MIT Press, Cambridge, MA.
• Cours et tutoriaux:
http:// www.idris.fr/ formations/ mpi (Supports de cours et
Aide mémoire en C et Fortran )
http:// www.mcs.anl.gov/ research/ projects/ mpi/
• Quelques exemples de bibliothèques scientifiques parallèles :
ScaLAPACK, PETSc, FFTW . . .
342 / 488
Premiers pas avec MPI
3 Communications
1 Introduction
4 Types dérivés
2 Premiers pas avec MPI
Écriture d’un programme MPI 5 Groupes, communicateurs et topologies
Compilation et exécution d’un
programme MPI 6 Autres fonctionnalités
Présentation des tps et
consignes/aide-mémoire
343 / 488
Premiers pas avec MPI
MPI
344 / 488
Premiers pas avec MPI
345 / 488
Premiers pas avec MPI Écriture d’un programme MPI
3 Communications
1 Introduction
4 Types dérivés
2 Premiers pas avec MPI
Écriture d’un programme MPI 5 Groupes, communicateurs et topologies
Compilation et exécution d’un
programme MPI 6 Autres fonctionnalités
Présentation des tps et
consignes/aide-mémoire
346 / 488
Premiers pas avec MPI Écriture d’un programme MPI
Une bibliothèque MPI va fournir un certain nombre de fonctions pour chacun des
langages disponibles.
Quel que soit le langage, la structure standard du programme ressemblera en général à :
1 inclusion des headers, modules, packages ...
347 / 488
Premiers pas avec MPI Écriture d’un programme MPI
La bibliothèque MPI
Les routines que nous allons aborder dans ce cours peuvent être classées selon les
catégories ci-dessous :
• Gestion du contexte de communication et des processus
• Initialisation et fin du contexte de communication. Séance 1. TP 1.
• Organisation des processus en communicateurs, groupes ou topologies. Séance 1 et
4 - TP 4.
• Communications point à point.
Échange de messages entre deux processus. Séance 1 et 2. TP 2.
• Communications collectives.
Échange de messages entre des groupes de processus. Séance 2. TP 2.
• Création/définition de nouveaux types de données :
Types dérivés MPI. Séance 3, TP 3.
348 / 488
Premiers pas avec MPI Écriture d’un programme MPI
use mpi_f08
#include <mpi.h>
En python
from mpi4py import MPI
349 / 488
Premiers pas avec MPI Écriture d’un programme MPI
Les deux routines renvoient un code d’erreur qui vaut MPI_SUCCESS si tout s’est
bien passé.
• Un et un seul appel à MPI_Init par programme.
• Init impératif avant tout appel d’une autre fonction MPI.
• init/finalize: collectif , doit être appelé par tous les processus.
350 / 488
Premiers pas avec MPI Écriture d’un programme MPI
Vous pourrez donc facilement interpréter les exemples et passer d’un langage à l’autre,
• il suffira d’adapter les types (int → integer …),
• et de vérifier le nombre d’arguments C/Fortran (la plupart du temps presque
identique, à un argument près : le dernier argument du Fortran est transformé en
argument de retour pour le C)
call MPI_Finalize(code_erreur) !! Fortran
Toujours vérifier dans la norme ou via man le type et le nombre d’arguments des
fonctions MPI. Cela évitera des messages d’erreur pas toujours explicites …
351 / 488
Premiers pas avec MPI Écriture d’un programme MPI
MPI et le C++
l’interface C++ est obsolète depuis MPI-2 et a été supprimée à partir de MPI-3.
Il est donc fortement déconseillé de l’utiliser.
Conseil :
• codez en C++ mais pour tous les appels MPI, utilisez l’API C,
• continuez d’utiliser un compilateur C++ (souvent plus “rigoureux” que le
compilateur C).
Vous pouvez aussi éventuellement utiliser une implémentation spécifique telle que
boost::mpi, http:// www.boost.org/ doc/ libs/ 1_62_0/ doc/ html/ mpi.html.
352 / 488
Premiers pas avec MPI Écriture d’un programme MPI
354 / 488
Premiers pas avec MPI Écriture d’un programme MPI
354 / 488
Premiers pas avec MPI Écriture d’un programme MPI
355 / 488
Premiers pas avec MPI Écriture d’un programme MPI
program testmpi
! 1 - Inclusion du module mpi
use mpi_f08
implicit none
type(MPI_Comm) :: mon_comm
integer :: error, nombre_de_processus, rang
! 2 - Initialisation du contexte de communication
call MPI_Init(error)
! 3 - Organisation des processus : par défaut dans MPI_COMM_WORLD (crée à l'appel de MPI_Init)
mon_comm = MPI_COMM_WORLD
! nombre_de_processus = taille du communicateur mon_comm
call MPI_Comm_size(mon_comm,nombre_de_processus,error)
! rang = rang du processus courant dans mon_comm
call MPI_Comm_rank(mon_comm, rang, error)
! 4 - Calculs, communications ...
print *, "je suis le processus de rang ", rang
! 5 - Cloture du contexte MPI
call MPI_Finalize(error)
end program
356 / 488
Premiers pas avec MPI Écriture d’un programme MPI
Un premier exemple en C
#include <stdio.h>
// 1 - Inclusion du header mpi
#include <mpi.h>
int main(int argc, char* argv[])
{
int error, nombre_de_processus, rang;
// 2 - Initialisation du contexte de communication
error = MPI_Init(&argc,&argv);
// 3 - Organisation des processus : par défaut dans MPI_COMM_WORLD (crée à l'appel de MPI_Init)
MPI_Comm mon_comm = MPI_COMM_WORLD;
// nombre_de_processus = taille du communicateur mon_comm
error = MPI_Comm_size(mon_comm,&nombre_de_processus);
// rang = rang du processus courant dans mon_comm
error = MPI_Comm_rank(mon_comm,&rang);
// 4 - Calculs, communications ...
printf("je suis le processus de rang %d\n",rang);
// 5 - Cloture du contexte MPI
error = MPI_Finalize();
}
357 / 488
Premiers pas avec MPI Écriture d’un programme MPI
358 / 488
Premiers pas avec MPI Écriture d’un programme MPI
Exemple d’exécution
359 / 488
Premiers pas avec MPI Écriture d’un programme MPI
Pour mesurer le temps écoulé sur chaque processus, on utilise la fonction MPI_Wtime
: elle renvoie le temps écoulé depuis un temps arbitraire (constant pendant l’exécution
du programme).
360 / 488
Premiers pas avec MPI Écriture d’un programme MPI
3 Communications
1 Introduction
4 Types dérivés
2 Premiers pas avec MPI
Écriture d’un programme MPI 5 Groupes, communicateurs et topologies
Compilation et exécution d’un
programme MPI 6 Autres fonctionnalités
Présentation des tps et
consignes/aide-mémoire
362 / 488
Premiers pas avec MPI Compilation et exécution d’un programme MPI
Compilation/édition de lien
363 / 488
Premiers pas avec MPI Compilation et exécution d’un programme MPI
ou
> g++ -I/nix/store/slfy56hw7zl8ff1kzq984vb15m1wj3bi-openmpi-3.1.0/include -pthread -Wl,-rpath
-Wl,/nix/store/slfy56hw7zl8ff1kzq984vb15m1wj3bi-openmpi-3.1.0/lib -Wl,--enable-new-dtags
-L/nix/store/slfy56hw7zl8ff1kzq984vb15m1wj3bi-openmpi-3.1.0/lib -lmpi ./monProg
les options, les chemins vers les librairies et les librairies elles mêmes vont dépendre
de l’implémentation de MPI et du compilateur …
C’est un peu pénible mais heureusement, certaines implémentations (e.g. openmpi)
fournissent des “wrappers” pour la compilation et l’édition de lien.
364 / 488
Premiers pas avec MPI Compilation et exécution d’un programme MPI
# Intel
> mpiicpc -show
...
Exemples
# 4 processus, sur un seul noeud # calcul sur deux noeuds, 4 processus par noe
mpirun -np 4 ./prog mpirun -H luke44,luke43 -npernode 4 ./prog
366 / 488
Premiers pas avec MPI Compilation et exécution d’un programme MPI
• Pour démarrer, utilisez openmpi basé sur les compilateurs ‘gnu”, souvent
disponibles par défaut.
• En général d’autres implémentations seront accessibles sur les machines de calcul
(via nix ou guix par exemple)
• à la compatibilité entre le compilateur utilisé et la commande mpirun.
Assurez-vous (which mpirun) qu’il s’agit bien du mpirun correspondant aux
compilateurs employés pour votre code.
• Quelques commandes utiles pour suivre le job et l’utilisation des ressources :
top, htop, oarstat (si oar est le gestionnaire de ressource) …
367 / 488
Premiers pas avec MPI Compilation et exécution d’un programme MPI
368 / 488
Premiers pas avec MPI Compilation et exécution d’un programme MPI
369 / 488
Premiers pas avec MPI Compilation et exécution d’un programme MPI
• Un peu d’aide ?
man mpirun
man mpiexec 370 / 488
Premiers pas avec MPI Compilation et exécution d’un programme MPI
Pour lancer votre programme vous devrez utiliser oar en mode interactif ou en batch.
Nous vous fournirons des scripts et des détails durant les tps.
• oarscript-gnu.sh pour le mode batch, basé sur les compilateurs gnu et openmpi
• oarscript-intel.sh pour le mode batch, basé sur les compilateurs intel sur Dahu.
371 / 488
Premiers pas avec MPI Présentation des tps et consignes/aide-mémoire
3 Communications
1 Introduction
4 Types dérivés
2 Premiers pas avec MPI
Écriture d’un programme MPI 5 Groupes, communicateurs et topologies
Compilation et exécution d’un
programme MPI 6 Autres fonctionnalités
Présentation des tps et
consignes/aide-mémoire
372 / 488
Premiers pas avec MPI Présentation des tps et consignes/aide-mémoire
Comme pour OpenMP, les exercices sont décrits dans le projet gitlab habituel, trainings.
Avant de passer aux communications, lisez les consignes et faites le premier exercice,
“Bases de MPI”.
373 / 488
Communications
point à point
Communications collectives
1 Introduction
4 Types dérivés
2 Premiers pas avec MPI
374 / 488
Communications Communications point à point
point à point
Communications collectives
1 Introduction
4 Types dérivés
2 Premiers pas avec MPI
375 / 488
Communications Communications point à point
• Finalité : copier une zone mémoire du processus source vers une zone mémoire du
processus destinataire.
• Source : envoi explicite d’un message →MPI_Send.
• Destinataire : réception explicite d’un message → MPI_Recv. 376 / 488
Communications Communications point à point
Message?
377 / 488
Communications Communications point à point
“nb_elements” : nombre maximum d’éléments de type “type_data” qu’on pourra recevoir dans
data.
vous pouvez choisir un nombre différent du nombre effectifs d’éléments reçus (pas de
vérification à la réception. Pour obtenir le nombre d’élements réellement reçus, voir la fonction
MPI_Get_count ).
vérifiez toujours dans la norme ou via man le type et le nombre d’arguments des fonctions
MPI. Cela évitera des messages d’erreur pas toujours explicites …
378 / 488
Communications Communications point à point
Un exemple simple
integer :: source, dest, tag, error, buffer, nb_elements
TYPE(MPI_Status) :: status
source = 0 ; dest = 1; tag = 21 ; nb_elements=1
!! On récupère le rang du processus courant
call MPI_Comm_rank(MPI_COMM_WORLD, rang_processus, error)
379 / 488
Communications Communications point à point
Un exemple simple
380 / 488
Communications Communications point à point
Compléments
Wildcards : constantes pré-définies, évite d’avoir à renseigner le tag et/ou la source;
permet d’autoriser la réception de n’importe quelle source avec n’importe quel tag.
source = MPI_ANY_SOURCE
tag = MPI_ANY_TAG
call MPI_Recv(buffer,12,MPI_INTEGER,source,tag,MPI_COMM_WORLD,status,error)
MPI_Recv : à ne pas oublier l’argument ’status’. C’est une structure qui contient
les informations concernant l’enveloppe du message reçu :
• status%MPI_SOURCE : origine du message (rang)
• status%MPI_TAG : tag du message
call MPI_Get_count(status, MPI_INTEGER, count, erreur)
int buffer[6];
int nombre = 3;
// cas 1 : envoi de trois entiers
MPI_Send(buffer, nombre, MPI_INT, ...);
// cas 2 : aucune erreur de compilation
// mais mauvais résultat
MPI_Send(buffer, nombre, MPI_DOUBLE ...)
Ecriture d’un tableau d’entiers en mémoire
382 / 488
Communications Communications point à point
int buffer[6];
int nombre = 3;
// cas 1 : envoi de trois entiers
MPI_Send(buffer, nombre, MPI_INT, ...);
// cas 2 : aucune erreur de compilation
// mais mauvais résultat
MPI_Send(buffer, nombre, MPI_DOUBLE ...)
Envoi de MPI_INT
382 / 488
Communications Communications point à point
int buffer[6];
int nombre = 3;
// cas 1 : envoi de trois entiers
MPI_Send(buffer, nombre, MPI_INT, ...);
// cas 2 : aucune erreur de compilation
// mais mauvais résultat
MPI_Send(buffer, nombre, MPI_DOUBLE ...)
Envoi de MPI_INT
382 / 488
Communications Communications point à point
int buffer[6];
int nombre = 3;
// cas 1 : envoi de trois entiers
MPI_Send(buffer, nombre, MPI_INT, ...);
// cas 2 : aucune erreur de compilation
// mais mauvais résultat
MPI_Send(buffer, nombre, MPI_DOUBLE ...)
Envoi de MPI_INT
382 / 488
Communications Communications point à point
int buffer[6];
int nombre = 3;
// cas 1 : envoi de trois entiers
MPI_Send(buffer, nombre, MPI_INT, ...);
// cas 2 : aucune erreur de compilation
// mais mauvais résultat
MPI_Send(buffer, nombre, MPI_DOUBLE ...)
Envoi de MPI_INT
382 / 488
Communications Communications point à point
int buffer[6];
int nombre = 3;
// cas 1 : envoi de trois entiers
MPI_Send(buffer, nombre, MPI_INT, ...);
// cas 2 : aucune erreur de compilation
// mais mauvais résultat
MPI_Send(buffer, nombre, MPI_DOUBLE ...)
Envoi de MPI_DOUBLE
Pas de vérification de consistance entre le type de la donnée envoyée et le type MPI !
send et recv sont indépendants : il est tout a fait possible de recevoir un envoi d’entiers
dans des flottants.
382 / 488
Communications Communications point à point
Nous verrons plus loin qu’il est possible de définir ses propres types (types dérivés).
383 / 488
Communications Communications point à point
Comportement à l’exécution
Au cours d’un échange point à point, l’envoi et la réception (appels à MPI_Send et
MPI_Recv) sont deux opérations distinctes éventuellement asynchrones, réalisées par
deux processus différents.
Un certain nombre de questions se posent …
• Que se passe t’il si aucune réception ne correspond à l’envoi?
• Peut-on utiliser les variables envoyées/reçues sans impact sur le message?
• Peut-on reprendre la main et faire autre chose pendant l’envoi ou la réception du
message?
• …
Deux notions importantes à définir : celle d’échange bloquant et celle de complétion
d’un envoi ou d’une réception.
384 / 488
Communications Communications point à point
385 / 488
Communications Communications point à point
Appel bloquant
Un appel est dit bloquant lorsque le programme reste dans la routine tant que
l’envoi ou la réception n’est pas complet au sens défini juste avant.
⇒ un appel non-bloquant ne garantit pas la complétion.
386 / 488
Communications Communications point à point
Comportement à l’envoi
1 Démarrage de la communication (on parle de postage de l’envoi).
2 Ensuite, deux situations sont possibles.
• Bufferisation , copie dans une zone mémoire temporaire en attendant l’envoi qui se
fera plus tard, de manière asynchrone. Il n’est donc pas nécessaire d’attendre la
réception.
• Synchronisation avec la réception : la routine attend que le processus récepteur
soit prêt et que le transfert ait commencé. Le programme reprend la main
uniquement quand l’envoi est complet.
387 / 488
Communications Communications point à point
Comportement à l’envoi
1 Démarrage de la communication (on parle de postage de l’envoi).
2 Ensuite, deux situations sont possibles.
• Bufferisation , copie dans une zone mémoire temporaire en attendant l’envoi qui se
fera plus tard, de manière asynchrone. Il n’est donc pas nécessaire d’attendre la
réception.
• Synchronisation avec la réception : la routine attend que le processus récepteur
soit prêt et que le transfert ait commencé. Le programme reprend la main
uniquement quand l’envoi est complet.
La “bufferisation” donnera probablement de meilleures performances mais nécessite une
copie en mémoire (côté émetteur ou récepteur, selon l’implémentation). A noter que la
taille des buffers disponibles est forcément limitée.
Le passage d’un mode à l’autre
dépendra de l’implémentation et de la taille du message .
387 / 488
Communications Communications point à point
Comportement à la réception
Attention : seule l’enveloppe est vérifiée par le MPI_Recv, pas le type des données
reçues!
388 / 488
Communications Communications point à point
Pour conclure, dans le cas des communications en mode “standard” (i.e. avec
MPI_Send et MPI_Recv):
• l’envoi de message peut-être “bufferisé” ou synchrone avec la réception,
• les envois et réceptions ont un comportement bloquant .
L’emploi de MPI_Send et MPI_Recv est donc sûr du point de vue de l’accès aux
données mais une mauvaise gestion dans le code de la synchronisation et du
comportement bloquant peut amener à des situations de deadlock.
389 / 488
Communications Communications point à point
390 / 488
Communications Communications point à point
390 / 488
Communications Communications point à point
391 / 488
Communications Communications point à point
391 / 488
Communications Communications point à point
391 / 488
Communications Communications point à point
391 / 488
Communications Communications point à point
392 / 488
Communications Communications point à point
392 / 488
Communications Communications point à point
392 / 488
Communications Communications point à point
point à point
Communications collectives
1 Introduction
4 Types dérivés
2 Premiers pas avec MPI
394 / 488
Communications Optimisations des communications point à point
395 / 488
Communications Optimisations des communications point à point
396 / 488
Communications Optimisations des communications point à point
397 / 488
Communications Optimisations des communications point à point
397 / 488
Communications Optimisations des communications point à point
398 / 488
Communications Optimisations des communications point à point
Envoi non-bloquant
MPI_Isend : dès que le message est posté, le programme reprend la main sur le
processus source.
Réception non-bloquante
MPI_Irecv : dès que la réception est postée, le programme reprend la main.
⇒ le programme peut faire autre chose pendant que les transferts de message :
recouvrement des communications par les calculs.
Attention: le programme reprend la main avant que la réception ou l’envoi soit
complet. La variable envoyée/reçue ne sera donc pas utilisable immédiatement.
398 / 488
Communications Optimisations des communications point à point
A noter la présence d’un nouvel argument “requête” qui permettra d’identifier l’appel.
! en fortran
Type(MPI_Request) request
// en c
MPI_request request
MPI_Wait est bloquant et rend la main dès que la réception ou l’envoi est complet.
400 / 488
Communications Optimisations des communications point à point
logical flag
call MPI_Isend(data, nb_elements, type, destinataire, tag, communicateur, req
!! ... calcul ...
call MPI_Test(request, flag, statut, erreur)
MPI_Test est non-bloquant et renvoie un booléen qui est vrai quand l’envoi ou la
réception est complet.
401 / 488
Communications Optimisations des communications point à point
Modes de communication
Un autre moyen pour optimiser les communications consiste à contrôler le mode
d’envoi.
Il existe quatre possibilités. Dans chaque cas l’envoi peut-être bloquant ou
non-bloquant.
• Mode standard : celui que nous avons vu jusqu’à présent.
MPI_Send, MPI_Isend.
• Mode synchrone : on force l’attente de la réception et du début du transfert.
MPI_Ssend, MPI_Issend.
• Mode bufferisé : on force la copie des variables envoyées dans un buffer. C’est à
l’utilisateur de gérer les buffers.
MPI_Bsend, MPI_Ibsend.
• Mode ready : la réception doit avoir été postée avant l’envoi.
A éviter …
MPI_Rsend, MPI_Irsend. 402 / 488
Communications Communications collectives
point à point
Communications collectives
1 Introduction
4 Types dérivés
2 Premiers pas avec MPI
403 / 488
Communications Communications collectives
Communications collectives
• Rappel : communications point à point.
• Communication entre 2 processus au sein d’un même communicateur.
• Pour réaliser plusieurs envois successifs (d’une unique ou de différentes zones
mémoire) : plusieurs appels à la même procédure MPI_Send (par exemple).
• Certains inconvénients : lisibilité du code, latence à chaque appel, gestion des
étiquettes (tag), ...
404 / 488
Communications Communications collectives
Communications collectives
406 / 488
Communications Communications collectives
• Synchronisation globale
• MPI_Barrier()
• Echange de messages : transfert de données
• Diffusion globale de données : MPI_Bcast()
• Diffusion selective de données : MPI_Scatter()
• Collecte selective de données réparties : MPI_Gather()
• Collecte par tous les processus de données réparties : MPI_Allgather()
• Collecte + Diffusion par tous les processus de données réparties (' ”transposition”)
: MPI_Alltoall()
407 / 488
Communications Communications collectives
408 / 488
Communications Communications collectives
TYPE(MPI_Comm) :: comm
call MPI_Barrier(comm,ier)
409 / 488
Communications Communications collectives
TYPE(MPI_Datatype) :: send_type
call MPI_Bcast(send_buffer, send_count, send_type, rank, comm, err)
411 / 488
Communications Communications collectives
413 / 488
Communications Communications collectives
415 / 488
Communications Communications collectives
417 / 488
Communications Communications collectives
418 / 488
Communications Communications collectives
419 / 488
Communications Communications collectives
Remarque : les arguments sont les mêmes que pour MPI_Allgather mais on croise les
données échangées.
Remarque : il est possible d’utiliser le même buffer pour l’envoi et la réception, dans ce
cas le mot clé MPI_IN_PLACE doit être utilisé pour l’argument send_buffer.
420 / 488
Communications Communications collectives
Pour une programmation correcte si les buffers d’envoi et réception sont identiques:
call MPI_Alltoall( MPI_IN_PLACE , 1, MPI_INTEGER, tab, 1, MPI_INTEGER, MPI_COMM_WORLD, ierr)
421 / 488
Communications Communications collectives
Réductions réparties
422 / 488
Communications Communications collectives
Nom Opération
MPI_SUM Somme des éléments
MPI_PROD Produit
MPI_MAX Recherche du maximum
MPI_MIN Recherche du minimum
MPI_MAXLOC Recherche de l’indice du maximum
MPI_MINLOC // minimum
MPI_LAND ET logique
MPI_LOR OU logique
MPI_LXOR OU exclusif logique
423 / 488
Communications Communications collectives
424 / 488
Communications Communications collectives
427 / 488
Communications Communications collectives
Rendez-vous dans le projet habituel pour les exercices sur les communications entre
processus.
428 / 488
Types dérivés
Motivations
Définition des types dérivés
1 Introduction
Création d’un type dérivé
Conclusions
2 Premiers pas avec MPI
6 Autres fonctionnalités
4 Types dérivés
429 / 488
Types dérivés Motivations
Motivations
Définition des types dérivés
1 Introduction
Création d’un type dérivé
Conclusions
2 Premiers pas avec MPI
6 Autres fonctionnalités
4 Types dérivés
430 / 488
Types dérivés Motivations
real :: a(3,3)
! ...
call MPI_Send(a, 3, MPI_REAL,...)
432 / 488
Types dérivés Motivations
En fortran
TYPE(MPI_Datatype) :: mpi_maStruct
En C/C++
MPI_Datatype mpi_maStruct;
435 / 488
Types dérivés Définition des types dérivés
Motivations
Définition des types dérivés
1 Introduction
Création d’un type dérivé
Conclusions
2 Premiers pas avec MPI
6 Autres fonctionnalités
4 Types dérivés
436 / 488
Types dérivés Définition des types dérivés
437 / 488
Types dérivés Création d’un type dérivé
Motivations
Définition des types dérivés
1 Introduction
Création d’un type dérivé
Conclusions
2 Premiers pas avec MPI
6 Autres fonctionnalités
4 Types dérivés
438 / 488
Types dérivés Création d’un type dérivé
439 / 488
Types dérivés Création d’un type dérivé
441 / 488
Types dérivés Création d’un type dérivé
MPI_Datatype colonne;
ierr = MPI_Type_vector(5, 1, 4,
MPI_FLOAT, &colonne);
443 / 488
Types dérivés Création d’un type dérivé
Exemple :
• Les tailles des blocs sont calculées en nombre d’éléments du type initial.
• Les déplacements sont calculés en nombre d’éléments du type initial (indexed) ou en octets (create_hindexed) et
dans ce cas sont de type MPI_Aint (C/C++) ou INTEGER(KIND=MPI_ADDRESS_KIND) (Fortran).
444 / 488
Types dérivés Création d’un type dérivé
Exemple :
446 / 488
Types dérivés Création d’un type dérivé
447 / 488
Types dérivés Création d’un type dérivé
448 / 488
Types dérivés Conclusions
Motivations
Définition des types dérivés
1 Introduction
Création d’un type dérivé
Conclusions
2 Premiers pas avec MPI
6 Autres fonctionnalités
4 Types dérivés
449 / 488
Types dérivés Conclusions
Conclusions
450 / 488
Types dérivés Conclusions
Rendez-vous dans le projet habituel pour les exercices sur les types dérivés.
451 / 488
Groupes, communicateurs et topologies
452 / 488
Groupes, communicateurs et topologies Rappels sur les communicateurs
453 / 488
Groupes, communicateurs et topologies Rappels sur les communicateurs
454 / 488
Groupes, communicateurs et topologies Rappels sur les communicateurs
collectives :
455 / 488
Groupes, communicateurs et topologies Rappels sur les communicateurs
Pour échanger des messages, des processus doivent nécessairement appartenir au même
communicateur.
Le communicateur définit le contexte de communication. Il donne un “ cadre ” aux
échanges et fixe la portée des communications entre les processus du groupe.
Créer de nouveaux communicateurs permettra :
• de spécialiser un sous-groupe de processus. Par exemple pour appeler une routine
de communication collective dans ce sous-groupe,
• d’organiser un certains nombre de processus. Par exemple pour mieux “coller” au
problème à traiter en réordonnant les processus.
456 / 488
Groupes, communicateurs et topologies Rappels sur les communicateurs
Exemples
457 / 488
Groupes, communicateurs et topologies Rappels sur les communicateurs
Exemples
Réduction de la portée d’une communication collective , spécialisation d’un sous
groupe :
457 / 488
Groupes, communicateurs et topologies Rappels sur les communicateurs
Exemples
Ré-organisation des processus : topologie, notion de voisins …
457 / 488
Groupes, communicateurs et topologies Rappels sur les communicateurs
Communicateurs
458 / 488
Groupes, communicateurs et topologies communicateurs
459 / 488
Groupes, communicateurs et topologies communicateurs
MPI_Comm_group(comm_source, group)
dim : nombre de processus dans le groupe (dans le groupe target) ranks : liste des
rangs (dans source) des processus à inclure/exclure dans/de target.
460 / 488
Groupes, communicateurs et topologies communicateurs
• Destruction:
MPI_Group_free(group)
• Informations :
MPI_Group_rank(groupe, rang_dans_le_groupe) // Rang du proc. courant dans le groupe
MPI_Group_size(groupe, taille_du_groupe) // Taille du groupe
// Calcul des rangs dans group2 à partir de ceux dans group1
MPI_Group_translate_ranks(group1, dim, ranks_in_1, group2, ranks_in_2)
MPI_Group_compare(group1, group2, result) // Comparaison de deux groupes
result : MPI_IDENT (mêmes procs/ordre), MPI_SIMILAR (mêmes procs), MPI_UNEQUAL 461 / 488
Groupes, communicateurs et topologies communicateurs
Instructions de création
• copie d’un communicateur : MPI_Comm_dup
• découpage d’un communicateur : MPI_Comm_split
• création d’une grille de processus (topologie) : MPI_Cart_create
• découpage d’une topologie : MPI_Cart_sub
Instruction de libération : MPI_Comm_free
463 / 488
Groupes, communicateurs et topologies communicateurs
MPI_Comm_dup(Comm_origine,nouveau_comm)
464 / 488
Groupes, communicateurs et topologies communicateurs
465 / 488
Groupes, communicateurs et topologies communicateurs
rangs 0 1 2 3 4 5 6 7
465 / 488
Groupes, communicateurs et topologies communicateurs
rangs 0 1 2 3 4 5 6 7
couleurs 1 1 1 1
465 / 488
Groupes, communicateurs et topologies communicateurs
rangs 0 1 2 3 4 5 6 7
couleurs 1 4 4 1 1 1 4 7
465 / 488
Groupes, communicateurs et topologies communicateurs
rangs 0 1 2 3 4 5 6 7
couleurs 1 4 4 1 1 1 4 7
clés 3 0 2 1
465 / 488
Groupes, communicateurs et topologies communicateurs
rangs 0 1 2 3 4 5 6 7
couleurs 1 4 4 1 1 1 4 7
clés 3 1 2 0 2 1 0 7
465 / 488
Groupes, communicateurs et topologies Topologies
466 / 488
Groupes, communicateurs et topologies Topologies
Topologies cartésiennes
Réorganisation des processus d’un communicateur selon une grille cartésienne .
Contexte et motivations :
• Méthodes de décomposition de domaine.
• La correspondance entre les grilles de données et les grilles de processus favorise les
performances et facilite l’implémentation.
467 / 488
Groupes, communicateurs et topologies Topologies
468 / 488
Groupes, communicateurs et topologies Topologies
468 / 488
Groupes, communicateurs et topologies Topologies
468 / 488
Groupes, communicateurs et topologies Topologies
470 / 488
Groupes, communicateurs et topologies Topologies
• direction indique l’axe de déplacement (0:x, 1:y ...), step donne la taille du
déplacement.
• Les rangs des voisins sont récupérés dans previous_rank et next_rank.
• La routine prend en compte la périodicité éventuelle de la topologie.
• Si le processus n’a pas de voisin dans une direction, la routine renvoie
MPI_PROC _NULL ou MPI_UNDEFINED .
471 / 488
Groupes, communicateurs et topologies Topologies
Il peut parfois être utile de dégénérer une topologie cartésienne (i.e. de créer des sous
topologies de dimension inférieure à la topologie d’origine).
Comment?
• MPI_Comm_split (voir plus haut).
• MPI_Cart_sub : le découpage va se faire selon une ou plusieurs directions (au
max N-1, N étant la dimension de la topologie).
472 / 488
Groupes, communicateurs et topologies Topologies
473 / 488
Groupes, communicateurs et topologies Topologies
474 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
Inter- communicateurs
475 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
476 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
477 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
call MPI_Comm_rank(MPI_COMM_WORLD,rangMonde,erreur)
call MPI_Comm_size(MPI_COMM_WORLD,nbProcs,erreur)
ocean = 0
atmosphere = 1
visu = 2
couleur = mod(rang,3)
call MPI_Comm_split(MPI_COMM_WORLD,couleur,rangMonde,&
sous_comm,erreur)
477 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
select case(couleur)
case(ocean)
call MPI_Intercomm_create(sous_comm,0, &
MPI_COMM_WORLD,1, tag1, oceanAtmo,erreur)
477 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
select case(couleur)
case(ocean)
call MPI_Intercomm_create(sous_comm,0, &
MPI_COMM_WORLD,1, tag1, oceanAtmo,erreur)
case(atmosphere)
call MPI_Intercomm_create(sous_comm,0, &
MPI_COMM_WORLD,0, tag1, oceanAtmo,erreur)
477 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
select case(couleur)
case(ocean)
call MPI_Intercomm_create(sous_comm,0,&
MPI_COMM_WORLD,1,&
tag1, oceanAtmo,erreur)
case(atmosphere)
call MPI_Intercomm_create(sous_comm,0,&
MPI_COMM_WORLD,0,&
tag1, oceanAtmo,erreur)
call MPI_Intercomm_create(sous_comm,0,&
MPI_COMM_WORLD,2,&
tag2, visuAtmo,erreur)
case(visu)
call MPI_Intercomm_create(sous_comm,0,&
MPI_COMM_WORLD,1,&
tag2, visuAtmo,erreur)
477 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
select case(couleur)
case(ocean)
call code_ocean(sous_comm,oceanAtmo)
case(atmosphere)
case(visu)
call code_visu(sous_comm,oceanAtmo,visuAtmo)
477 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
end subroutine
subroutine code_atmo(sous_comm, oceanAtmo,visuAtmo)
! ...
call MPI_Comm_rank(sous_comm,rang,erreur)
call MPI_Recv(a,size_a,MPI_REAL,rang,tag,&
oceanAtmo,statut,erreur)
end subroutine
477 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
• problème multi-échelle
• architecture hybride (GPU/CPU)
• v nécessaire aux deux problèmes
478 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
Compléments
call MPI_Comm_test_inter(comm,flag,error)
call MPI_Comm_remote_size(comm,size,error)
call MPI_Comm_remote_group(comm,group,error);
480 / 488
Groupes, communicateurs et topologies Intra et inter-communicateurs
Rendez-vous dans le projet habituel pour les exercices , partie “organisation des
processus”.
481 / 488
Autres fonctionnalités
4 Types dérivés
1 Introduction
5 Groupes, communicateurs et topologies
2 Premiers pas avec MPI
6 Autres fonctionnalités
3 Communications
482 / 488
Autres fonctionnalités
483 / 488
Autres fonctionnalités
Mise en œuvre
Définition :
Création de processus durant l’exécution de l’application
486 / 488
Autres fonctionnalités
488 / 488