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