1.17k likes | 1.56k Views
Multithreading et Calcul Haute Performance. J-F. Méhaut , R. Namyst INRIA, ReMaP, LIP, ENS Lyon. Au menu. Introduction : contexte technologique Nouvelles archis: processeurs, réseaux, etc. Multithreading : quels intérêts? Définition, premiers contacts, partage mémoire Pause (10’)
E N D
Multithreading et Calcul Haute Performance J-F. Méhaut, R. Namyst INRIA, ReMaP, LIP, ENS Lyon
Au menu • Introduction : contexte technologique • Nouvelles archis: processeurs, réseaux, etc. • Multithreading : quels intérêts? • Définition, premiers contacts, partage mémoire • Pause (10’) • Multithreading distribué • Intérêts et difficultés • Quelques environnements • L’environnement PM2 • Conclusion
2 3 F (b) F (a) j=m j=1 j=3 j=2 G(A) 1 4 … i=n i=1 i=2 i=3 Architecture processeur Cray-TERA Applications Threads concurrents Programme séquentiel … Streams Pool d’instructions prêtes Pipeline d’instructions en cours d’exécution
Multi-threading Cray-TERA • Principe • Maintenir plusieurs threads (streams) actifs (40 à 80 streams => 90% utilisation de la machine) • Garantir une instruction prête à chaque cycle processeur • Dispositif matériel supportant • Gestion de plusieurs streams • Changement de contexte tous les cycles (3ns) • Jusqu’à 8 requêtes d’accès mémoire en attente pour un stream
Caractéristiques du processeur Cray-TERA • Horloge • 333 MHZ • Accès mémoire • 2,8 Gbytes/seconde bande passante • Emission/réception d’un paquet par cycle • Pas de cache de données, cache instr 2Mbytes • Multiprogrammation/concurrence • 16 domaines de protection • 128 streams (32 registres, 1 Program Counter)
Enjeux • Trouver le bon niveau de parallélisme • Besoin de travail (threads) pour saturer la machine • Quatre sources potentielles de parallélisme • Applications (jobs) • Threads • Boucles • ILP (Instruction-Level Parallelism) • Compilateur/paralléliseur • Marché restreint • Une machine installée à San Diego
PC Commutateur Myrinet/BIP Cluster computing • Architecture homogène, faiblement hétérogène • Grappes (Cluster, COW), machines // • PC, stations de travail • SCI, Myrinet, Giganet, MPC, ... • Protocoles de communication • BIP, SISCI, SciOS, VIA, TCP, UDP, ...
Motivations pour le haut-débit • Performances des communicationsAtteindre le niveau de performance des machines parallèles avec les équipements du marché (PC ou station de travail) Minimiser la latence, maximiser le débit • Thématiques de recherche • Matériel • Commutateurs, cartes d’interface • Commutations, routage • Logiciel • Interfaces de communication (AM, FM, BIP, …) • Env. de programmation (MPI, PM2, Nexus,…)
Myrinet • Objectifs • Performances en communication équivalentes à celles des supercomputers • Quelques microsecondes en latence • Atteindre le Gbps en bande passante • Caractéristiques • Carte d’interface programmable • Protocole : carte d’interface et le host • Utilisé pour implémenter des environnements de programmation
Host Host Host Host Carte d’interface Carte d’interface Carte d’interface Carte d’interface Carte d’interface Carte d’interface Myrinet commutateur Myrinet commutateur Crossbar complet Câble 2,6 Gbps full duplex Host Host Myrinet : Description technique • Routage • Statique à la source (entête consommé progressivement) • Wormhole
Memory PCI Bridge DMA Controler PCI Bus Packet Interface Lien Myrinet RISC LANai Myrinet : cartes d’interface • Matériel • 66MHz cpu (LANai) • 1 Mbyte SRAM • 3 DMA (lien entrée, lien sortie, mémoire du host) • Interface au bus PCI • Logiciel • LANai Control Program (LCP) • Performance (BIP/Myrinet) • 6 microsecondes latence • 127 Mbytes/sec bande passante
SCI*(Scalable Coherent Interface) • Réseau à capacité d’adressage • Adressage des mémoires distantes • Lecture/écriture distante sans interruption du processeur distant • Support matériel pour mémoire partagée * Emmanuel Cecchet (Sirac, INRIA Rhône-Alpes)
SCI : caractéristiques techniques • Scalable Coherent Interface • Matériel standard (PC, station Unix, …) • Architecture en anneau et/ou commutateur • Evolutif jusqu’à 64 Knœuds • Bande passante de 500 Mo/s (4 Gb/s) full-duplex • Pas de cohérence sur PCI (bus d’entrées/sorties) * Emmanuel Cecchet (Sirac, INRIA Rhône-Alpes)
SCI : performances • Latence : 2.5 ms (écriture de processus à processus) • Débit : 70 Mo/s • Verrou : < 10 ms (fetch&add)
Comms : remarques préliminaires • Règle des 80/80 • 80% des messages sont de taille inférieure à 256 octets • 80% du trafic provient de messages d’une taille supérieure à 8KB • Nouvelles approches • Latence faible pour les petits messages • Bande passante importante pour les gros messages • Coût des protocoles traditionnels
Protocole système (TCP/UDP/IP) Réseaux 10 Mb Réseaux 100 Mb Réseaux Gb Communications système • Evolutions technologiques • Coûts logiciels des protocoles
Comm. en contexte utilisateur Interface • Recherches académiques • Active Messages (Berkeley) • Illinois Fast Messages (Urbana) • U-Net (Cornell) • MPC (Paris6, Versailles) • BIP (Lyon) • Interface de bas-niveau • Cibles pour les supports d’exécution • Standard industriel : VIA • Participation des industriels • Etendre le spectre des applications Processus OS
VIA : Virtual Interface Architecture Sockets, MPI,Legacy, etc. VI VI VI C COMP S R S R S R VI Consumer Host VI User Agent (“libvia”) VI Kernel Agent (Slow) User-Level (Fast) Descriptor Read, Write Open, Connect, Map Memory Undetermined Doorbells RequestsCompleted NIC VI-Capable NIC
Giganet : Cartes VIA Application Winsock API VI API TCP/IP With VIA 50 versus 7000 instructions NDIS Native VI Interface Fast Fastest
™ • Commutateurs • Cartes d’interface • Administration du réseau • cLAN pour Windows • cLAN pour Linux
Supports d’exécution parallèle • Avantages pour les utilisateurs • Abstractions de haut niveau • Portabilité des applications • Efficacité ! Applications Interface de programmation (API) Support d’exécution // Systèmes d’exploitation Architectures parallèles et distribuées
Le multithreading :quel(s) intérêt(s) ? Introduction et rappels
Rappel : les processus lourds • Caractéristiques • Entité active directement supportée par l’OS • Flot d’exécution • Espace d’adressage privé • Ressources systèmes • Exécution séquentielle • Coût de gestion élevé • Allocation des ressources • Appels systèmes
processeur processeur processeur Processus lourds (bis) • Ressources “kernel” + données “user” Espace utilisateur Processus Processus Processus Ordonnanceur Noyau
Threads : Motivations • Difficulté de programmation • Fil d’exécution unique une seule chose à la fois ! • Partage de données laborieux • Performances • Opérations de base coûteuses • Recouvrement des opérations d’E/S difficiles
Simplicité de programmation • Objectif • Mener plusieurs activités indépendantes au sein d’un processus • Exemples • Simulations • Serveurs de fichiers • Systèmes d’exploitation (!) • Seule solution (?) • Automate à états finis implanté « à la main » (sauvegardes d’états)
Structure d’un OS monolytique • Exemple • Séquence infinie d’opérations courtes • Ordre et fréquence des scrutations ? for (;;) { if(networkMsgIn()) getNetworkMsg(); if(kbdReady()) getKey(); if(diskBlockReady()) handleDiskBlock(); … }
Systèmes multiprogrammés • Exécution indépendante des activités • Concurrence entre les différents traitements for (;;) { wait for key stroke; getKey(); } for (;;) { wait for network msg; getNetworkMsg(); } for (;;) { wait for disk block; handleDiskBlock(); }
Processus serveur classique • Sérialisation des requêtes • Pas de recouvrement des E/S • Exploitation SMP délicate • Prise en compte de priorités ? client serveur OS OS
Sur l’efficacité des E/S • Caractéristiques du serveur de fichiers • Tps de traitement d’une requête = 15ms • Tps supplémentaire pour l’accès disque = 75ms (pour 1/3 des requêtes) • Débit sans/avec recouvrement des E/S • Sans recouvrement • 25 requêtes/seconde • Avec recouvrement • 33.33 requêtes/seconde (+33%)
Les processus légers • Principe • Détacher flot d’exécution et ressources • Introduits dans divers langages & systèmes • Programmation concurrente • Recouvrement des E/S • Exploitation des architectures SMP thread ressources
Caractéristiques de base • Thread = pile + contexte • Partage de ressources • Code, tas, … : espace d’adressage • Fichiers ouverts • Table des traitants de signaux • Opérations de base performantes • Création, destruction • Synchronisation, commutation de contextes • Création d’un processus léger • Adresse de fonction à exécuter + paramètres
Performance des threads • Opérations critiques • Création/destruction (gestion mémoire) • Changement de contexte (temps-partagé) • Synchronisation (mode utilisateur) • Programme d’évaluation • Création d’une activité (processus, thread)+ synchronisation (terminaison de l’activité)
Repères historiques • L’ancêtre : les coroutines • Entrelacement explicite des exécutions • Langages : Simula (67), Modula2 (82) • Primitives clés : create + resume • Les threads dans les systèmes • Cthread (Mach) -> DecThread -> PThread (~90) • Chorus, Solaris (87), winNT, IRIX, Linux, etc. • Les threads dans les langages • Ada (83), Java, etc. • C++ //, Eiffel //, etc.
Le multithreading :quel(s) intérêt(s) ? Premier contact
L’interface POSIX-Threads • Interface de programmation standard pour Unix • Portabilité des applications • Solaris, IRIX, HP-UX, Linux, etc. • Fonctionnalités • Création/destruction de threads • Synchronisation • Ordonnancement, priorités • Signaux • Etc.
Exemple: création • Création d’un nouveau thread • Éventuels attributs dans la structure attr • Exécution de start_func avec le paramètre arg • *pid est l’identificateur du thread créé int pthread_create( pthread_t *pid, pthread_attr_t *attr, void * (*start_func)(void *), void *arg);
Attente de fin d’exécution • Attente de la terminaison du thread pid • Récupération de son code de retour status • On peut contourner ce mécanisme en « détachant » les threads : int pthread_join( pthread_t pid, void **status); int pthread_detach( pthread_t pid);
« Hello World! » #include <stdio.h> #include <pthread.h> void *func(void *arg) { printf(“Thread %x says %s\n”, pthread_self(), arg); return NULL; } int main(void) { pthread_t pid; pthread_create(&pid, NULL, func, “Hello World!”); printf(“This is the main thread\n”); pthread_join(pid, NULL); return 0; }
Attributs • Ensemble fixé de caractéristiques • Utilisé à l’initialisation • Threads, verrous, variables de condition, etc. • Threads • Priorité • Pile : taille, emplacement • Détaché : oui/non • Type d’ordonnancement • Verrous • Inversion de priorités, récursivité
Attributs : exemple #include <stdio.h> #include <pthread.h> void *handle_request(void *arg) { … } int main(void) { … pthread_attr_t attr; for(;;) { fd = accept(sock, …); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(NULL, &attr, handle_request, fd); } }
Exemple bis : pile • À manipuler avec précaution ! • Quelle taille de pile choisir ? • Comment prévenir/détecter les débordements ? pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 128*1024); pthread_create(NULL, &attr, func, NULL);
Le standard OpenMP • Interface pour écrire des applications multithreads portables (sur SMP) • Directives de compilation (C, C++, Fortran)+ routines • Objectif = simplicité + portabilité • Constructeurs + fabricants de logiciels + etc. • Modèle de programmation • « Fork-Join » • Parallélisation des boucles (#pragma omp)
Le multithreading :quel(s) intérêt(s) ? Partage mémoire efficace
Les threads et la mémoire • Chaque thread possède sa propre pile • Variables locales « privées » (visibilité) • Les threads partagent l’espace d’adressage • Variables globales • Tas (malloc) • Variables locales (piles) également ! • Intérêt • Communications par pointeurs ! • Parallélisation de programmes séquentiels aisée ?
Problèmes de réentrance • Exemple simple : int glob = 0; void *inc(void *arg) { int i; for(i=0; i<100; i++) glob++; } int main(void) { pthread_create(&t1, NULL, inc, NULL); pthread_create(&t2, NULL, inc, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); printf(“glob = %d\n”, glob); } Résultat ?
Mov @glob, $r1 Inc r1 Mov @glob, $r1 Inc r1 Mov $r1, @glob … Mov $r1, @glob Mov @glob, $r1 Inc r1 Mov @glob, $r1 Inc r1 Mov $r1, @glob … Explication glob++ n’est pas forcément une opération atomique Scénario d’exécution concurrente par 2 threads : Mov @glob, $r1 ; charger Inc r1 ; incrémenter Mov $r1, @glob ; enregistrer Mov $r1, @glob
Outils pour la synchronisation • Exclusion mutuelle : les verrous • Synchronisations plus complexes : • Variables de condition (cf moniteurs de Hoare) • pthread_cond_wait • pthread_cond_signal, pthread_cond_bcast int glob = 0; void *inc(void *arg) { for(i=0; i<100; i++) { pthread_mutex_lock(&mutex); glob++; pthread_mutex_unlock(&mutex); } }
Code réentrant • « code demeurant correct lorsqu’il est exécuté simultanément par plusieurs threads » • Exemples typiques • Fonction n’utilisant que des variables locales • Code protégé par un verrou • Quid du code que l’on écrit pas soi-même ? • Malloc, free, …, la bibliothéque standard • Fonctions « MT-safe » • Option –D_REENTRANT • Certains prototypes changent…