• Aucun résultat trouvé

Étude du modèle de programmation par tâches

Dans le document The DART-Europe E-theses Portal (Page 128-131)

6.2 Opérateur de Poisson

7.1.1 Étude du modèle de programmation par tâches

Le modèle de programmation par tâches offre de nombreuses possibilités d’optimisation et de paramétrage du code. La taille des tuiles, la granularité des tâches ainsi que le choix de l’ordonnanceur influent sur ses performances. Cette section propose un examen de l’ensemble de ces paramètres ainsi que des visualisations des traces d’exécution du code, grâce à l’outil ViTE1. Ces traces sont générées pour chaquethread directement par leruntime (Intel KOMP et GNU) dans les versions les plus récentes.

Le choix de la taille des tuiles est crucial. Si celles-ci sont trop petites, le code perd en densité calculatoire et son empreinte mémoire augmente fortement à cause des halos (voir section 5.1.1). Si elles sont trop grandes, il perd en localité mémoire et l’ordonnancement a moins de flexibilité pour le placement des tâches. Après expérimentation, les dimensions minimales permettant un bon déroulement de l’exécution sont les suivantes : nr = 16, nθ = 16, nϕ = 8, nvk = 16. Cela représente 256KiO de données, ce qui correspond à la taille des caches L2 des processeurs actuels. Cela permet également d’avoir suffisamment de tuiles à distribuer entre un grand nombre de processus MPI, même pour un petit maillage, en gardant le surcoût mémoire inférieur à deux fois l’espace de stockage des données. Il est possible d’augmenter la taille des tuiles en fonction de l’architecture tout en restant dans la limite du cache L3 (partagé entre tous les cœurs).

La granularité des tâches doit être adaptée à l’ordonnanceur et à la machine. Elle ne doit pas être trop grosse, afin de pouvoir laisser une marge de manœuvre à l’ordonnanceur et de ne pas générer de temps d’attente où certains cœurs se retrouveraient sans tâche à exécuter. Elle ne doit pas non plus être trop fine, ce qui entraînerait un trop grand nombre de tâches, au risque que l’ordonnancement prenne autant de temps que l’exécution. La Figure 7.1 présente un extrait de la visualisation ViTE d’une exécution du code sur un maillage de (256×256×32×32) avec des tuiles de taille nr = 8, nθ = 8, nϕ = 4,nvk = 4 (8KiO). Chaque ligne représente les tâches (en couleur) exécutées par un thread, lethread

1. https://vite.gforge.inria.fr

7.1. Évaluation des performances 119 1 étant le thread ordonnanceur. L’extrait montre l’advection en vk pour certains threads.

On observe entre chaque tâche (en vert et violet) une phase grise qui consiste à un temps d’inactivité du thread en attente de l’attribution de sa prochaine tâche. Ce temps est de quelques dizaines de microsecondes sur les machines que nous utilisons pour cesbenchmarks (Poincaré et Occigen), et ce aussi bien pour l’ordonnanceur Intel que GNU. Des tâches plus lourdes sont nécessaires pour minimiser ces surcoûts. Après expérimentations, avec les dimensions de tuile données au paragraphe précédent, générer une tâche par tuile donne une bonne granularité.

Figure 7.1 – Extrait de la trace d’une exécution sur un maillage de (256×256×32×32) points (réduit en r×θ) avec de petites tuiles et un processus MPI. Zoom sur l’opérateur d’advection vk (en vert) et des copies de halos (en violet) suivantes. Runtime Intel.

La Figure 7.2 montre la trace d’une itération complète sur le même maillage que pré-cédemment avec les dimensions de tuile conseillées en début de section. Le cas est exécuté avec un seul processus MPI sur un nœud du calculateur Occigen (deux processeurs de 12 cœurs). Les tâches violettes, jaunes et rouges correspondent respectivement aux advections envk,ϕetr×θ. Les tâches turquoises entre elles correspondent aux recopies de halos. Les détails de l’opérateur de Poisson (à gauche avant la première advection envk) sont mieux visibles sur la Figure 7.3. Les tâches vertes correspondent au calcul de la densité, les tâches cyan au calcul du potentiel et les tâches orange au calcul des dérivées du potentiel. Les zones grises entre elles sont dues à des barrières et à des calculs séquentiels intermédiaires non tracés par l’outil. On observe globalement sur les deux figures un bon ordonnancement des tâches. De plus, leur granularité est assez régulière, ce qui montre le faible impact en matière de déséquilibrage de charge des différents traitements pour chaque type de tuile (régulière, jonction, centre et bord). Seules les tuiles centrales sont plus grosses par construction (elles prennent tous les points enθ et sont donc ici huit fois plus grosses que les autres tuiles). Les tâches relatives à ces tuiles sont créées en premier afin qu’elles soient ordonnancées pour exécution en premier.

En effet les tâches d’une advection peuvent être simplement créées dans l’ordre de nu-mérotation des tuiles. Mais comme le montre la Figure 7.4, une phase d’attente impromptue peut être générée par l’ordonnanceur à la fin de l’exécution des tâches de l’advection. En effet, la tâche associée à une des tuiles centrale est systématiquement ordonnancée à la fin (entourée en jaune). Afin d’éviter ce problème, il serait intéressant que des priorités puissent

120 7.1. Évaluation des performances

Figure 7.2 – Extrait de la trace d’une exécution sur un maillage de (256×256×32×32) points (réduit en r×θ) avec un processus MPI. Zoom sur une itération. Runtime GNU.

Figure 7.3 – Extrait de la trace d’une exécution sur un maillage de (256×256×32×32) points (réduit en r×θ) avec un processus MPI. Zoom sur l’opérateur de Poisson. Runtime GNU.

être spécifiées au runtime lors de la création des tâches. Cela est techniquement possible dans le standard OpenMP mais en pratique, très peu d’implémentations les prennent en compte.

La Figure 7.5 donne la trace d’une itération sur le même cas qu’en Figure 7.2 mais avec leruntime Intel. L’ordonnancement des tâches y est très similaire. Il est important de noter que la création de l’ensemble des tâches pour chaque opérateur est relativement rapide.

Pour l’advection poloïdale par exemple, la génération de toutes les tâches représente un dixième du temps d’exécution d’une tâche (non tuile centrale).

La parallélisation par tâches offre comme désiré une bonne occupation des cœurs de calcul lorsque les bons paramètres sont choisis pour la taille des tâches. On pourrait néan-moins opter pour des tailles plus petites si le runtime était en mesure de réduire ses coûts de gestion. L’utilisation des caches et les performances seraient ainsi améliorées. Néan-moins, certaines fonctionnalités manquent encore dans les runtimes, et elles nécessitent d’être remplacées manuellement.

7.1. Évaluation des performances 121

Figure 7.4 – Extrait de la trace d’une exécution sur un maillage de (256×256×32×32) points (réduit enr×θ) avec un processus MPI. Zoom sur une itération.Runtime GNU sans ordonnancement manuel.

Figure 7.5 – Extrait de la trace d’une exécution sur un maillage de (256×256×32×32) points (réduit en r×θ) avec un processus MPI. Zoom sur une itération. Runtime INTEL.

Dans le document The DART-Europe E-theses Portal (Page 128-131)