4.2 Parall´elisation des noyaux
4.2.2 Restructuration des acc`es-m´emoire
probl`eme. A ce point, nous disposons d’algorithmes pour extraire le parall´elisme amorphe inh´erent`
`a chaque noyau. Les tˆaches extraites sont suffisamment fines pour laisser `a l’ordonnanceur la latitude n´ecessaire au r´e´equilibrage dynamique de charges33. Ainsi il nous reste `a g´erer l’aspectdata-intensive.
Pour am´eliorer la r´eutilisation des donn´ees en cache et minimiser la latence des acc`es-m´emoire, il faudrait restructurer les insertions et suppressions de donn´ees de chaque noyau. En fait ces indirections m´emoire peuvent impacter de mani`ere significative les performances de ces noyaux34 surtout s’ils ont une faible intensit´e arithm´etique35. Le probl`eme est qu’il nous est impossible de les inf´erer puisque les d´ependances de donn´ees varient selon la mani`ere dont la topologie ´evolue36. Dans ce cas, comment allons nous d´ebrouiller pour restructurer nos acc`es-m´emoire de mani`ere `a att´enuer les p´enalit´es relatives `a ces indirections ?
4.2.2.1 Refonte en vagues synchrones
principe. Afin d’att´enuer leur irr´egularit´e, nous restructurons les noyaux en vagues synchrones en nous inspirant du paradigmemulti-bsp37[170]. Ici les instructions d’un noyau sont structur´es en une s´equence de vagues de tˆaches, chaque vague ´etant constitu´ee d’une phase decalcul local, d’une phase decommunicationet d’unebarri`ere de synchronisationcomme montr´e `a la table4.2. Ici l’avantage est triple :
• coalescence: les communications des threads sont regroup´ees en vagues de mani`ere `a att´enuer la latence m´emoire38. Les ´ecritures en m´emoire partag´ee sont ainsi effectu´es de mani`ere coalescente, ce qui est un aspect crucial sur les architectures massivement multithread39.
33`a condition d’ajuster la granularit´e
34C’est particuli`erement vrai pour la simplification comme illustr´e sur la courbe de la figureB.9en annexe.
35L’intensit´e arithm´etique est le ratio de calcul utile sur le nombre d’acc`es de donn´ees. Elle est mesur´ee enflop/byte
36Du coup, nous ne pouvons pas recourir aux techniques usuelles decache blocking, ni pr´eserver un placement de donn´eescache-aware, comme ce qui se fait en visualisation haute performance [57,58]
37Il s’agit d’unbridging-modelentre le mat´eriel et l’algorithme : il permet de concevoir des algorithmes tenant compte des param`etres hardware li´es `a la communication (bande-passante et latence `a chaque niveau de la hi´erarchie m´emoire) tout en restant suffisamment g´en´erique pour la portabilit´e de l’application.
38Plus pr´ecis´ement, elles sont coalesc´ees par thread et effectu´es dans une seule phase d’une vague synchrone.
39C’est particuli`erement vrai pour legpgpu.
c2018.HOBYRAKOTOARIVELO
112 4.2. Parall´elisation des noyaux
• moins de communications: elle permet de r´eduire la fr´equence de mise `a jour de donn´ees entre threads ainsi que les synchronisations associ´ees40.
• portabilit´e: elle offre un juste milieu entre prise en compte descontraintes hardwareetg´en´ericit´e pour la portabilit´e des performances. De plus, elle fournit un mod`ele de coˆut li´e aux param`etres hardware, ce qui peut-ˆetre utile pour le r´e´equilibrage de charges41
Table 4.2: Structuration des noyaux.
vagues
noyau 1 2 3 4 5
raffinement : filter steiner apply repair – simplification : filter graph indep apply repair relaxation : filter graph match apply repair lissage : graph color qualit apply –
Contributions
Approach
Main idea
I explicit parallelism extraction.
- express data dependencies into a graph.
- extract a subset of compatible stencils.
- kernel granularity related to its graph size/structure.
I synchronization for topology consistency.
synth`ese. Les vagues synchrones relatives `a chaque noyau sont r´esum´ees `a la table4.2. Les d´etails de d´ecomposition des noyaux ainsi que leurs complexit´es th´eoriques42 sont expliqu´es dans[RLP16]43. Sur cette table, les vagues
• filtercorrespond au filtrage des points ou mailles actives selon un crit`ere num´erique.
• graphcorrespond `a la construction du graphe de conflits ou mailles `a appairer.
• applycorrespond `a l’application proprement dite du noyau.
• repaircorrespond `a l’´epuration des listes d’incidence inconsistantes.
• steinercorrespond au calcul et r´esolution des indices de points desteiner.
En fait tout l’int´erˆet de ce formalisme r´eside dans la coalescence des communications44 des threads, ce qui permet de minimiser les synchronisations tout en att´enuant la latence des acc`es-m´emoire. Bon nombre de biblioth`eques existent pour rendre ces communications transparentes [171–174]. N´eanmoins cela est inadapt´e dans notre cas, puisque nous voulons contrˆoler finement la mani`ere dont les transferts de donn´ees sont effectu´es en m´emoire partag´ee.
4.2.2.2 Insertions de mailles
Pour le raffinement, nous disposons de plusieurs patterns de d´ecoupage selon le nombre d’arˆetes
”longues” conform´ement `a une m´etrique donn´ee. Ainsi il est a priori impossible de pr´edire en amont le nombre de cellules `a ins´erer. Pour y rem´edier, une mani`ere simple serait de les stocker localement jusqu’`a ce que chaque thread ait termin´e de traiter toutes les mailles qui lui ont ´et´e assign´ees, puis de les copier de mani`ere synchronis´ee au sein du conteneur partag´e dans une seule vague, comme ce qui est impl´ement´e dansPragmatic[199,167]. Le probl`eme est que cela induit un nombre important d’acc`es-m´emoire, ce qui peut ˆetre r´edhibitoire en contextenuma.
principe. Pour contourner le probl`eme pr´ec´edent, nous scindons le noyau en deux phases synchrones relatives au filtrage et `a l’application, de sorte `a pouvoir inf´erer explicitement le nombre de cellules `a ins´erer. Ainsi cela va nous permettre de trouver le bonoffsetd’indices par thread.
Concr`etement, nous stockons le pattern par maille `a appliquer dans un tableau pattern durant la phase de filtrage. Ensuite, chaque thread ti effectue une r´eduction sur pattern dans son espace d’it´erations dn/pe[i, i+ 1], avec n le nombre de tˆaches et p le nombre de threads. Le r´esultat est
40Elle minimise ainsi les contentions d’acc`es aux conteneurs partag´es, typiquement les files de taches associ´e `a chaque noyau et la structure de donn´ees topologiques
41Dans ce cas, elle permet de d´ecider s’il faut migrer les mailles ou non selon le coˆut estim´e du prochain it´er´e.
42`a l’aide du mod`ele de pontQueuing Shared Memory.
43dans le cas planaire mais c’est exactement pareil en surfacique
44par mise `a jour synchronis´ee de variables en m´emoire partag´ee.
c2018.HOBYRAKOTOARIVELO
pourtde0`adlog2ne −1faire
pouride0`an−1faire en parall`ele sii <2talors
off[t+1]i ←off[t]i sinon
off[t+1]i ←off[t]i +off[t]i−2t
fin si barri`ere fin
3 2 1 2 3 2 1 3 3 2 3 1 3 2 3 2 pattern
n tasks 10 10 45
0 8 9 9
off
0 8 17 18 0 8 17 35
Figure 4.10: Pr´ecalcul des r´ef´erences par thread pour l’insertion de mailles. Les motifs de raffinement associ´es `a chaque maille sont explicitement r´ef´erenc´es dans un tableau, et chaque thread d´etermine la quantit´e de mailles qu’il doit cr´eer par une r´eduction partielle.
Enfin unprefix-sumest effectu´e pour d´eterminer les offsets associ´es `a chaque thread.
Open issue
Data placement
Spatial locality: geometric proximity ) memory locations proximity.
7 index reordering (Hilbert, Reverse Cuthill-Mckee): difficult to parallelize, huge overhead.
7 octree, cache-oblivious (Packed-memory, Van Emde Boas): rebalance and memory costs.
I workaround: memory block o↵sets precomputation, and asynchronous writes.
cells to be stored (1 thread per core)
fully asynchronous: 7remote accesses
cells 1 8 2 11 12 3 4 13 14 7 9 6 10 5 16 15
DRAM 1 (close to core 1) 1 8 2 11 12 3 4 13
DRAM 2 (close to core 2)
14 7 9 6 10 5 16 15
block precomputing: 1remote access
cells 1 2 3 4 7 6 5 8 11 12 13 14 9 10 16 15
DRAM 1 (close to core 1)
1 2 3 4 7 6 5 8
DRAM 2 (close to core 2)
11 12 13 14 9 10 16 15
SLIDE 9/13
Figure 4.11: Impact des patterns d’insertion de mailles sur le placement m´emoire en contexteNUMA.
ensuite stock´e dans un tableauoffset[i] de taillep. Finalement, un prefix-sumest effectu´e suroffset[i]
afin de d´eterminer les plages d’indices [ki, ki+1] par thread.
L’exemple de la figure 4.11 illustre l’impact du pattern d’insertion de mailles sur le placement m´emoire. Ici on a deux threads punais´es sur deux cores situ´es sur deux sockets distincts. Dans le premier cas, les indices des mailles sont obtenus de mani`ere asynchrone et les threads ins`erent directe-ment dans le conteneur partag´e. Dans le second cas, les plages de blocs-m´emoires sont pr´ed´etermin´es dans une premi`ere vague, et les insertions sont r´ealis´ees de mani`ere coalescente dans une vague `a part.
Dans ce cas, les blocs de donn´ees associ´es `a chaque thread sont r´eellement stock´es dans la m´emoire la plus proche du core d’une part, et les mailles voisines g´eom´etriquement le sont ´egalement en m´emoire.
4.2.2.3 R´eduction de donn´ees
A ce point, chaque noyau est structur´e de mani`ere `` a ce que la communication des threads se fasse de mani`ere coalescente. De mani`ere concr`ete, elle consiste en une mise `a jour synchronis´ee de donn´ees en m´emoire partag´ee. En fait les points et mailles ainsi que les donn´ees aff´erentes sont stock´ees dans des tableaux unidimensionnels de sorte qu’elles sont r´ef´erenc´ees par des adresses contig¨ues en m´emoire. Dans ce cas, les primitives d’insertion, de suppression ou de mise `a jour des conteneurs
c2018.HOBYRAKOTOARIVELO
114 4.2. Parall´elisation des noyaux
partag´es doivent ˆetre synchronis´ees. Ici le but est de montrer comment les r´eductions45 de donn´ees sont r´eellement effectu´es par les threads.
r´eductions. Les boucles de work-sharing impliqu´ees dans chaque vague synchrone n´ecessitent le recours `a un m´ecanisme de r´eduction de donn´ees au sein d’une file de taches ou d’un conteneur partag´e. Ici les deux points critiques concernent la minimisation des points de synchronisations et la pr´eservation du placement m´emoire initial. En fait il est compliqu´e de concilier les deux : l’asynchronisme implique l’insertion non d´eterministe des donn´ees tandis que le placement fin des donn´ees implique n´ecessairement plus de points de synchronisations. Partant de constat, nous pro-posons deux strat´egies de r´eduction. Elles sont bas´ees sur la pr´ed´etermination des offsets off[tid] `a partir desquels chaque thread tidpeut initier sa copie de donn´ees dans le conteneur partag´e R. Ces deux strat´egies sont :
• asynchrone : ici off[tid] est calcul´e de mani`ere non-d´eterministe `a partir de la taille nR du conteneur partag´eR. `A l’instantt,n[t]R est incr´ement´e de mani`ere atomique tout en r´ecup´erant en cache son ancienne valeurn[t−1] qui sera assign´ee `a off[tid] : ce m´ecanisme s’appelle la cap-ture atomique. Ainsi le thread tid sait exactement qu’il doit copier ses donn´ees aux indices [n[kR−1], n[kR−1]+|`tid|], o`u `tid d´esigne sa liste locale de donn´ees. Notons qu’on a bien un asyn-chronisme puisque le thread tid n’attend pas que la r´eduction se termine pour faire du calcul local. Par contre, la plage d’adresses associ´ee `a tid est compl`etement arbitraire et varie d’une ex´ecution `a une autre.
• numa-aware : cette fois off[tid] est mis `a jour par le biais d’un prefix-sum de sorte que les plages d’adresses soient assign´ees de mani`ere d´eterministe aux threads. En fait elles d´ependent de l’indicetiddu thread qui lui est punais´e statiquement sur un core : cela permet ainsi d’allouer une plage d’adresses la plus proche possible de ce core. Notons qu’ici on a log(p) r´eductions et donc autant de points de synchronisation.
Listing 4.1: quasi-asynchrone
off[tid] = sync fetch and add(size,nb);
// tasks:null si on veut juste calculer les offsets if(shared != nullptr)
Notons que ces m´ecanismes de r´eduction n’impliquent que des variables enti`eres (heap, shared).
Pour minimiser le volume de donn´ees transf´er´ees en m´emoire partag´ee, les r´eductions ne sont utilis´ees que pour la copie d’indices. Ainsi les cellules et les donn´ees qui leur sont associ´ees (normales, tenseurs etc.) sont directement cr´e´es et initialis´ees `a leur emplacement final, contrairement `a l’approche de Rokos [199]. ´Etant donn´e leur caract`ere data-intensive, ces multiples transferts de donn´ees impactent les performances des noyaux de mani`ere significative, notamment en2D(sec4.2.3).