11.4.1 : Introduction



Dans un monde idéal, il serait possible d'accélérer indéfiniment les programmes sans les modifier, en augmentant simplement la fréquence d'horloge du processeur qui dicte le rythme auquel les instructions sont traitées. Malheureusement, les limites physiques de cette approche ont été atteintes autour de 2005, et l'on ne peut aujourd'hui augmenter cette fréquence qu'à un prix prohibitif en termes de consommation d'énergie et de dissipation de chaleur.

À la place, les processeurs modernes tentent donc d'effectuer plus de calculs par cycle d'horloge. La vectorisation, que nous avons traitée au chapitre 11.3, est une approche très économe en silicium pour parvenir à ce résultat. Mais tous les algorithmes ne s'y prêtent pas, et il est souvent préférable de pouvoir exécuter plusieurs sous-programmes composés d'instructions indépendantes simultanément. On parle alors de calcul parallèle.

Une première forme de parallélisation consiste à faire travailler ensemble plusieurs ordinateurs, appelés nœuds de calcul. Cette forme de parallélisation, appelée calcul distribué, est la seule qui soit capable de passer à l'échelle indéfiniment à technologie informatique constante. Mais l'écriture d'un programme de calcul distribué performant est très difficile, car les nœuds ne peuvent communiquer que par le biais d'un réseau dont la bande passante est bien plus basse que celle des échanges CPU--RAM, donc la latence est très élevée par rapport aux temps de calcul, et où l'ordre de distribution des messages ne peut être que partiellement garanti.

Pour cette raison parmi d'autres, un parallélisme à grain plus fin a aussi été introduit au sein des CPU, le multi-cœur. Un processeur multi-cœur est capable d'exécuter plusieurs sous-programmes (threads) simultanément, en permettant à ceux-ci d'échanger des données très rapidement via la RAM et la hiérarchie de caches. Convenablement utilisée, cette interconnexion rapide facilite grandement la parallélisation de calculs nécessitant des communications fréquentes entre sous-programmes. Mais même dans ce cadre favorable, la communication reste bien plus onéreuse que le calcul, et l'on ne peut donc pas en abuser.

Le calcul distribué et les processeurs multi-cœur sont omniprésents au sein des centres de calculs comme le CC-IN2P3[77]Computational centre of IN2P3, car ce sont les seules infrastructures capables de traiter les volumes de données titanesques et toujours croissants de la Grille WLCG[71]WLCG : World-wide LHC Computing Grid, CERN dans des délais raisonnables. Un programme qui n'est pas capable d'exploiter ces ressources ne pourra donc pas contribuer aux analyses physiques à grande échelle couramment pratiquées à l'IN2P3.

Pendant de nombreuses années, les experts de la Grille ont su cacher l'existence du parallélisme multi-cœur et distribué aux physiciens et aux autres informaticiens, en tirant parti du fait que les analyses physiques manipulaient un grand nombre de données indépendantes. L'approche utilisée était de décomposer les données à traiter en blocs, et de lancer un exemplaire du programme d'analyse par cœur CPU du centre de calcul en ne lui confiant que ce sous-ensemble des données à traiter.

Mais malheureusement, cette approche atteint aujourd'hui ces limites. Comme le rapport capacité/prix et les performances de la RAM augmentent bien plus lentement que le nombre de cœurs des CPUs, il est de plus en plus souvent nécessaire de prendre explicitement en compte la nature multi-cœur des CPUs dans un programme pour faire bon usage des ressources mémoire. Et de nouvelles problématiques comme le traitement de données du télescope LSST ne se prêtent plus non plus à une distribution des calculs par découpage automatique des données d'entrée, car certaines étapes du calcul doivent prendre en compte une sous-partie des données trop grande pour un nœud de calcul individuel.

Par conséquent, les expériences de physique ont de plus en plus souvent besoin d'écrire des programmes qui prennent explicitement en compte le parallélisme du matériel de calcul. Dans ce chapitre, nous verrons donc quelles sont les difficultés techniques qui sont couramment rencontrées lors de l'écriture d'un programme parallèle, et quels outils peuvent être utilisés pour simplifier l'écriture de tels programmes.