Programmer en Multicore avec C++ moderne
Objectifs pédagogiques
- Maîtriser les enjeux de la programmation Multicore avec le C++ moderne
- Concevoir et développer des applications à base de threads et de processus
- Synchronisation des threads et protection des variables partagées
- Les modèles mémoire de C++ et les opérations sur les variables atomiques
- Concevoir des structures de données sans verrou
- Maîtriser les modèles de programmation parallèle et les librairies disponibles
- Déboguer et profiler des applications Multicore
Nouveautés de C++ moderne
- Initialisation uniforme
- Les expressions constantes généralisées (constexpr).
- Espaces de nommage impriqués (nested namespaces)
- Les directives =delete, =default.
- Délégation de constructeurs.
- La surcharge explicite de la virtualité (override)
- Les méthodes et les classes « final »
- Les énumérations fortement typés
- Le mot-clé auto et boucle sur un intervalle.
- Les rvalues-reference et la sémantique de déplacement (move constructeur et surcharge de l’opérateur d’affectation par déplacement)
- Foncteurs, pointeurs de fonctions, et les lambda expressions.
Travaux pratiques
Réécriture d’un code C++ existant en C++ moderne et la comparaison des deux implémentations.
Programmation parallèle et concurrente
- Parallélisme vs concurrence
- Architecture en mémoire partagée vs mémoire distribuée.
- Architectures des processeurs et parallélisme
- Modèles de fonctionnement des threads
- Apport des threads dans une application industrielle
- Gestion des stacks et « call stack » dans les threads.
- Apport et objectifs de la programmation parallèle.
Travaux pratiques
Configuration optimale du système, du réseau et des services.
Gestion des threads
- Création de threads
- Attente de la fin d’un thread
- Exécution des threads en arrière-plan
- Transmission d’arguments à une fonction de thread
- Transfert de propriété d’un thread
- Choix du nombre de threads à l’exécution
- Fonctions de gestions d’un thread : yield , get_id , sleep_for, sleep_until
- Débogueurs multithreads.
Travaux pratiques
Création et gestion de threads selon plusieurs modèles
Partage de données entre les threads
- Problèmes liés au partage de données entre threads
- L’exclusion mutuelle et la protection des données paratagées avec les mutex
- Structuration du code pour protéger les données partagées
- Repérage des conditions de concurrence inhérentes aux interfaces
- Blocage : problème et solution
- Verrouillage flexible avec std::unique_lock
- Transfert de propriété de mutex
- Protection des données partagées pendant l’initialisation
- Protection des structures de données rarement mises à jour
- Verrouillage récursif
Travaux pratiques
Différents cas pour résoudre les problèmes liés au partage des données entre threads
Synchronisation des opérations concurrentes
- Attente d’un événement ou d’une autre condition : variable de condition
- Attente d’événements ponctuels avec des futures : promesse et future
- Attente avec une limite de temps
- Utilisation de la synchronisation des opérations pour simplifier le code
Travaux pratiques
Conception et implémentation d’une structure de données thread-safe avec les mutex (pile, file, etc)
Le modèle mémoire de C++ et les opérations sur les types atomiques
- Concepts fondamentaux du modèle de mémoire en C++
- Opérations et types atomiques en C++
- Synchronisation des opérations et imposition de l’ordre
- Ordre de la mémoire pour les opérations atomiques
- Ordre des opérations non-atomiques
Travaux pratiques
Implémentation de sémaphores avec les variables atomiques
Conception et implémentation d’une structure de données thread-safe non bloquante