Les systèmes à mémoire partagée, la consistance mémoire et la cohérence de cache
Les systèmes à mémoire partagée
L’une des classes les plus importantes des machines parallèles est la classe des multiprocesseurs à mémoire partagée. Dans ce type de machines parallèles, la communication résultant des opérations d’accès à la mémoire est implicite. On la trouve dans des systèmes comportant de quelques processeurs à des centaines de clusters souvent hétérogènes [Lenoski and Weber, 2014]. Les systèmes à mémoire partagée consistent en un ensemble de nœuds de calcul interconnectés par un réseau hiérarchique et composés de plusieurs cœurs se partageant l’espace mémoire auquel ils sont reliés via ce réseau, comme illustré dans les figures 2.2 et 2.3 [Culler et al., 1999].
La coopération et la coordination entre les cœurs sont accomplies en lisant et en modifiant des variables partagées. Une écriture d’un nœud de calcul est visible aux lectures des autres nœuds. Des opérations atomiques de synchronisation entre les processus indépendants sont établies. Les programmes parallèles, pour ces systèmes, sont structurés en segments privés pour les données privées et segments partagés se trouvant dans la même région partagée entre plusieurs processus ou threads du programme, comme illustré dans la figure 2.1 [Kumar et al., 1994]. Chaque cœur peut accéder à chaque emplacement mémoire avec différentes latences.
La latence d’accès à la mémoire est un des facteurs clés déterminant les performances d’un 9 les systèmes à mémoire partagée, la consistance mémoire et la cohérence de cache Figure 2.1 – Exemple d’un modèle mémoire pour un programme parallèle à mémoire partagée. tel système. Les optimisations proposées dans le but de réduire cette latence dans les systèmes multicœurs sont multiples [Alpern et al., 1994]. Une des solutions est d’introduire des mémoires locales servant de cache aux données [Wilson Jr, 1987].
Les modèles de mémoire
L’organisation de la hiérarchie mémoire est un élément clé dans la conception des systèmes à mémoire partagée. La latence d’accès à la mémoire a un impact important sur les performances d’un tel système. Cet accès peut adopter l’un des deux modèles suivants : Le modèle UMA L’approche la plus naturelle pour construire des systèmes à mémoire partagée est de maintenir un accès uniforme à la mémoire, comme illustré dans la figure 2.2.
Chaque accès à la mémoire est un message envoyé sur le bus/réseau d’interconnexion [Protic et al., 1998]. Le modèle NUMA L’approche alternative est d’assigner à un groupe de processeurs une mémoire, comme illustré dans la figure 2.3. Le contrôleur de la mémoire locale détermine si l’accès est à la mémoire locale ou bien une transaction à envoyer sur le réseau. L’accès aux données privées est souvent effectué localement [Schweizer and Carroll, 1990]. Dans les systèmes à mémoire partagée, la hiérarchie mémoire peut suivre trois modèles qui dépendent fortement de la taille du système considéré.
Les systèmes d’interconnexion
Avec l’émergence des systèmes multicœurs, un intérêt particulier a été porté aux techniques d’interconnexion. En effet, les goulots d’étranglement liés aux communications peuvent compromettre la performance. La conception de nombreux systèmes a été basée sur la communication via des bus. Cependant, ils sont vite arrivés à saturation avec l’augmentation du nombre de cœurs [Dally and Towles, 2004a]. Les systèmes hétérogènes les plus récents communiquent à travers un réseau d’interconnexion. Le choix d’un système d’interconnexion est souvent fortement lié aux objectifs, de performances, de coûts et de consommation en énergie, de chaque constructeur [Rixner
Figure 2.4 – Exemple d’un système basé sur une interconnexion par bus. et al., 2000]. Dans ce qui suit, nous présentons les 3 systèmes d’interconnexion les plus communs : les bus, les crossbars et les réseaux. Les bus Les bus se composent d’un ensemble de fils partagés entre les composants. Un bus peut être vu comme étant un canal unique partagé entre plusieurs nœuds de calcul. La figure 2.4 illustre un ensemble de cœurs connectés à la mémoire à travers un bus. La fréquence d’un bus dépend de la longueur des fils utilisés pour connecter tous les composants à ce bus. Cette contrainte de connexion de tous les composants à un seul bus limite sa fréquence avec l’augmentation du nombre de cœurs dans le système.
Le trafic dû aux requêtes d’accès à la mémoire et sa mise à jour , contribue à augmenter significativement la charge du bus partagé [Kumar et al., 2005]. A tout instant, une seule requête est exécutée, c’est pourquoi, les interconnexions basées sur les bus ne sont plus adaptées aux systèmes multicœurs. Afin d’y remédier, des bus multiples ont été conçus dans les systèmes les plus récents. Ces bus sont répartis selon les types des composants et les messages véhiculés dans le système, ainsi que d’autres caractéristiques du système [Salminen et al., 2002]. A titre d’exemple, le protocole de bus AMBA de ARM spécifie un bus haute performance (AHB) et un bus périphérique (APB) dans le même système. Plus de détails sont donnés dans la section 3.1.2.