Reconciliation of working life and parental responsibilities

I dokument Fifteen Years with the Norma Research Programme, Anniversary Volume Numhauser-Henning, Ann; Rönnmar, Mia (sidor 51-56)

Comme on le voit très clairement dans le code ci-dessus, le al ul d u ha p pou u e cellule est indépendant du calcul du champ des autres cellules. De plus, chaque cellule va exécuter exactement le même code, en travaillant sur des données différentes uniquement pour ce qui est de la position de la cellule traitée. De plus, pour chaque cellule, un nombre assez important de calculs est nécessaire : les cellules se trouvant dans un espace à trois dimensions, la moindre multiplication entre deux vecteurs nécessite plusieurs multiplications et plusieurs additions de nombres flottants. Toutes ces caractéristiques font ue es algo ith es so t pa faite e t adapt s à l utilisatio de GPU pou pa all lise les calculs.

Pou e ui est de l i pl e tatio su GPU, la différence majeure va être la disparition des trois boucles « for » de l algo ith e s ue tiel pe etta t de pa ou i l e se le de l espa e. À leu pla e, le ke el KernelCalculChampGravitation, qui sera exécuté sur le

185 GPU, sera appelé autant de fois u il a de ellules oi Code 4-7). On obtient ainsi une parallélisation en autant de threads u il a de ellules da s l espa e o sid . E ept dans le cas d u espa e t s duit, ette pa all lisatio est la ge e t suffisa te pou utilise tous les œu s du GPU.

void CalculChampGravitation(

std::vector< Particule * > & inParticules,

Espace * inEspace ) { dim3 dimGrille; dim3 dimBloc; Particule * particules_gpu; VecteurF * treilli_gpu; VecteurF * champ_gpu;

// Copie des donnees du cpu vers les tableaux gpu

[...]

calculDimensionGrilleEtBloc(

inEspace->Sx * inEspace->Sy * inEspace->Sz,

dimGrille,

dimBloc );

KernelCalculChampGravitation<<< dimGrille, dimBloc >>>(

particules_gpu,

inParticules.size()

treilli_gpu,

champ_gpu );

// Copie retour des donnees du gpu vers les tableaux cpu

[...] }

Code 4-7 : Extrait simplifié de l'appel du kernel de calcul du champ de gravitation sur le GPU.

Le kernel correspondant est par ailleurs très simple (voir Code 4-8). Il al ule tout d a o d l i di e du th ead. Puis, e fo tio de et i di e, il appelle le calcul du champ de gravité pour la bonne cellule. Ce calcul est réalisé de façon semblable à celui de la fonction CalculChampGravitationCellule vu précédemment (voir Code 4-6).

186

__global__ void KernelCalculChampGravitation(

Particule * inParticules,

unsigned int inNbParticules,

VecteurF * inTreilli,

VecteurF * inChamp ) {

unsigned int threadIdGlobal = calculerIdGlobal();

CalculChampGravitationCellule_gpu( inParticules, inNbParticules, inTreilli[ threadIdGlobal ], inChamp[ threadIdGlobal ], ); }

Code 4-8 : Kernel permettant le calcul du champ de gravitation.

L appel est do t s se la le à e ui se fait e s ue tiel. Le poi t le plus e li à introduire des erreurs est la réalisation des copies de mémoire entre la mémoire du CPU et elle du GPU a a t l appel du ke el pou les do es d e t es et une fois celui-ci terminé (pour les résultats).

Le p o l e ajeu de l utilisatio des GPU est, o e ela a t dit p de e t, la late e des a s oi e. O , pou al ule le ha p e ha ue poi t de l espa e, il est nécessaire à chaque fois de pa ou i l e se le des pa ti ules pou e suite so e le sultat du ha p p oduit pa ha ue pa ti ule e e poi t de l espa e. Si le o e de particules est grand, par exemple une centaine, le calcul du champ de gravitation, qui nécessitera toujours quat e fois plus d a s à des e tie s u pou la asse et t ois pou la position –voir Code 4-9), réalisera donc 400 accès. Ces accès vont alors avoir un impact très i po ta t su le te ps d e utio du ode.

187 void CalculChampGravitationCellule_gpu(

Particule * inParticules,

unsigned int inNbParticules,

VecteurF & inCellule,

VecteurF & outChamp )

{

outChamp = 0;

for ( unsigned int i = 0; i < inNbParticules; i++ )

{

Particule & particuleCourante = inParticules[ i ];

// Un accès pour la masse

float m1 = particuleCourante.Masse;

// Trois accès pour la position

VectorF r12 = inCellule.PositionGlobale -

particuleCourante->PositionGlobale; if ( r12.Norme() != 0. )

{

outChamp +=

-G * m1 / ( r12.Norme() * r12.Norme() ) * r12.Normalize();

}

} }

Code 4-9 : Accès réalisés aux particules durant le calcul du champ de gravitation d'une cellule.

Pour éviter ces accès en mémoire globale, il est possible de mutualiser les accès aux données des pa ti ules. E effet, ha ue ellule de l espa e a esoi des do es de toutes les pa ti ules. Il est do possi le u elles pa tage t ette do e à t a e s la oi e partagée du GPU.

Pou ela, il est essai e ue ha ue ellule issue d u e lo ui pa tage la e mémoire partagée) charge les do es d u e pa ticule (on partira ici du principe que le nombre de particules est inférieur au nombre de threads a i u d u lo pou simplifier) (voir Code 4-10). Une fois ces montées en mémoire réalisées, il est impératif de synchroniser tous les threads qui partagent la mémoire car sans cela, un thread pourrait o e e le al ul du ha p pou sa ellule alo s e ue toutes les pa ti ules o t pas été chargées en mémoire partagée.

U e fois ela fait, il suffit alo s d appele la fo tio

CalculChampGravitationCellule_gpu en prenant en paramètre, non plus le tableau de particules stocké en mémoire globale, mais celui stocké en mémoire partagée. Les quatre accès en mémoire ne sont plus alors réalisés en mémoire globale mais sont réalisés en mémoire partagée.

188

__global__ void KernelCalculChampGravitation(

Particule * inParticules,

unsigned int inNbParticules,

VecteurF * inTreilli,

VecteurF * inChamp,

) {

unsigned int threadIdGlobal = calculerIdGlobal();

unsigned int threadIdBloc = calculerIdBloc();

// Definition de la mémoire partagée

__shared__ Particule particulesPartagees[];

// Chargement de la mémoire partagée

if ( threadIdBloc < inNbParticules )

{

particulesPartagees[ threadIdBloc ] =

inParticules[ threadIdBloc ];

}

// Synchronisation des threads

__syncthread(); CalculChampGravitationCellule_gpu( particulesPartagees, inNbParticules, inTreilli[ threadIdGlobal ], inChamp[ threadIdGlobal ] ); }

Code 4-10 : Kernel pe etta t le al ul du ha p de g avitatio ave l’utilisatio de oi e

partagée.

4.2.4 Étude du calcul de forces gravitationnelles, électriques et magnétiques

I dokument Fifteen Years with the Norma Research Programme, Anniversary Volume Numhauser-Henning, Ann; Rönnmar, Mia (sidor 51-56)