ALG & Architectures Parallèles
Programmation parallèle
Modèles, synchronisation & comparaison des langages
C/C++ · OpenMP
Rust
Java
Python
01 · Introduction
Même travail, plus de cœurs
×4plus rapide
01 · Concepts fondamentaux
Processus vs thread
Processusapplication en cours
isolérobusteéchanges lourds
Threadsous-unité d'un processus
mémoire partagéeultra-rapidedangereux
01 · Concepts fondamentaux
Tâche : le quoi, pas le comment
Tâches
Thread pool
Filtre photo · 4 zones
Tâche 1filtrer ↖
Tâche 2filtrer ↗
Tâche 3filtrer ↙
Tâche 4filtrer ↘
4 tâches · 3 threads · le système répartit
02 · Les problèmes
Race condition : compteur++ × 2
02 · Les problèmes
Deadlock & famine
Interblocagechacun attend l'autre
Faminetoujours doublé
02 · Les mécanismes
La boîte à outils
Mutex
un seul à la fois
race condition
Sémaphore
N jetons d'accès
pool limité de ressources
Condition
dormir jusqu'au signal()
attente active (100 % CPU)
Atomique
une étape indivisible
compteurs, sans verrou
Barrière
rendez-vous collectif
phases de calcul
02 · Les solutions
Problème → remède
Race conditionaccès simultané
Mutexautour des variables partagées
Atomiquespour les compteurs simples
Deadlockattente circulaire
Ordre stricttoujours A avant B
Timeouttry_lock() · 10 ms puis on relâche
File FIFOpremier arrivé, premier servi
Fair locksverrous équitables
03 · Bibliothèques de parallélisme
3 familles, 3 architectures
Mémoire partagée
multicœur local
OpenMPIntel TBBJavaC# TPLRust Rayon
Mémoire distribuée
clusters · 1 RAM par machine
MPI
GPU massif
des milliers de petits cœurs
CUDAOpenCLSYCLWebGPU
04 · OpenMP en C/C++
Fork–Join : un #pragma suffit
#include <omp.h>
void traiter(vector<double>& d) {
#pragma omp parallel for
for (int i = 0; i < n; ++i)
d[i] *= 2.0;
}
donnees[ ] · 1 000 000 éléments · 4 cœurs
0 → 249 999
250 000 → 499 999
500 000 → 749 999
750 000 → 999 999
04 · OpenMP en C/C++
Partager, privatiser, réduire
shared(y) · y += 1
private(x) · une copie par thread
#pragma omp parallel for reduction(+:somme)
#pragma ajouté petit à petit
schedule(dynamic)
1 seule machine (sinon MPI)
false sharing
GPU limité
05 · Rust
Fearless concurrency
src/main.rs
let v = vec![1, 2, 3, 4];
let mut total = 0;
v.par_iter().for_each(|x| {
total += x; // écriture partagée !
});
$ cargo build
error[E0594]: cannot assign to `total`,
as it is a captured variable in a `Fn` closure
--> src/main.rs:4:5
error: could not compile `demo`
REFUSÉ À LA COMPILATION
La règle du borrow checker
Sendtransférable à un autre thread
Syncpartageable entre threads
05 · Rust
Arc, Mutex & Rayon
Arc : plusieurs propriétaires · Mutex : un seul écrivain
// une seule modification :
donnees.par_iter_mut()
.for_each(|x| *x *= 2);
Work-stealing · les cœurs libres volent du travail
si ça compile, c'est thread-safe
perf du C/C++, sans GC
courbe d'apprentissage
deadlocks toujours possibles
06 · Java
De synchronized aux threads virtuels
1996
Java 1.0
synchronized
un moniteur par objet
public synchronized void
retirer(int montant) { … }
2004
Java 5 · java.util.concurrent
tryLock(2, s)abandon possible
ExecutorServicepool réutilisé
ConcurrentHashMapverrous fins
2023
Java 21 · Projet Loom
Threads virtuels
gérés par la JVM · ultra-légers
Executors
.newVirtualThreadPerTaskExecutor()
06 · Java
Threads virtuels : des millions
Threads OSlourds · quelques milliers
Threads virtuelsgérés par la JVM
≈ millierslimite du système
0threads virtuels
try (var ex = Executors.newVirtualThreadPerTaskExecutor()) { … }
serveurs web · I/O
API très riche
code simple, perf async
aucune sécurité à la compilation
verbeux (CompletableFuture)
07 · Python
Le GIL : un seul à la fois
multiprocessing 1 GIL / processus
calculer_carre × 4 :~4 s→~1 sI/O : les threads suffisent (GIL relâché)
07 · Python
Contourner le GIL
Le prix à payer
500 Mo500 Mo500 Mo500 Mo500 Mo500 Mo500 Mo500 Mo
= 4 Go
8 processus = 8 interpréteurs en mémoire
{ objet }
b'\x80\x04\x95…'
{ objet }
pickle à chaque échange
if __name__ == '__main__':obligatoire (Windows / macOS)
Bientôt
3.13+Mode sans GILvrai parallélisme avec threading
3.14Sous-interpréteursInterpreterPoolExecutor
08 · Synthèse
Comparaison
C/C++ · OpenMPun #pragma, performance brute
Rust · Rayonsi ça compile, c'est sûr
JavaAPI riche, threads virtuels
Pythonsimple, mais freiné par le GIL
appréciation qualitative · d'après l'analyse présentée
08 · Conclusion
Quel outil pour quel besoin ?
Accélérer un code C/C++ existant
OpenMP
Sécurité garantie et performance native
Rust · Rayon
Serveur avec des millions de requêtes I/O
Java · threads virtuels
Data science et prototypage rapide
Python · joblib
Problème trop grand pour une machine
MPI · cluster
Calcul massif sur matrices
GPU · CUDA
→ / espace : avancer · ← : reculer · F : plein écran · N : notes & minuteur · R : rejouer