From 36a67e8a26a43798d44960c8555e0645a75d3f76 Mon Sep 17 00:00:00 2001 From: Martin Khannouz Date: Thu, 31 Mar 2016 11:20:11 +0200 Subject: [PATCH] Add new stuff in the orgmode. --- Doc/noDist/Presentation/presentation.org | 394 ++++++++++++++++++++++- 1 file changed, 384 insertions(+), 10 deletions(-) diff --git a/Doc/noDist/Presentation/presentation.org b/Doc/noDist/Presentation/presentation.org index 4f290560..8b2e732d 100644 --- a/Doc/noDist/Presentation/presentation.org +++ b/Doc/noDist/Presentation/presentation.org @@ -16,7 +16,325 @@ # spack install scalfmm@src+mpi+starpu \^starpu@svn-trunk+mpi+fxt \^openmpi # #+END_SRC -* Implémentation mpi implicite très naïve +* Abstract +* Introduction +* Background +** Fast Multipole Method +** Task based FMM +*** Sequential Task Flow +*** Runtime +*** Group tree +*** Distributed FMM +* Implicit MPI FMM +** Sequential Task Flow with implicit communication +** Data Mapping +*** Level Split Mapping +*** Leaf Load Balancing +*** TreeMatch Balancing +** Result +#+BEGIN_SRC +#!/bin/sh +export SCALFMM_SIMGRIDOUT='scalfmm.out' +export GROUP_SIZE=500 +export TREE_HEIGHT=5 +export NB_NODE=16 +export NB_PARTICLE_PER_NODE=15000 + +echo "GROUP_SIZE=$GROUP_SIZE" +echo "TREE_HEIGHT=$TREE_HEIGHT" +echo "NB_NODE=$NB_NODE" +echo "NB_PARTICLE_PER_NODE=$NB_PARTICLE_PER_NODE" + +#Compile only what we need +make testBlockedImplicitChebyshev testBlockedMpiChebyshev testBlockedImplicitAlgorithm testBlockedMpiAlgorithm compareDAGmapping -j $((`nproc`*2)) +if [ $? -ne 0 ]; then + exit +fi + +#Execute explicit mpi version +sleep 10 +mpiexec -n $NB_NODE ./Tests/Release/testBlockedMpiAlgorithm -nb $NB_PARTICLE_PER_NODE -bs $GROUP_SIZE -h $TREE_HEIGHT 2>/dev/null +if [ $? -ne 0 ]; then + echo + echo " /!\\Error on explicit" + echo + exit +fi + +#Aggregate task information from explicit execution +a=`ls $SCALFMM_SIMGRIDOUT\_*` +rm -f $SCALFMM_SIMGRIDOUT +for i in $a; do + cat $i >> $SCALFMM_SIMGRIDOUT +done + +#Get task information +cp -f $SCALFMM_SIMGRIDOUT scalfmm_explicit.out + +#Execute implicit version +sleep 10 +mpiexec -n $NB_NODE ./Tests/Release/testBlockedImplicitAlgorithm -f canard.fma -bs $GROUP_SIZE -h $TREE_HEIGHT 2>/dev/null +if [ $? -ne 0 ]; then + echo + echo " /!\\Error on implicit" + echo + exit +fi + +#Get task information +cp -f scalfmm.out_0 scalfmm_implicit.out + +#Compare DAGs +./Tests/Release/compareDAGmapping -e scalfmm_explicit.out -i scalfmm_implicit.out -h $TREE_HEIGHT > output + +sleep 10 +mpiexec -n $NB_NODE ./Tests/Release/testBlockedMpiChebyshev -nb $NB_PARTICLE_PER_NODE -bs $GROUP_SIZE -h $TREE_HEIGHT 2>/dev/null +if [ $? -ne 0 ]; then + echo + echo " /!\\Error on explicit Chebyshev" + echo + exit +fi +sleep 10 +mpiexec -n $NB_NODE ./Tests/Release/testBlockedImplicitChebyshev -f canard.fma -bs $GROUP_SIZE -h $TREE_HEIGHT 2>/dev/null +if [ $? -ne 0 ]; then + echo + echo " /!\\Error on implicit Chebyshev" + echo + exit +fi +#+END_SRC + +<> +The script of the job: +#+BEGIN_SRC +#!/usr/bin/env bash +## name of job +#SBATCH -J Implicit_MPI_time +#SBATCH -p special +## Resources: (nodes, procs, tasks, walltime, ... etc) +#SBATCH -N 40 +# # standard output message +#SBATCH -o batch%j.out +# # output error message +#SBATCH -e batch%j.err +module purge +module load slurm +module add compiler/gcc/5.3.0 tools/module_cat/1.0.0 intel/mkl/64/11.2/2016.0.0 +. /home/mkhannou/spack/share/spack/setup-env.sh +spack load fftw +spack load hwloc +spack load openmpi +spack load starpu@svn-trunk +## modules to load for the job +export GROUP_SIZE=500 +export TREE_HEIGHT=5 +export NB_NODE=$SLURM_JOB_NUM_NODES +export NB_PARTICLE_PER_NODE=100000 +echo "=====my job informations ====" +echo "Node List: " $SLURM_NODELIST +echo "my jobID: " $SLURM_JOB_ID +echo "Nb node: " $NB_NODE +echo "Particle per node: " $NB_PARTICLE_PER_NODE +echo "In the directory: `pwd`" +rm -f canard.fma > /dev/null 2> /dev/null +mpiexec -n $NB_NODE ./Build/Tests/Release/testBlockedMpiAlgorithm -nb $NB_PARTICLE_PER_NODE -bs $GROUP_SIZE -h $TREE_HEIGHT > loutre +cat loutre | grep Executing +cat loutre | grep Average +sleep 10 +mpiexec -n $NB_NODE ./Build/Tests/Release/testBlockedImplicitAlgorithm -f canard.fma -bs $GROUP_SIZE -h $TREE_HEIGHT > loutre +cat loutre | grep Executing +cat loutre | grep Average +rm -f canard.fma > /dev/null 2> /dev/null +sleep 10 +mpiexec -n $NB_NODE ./Build/Tests/Release/testBlockedMpiChebyshev -nb $NB_PARTICLE_PER_NODE -bs $GROUP_SIZE -h $TREE_HEIGHT > loutre +cat loutre | grep Executing +cat loutre | grep Average +sleep 10 +mpiexec -n $NB_NODE ./Build/Tests/Release/testBlockedImplicitChebyshev -f canard.fma -bs $GROUP_SIZE -h $TREE_HEIGHT > loutre +cat loutre | grep Executing +cat loutre | grep Average +#+END_SRC + +The result given by the script after few minutes executing: +#+BEGIN_EXAMPLE +=====my job informations ==== +Node List: miriel[038-077] +my jobID: 108825 +Nb node: 40 +Particle per node: 100000 +In the directory: /home/mkhannou/scalfmm +Executing time node 0 (explicit) : 0.886289s +Executing time node 1 (explicit) : 12.689s +Executing time node 2 (explicit) : 12.6714s +Executing time node 3 (explicit) : 12.6539s +Executing time node 4 (explicit) : 12.6373s +Executing time node 5 (explicit) : 12.599s +Executing time node 6 (explicit) : 12.5816s +Executing time node 7 (explicit) : 12.5721s +Executing time node 8 (explicit) : 12.5626s +Executing time node 9 (explicit) : 12.5458s +Executing time node 10 (explicit) : 12.5198s +Executing time node 11 (explicit) : 12.519s +Executing time node 12 (explicit) : 12.5141s +Executing time node 13 (explicit) : 12.5045s +Executing time node 14 (explicit) : 12.4958s +Executing time node 15 (explicit) : 12.4322s +Executing time node 16 (explicit) : 12.4149s +Executing time node 17 (explicit) : 12.416s +Executing time node 18 (explicit) : 12.3991s +Executing time node 19 (explicit) : 12.3865s +Executing time node 20 (explicit) : 12.3445s +Executing time node 21 (explicit) : 12.3269s +Executing time node 22 (explicit) : 12.3089s +Executing time node 23 (explicit) : 12.3107s +Executing time node 24 (explicit) : 12.2928s +Executing time node 25 (explicit) : 12.2555s +Executing time node 26 (explicit) : 12.2461s +Executing time node 27 (explicit) : 12.2409s +Executing time node 28 (explicit) : 12.2237s +Executing time node 29 (explicit) : 12.2064s +Executing time node 30 (explicit) : 12.1672s +Executing time node 31 (explicit) : 12.1504s +Executing time node 32 (explicit) : 12.1326s +Executing time node 33 (explicit) : 12.1156s +Executing time node 34 (explicit) : 12.1058s +Executing time node 35 (explicit) : 12.0725s +Executing time node 36 (explicit) : 12.0558s +Executing time node 37 (explicit) : 12.0507s +Executing time node 38 (explicit) : 12.0376s +Executing time node 39 (explicit) : 12.0198s +Average time per node (explicit) : 12.0666s +Executing time node 0 (implicit) : 1.3918s +Executing time node 1 (implicit) : 1.1933s +Executing time node 2 (implicit) : 0.808328s +Executing time node 3 (implicit) : 0.773344s +Executing time node 4 (implicit) : 1.25819s +Executing time node 5 (implicit) : 1.18945s +Executing time node 6 (implicit) : 1.27529s +Executing time node 7 (implicit) : 1.22866s +Executing time node 8 (implicit) : 1.26839s +Executing time node 9 (implicit) : 1.25121s +Executing time node 10 (implicit) : 0.337148s +Executing time node 11 (implicit) : 1.4247s +Executing time node 12 (implicit) : 1.41725s +Executing time node 13 (implicit) : 1.48044s +Executing time node 14 (implicit) : 1.5094s +Executing time node 15 (implicit) : 1.50355s +Executing time node 16 (implicit) : 1.55565s +Executing time node 17 (implicit) : 1.40483s +Executing time node 18 (implicit) : 1.57896s +Executing time node 19 (implicit) : 1.63332s +Executing time node 20 (implicit) : 1.13418s +Executing time node 21 (implicit) : 1.66588s +Executing time node 22 (implicit) : 1.75309s +Executing time node 23 (implicit) : 1.75407s +Executing time node 24 (implicit) : 1.77763s +Executing time node 25 (implicit) : 1.80734s +Executing time node 26 (implicit) : 1.84635s +Executing time node 27 (implicit) : 1.91082s +Executing time node 28 (implicit) : 1.92222s +Executing time node 29 (implicit) : 1.96819s +Executing time node 30 (implicit) : 1.995s +Executing time node 31 (implicit) : 2.03309s +Executing time node 32 (implicit) : 2.04957s +Executing time node 33 (implicit) : 2.08208s +Executing time node 34 (implicit) : 2.10419s +Executing time node 35 (implicit) : 2.17535s +Executing time node 36 (implicit) : 2.19764s +Executing time node 37 (implicit) : 1.48737s +Executing time node 38 (implicit) : 2.20165s +Executing time node 39 (implicit) : 2.23154s +Average time per node (implicit) : 1.58951s +Executing time node 0 (explicit Cheby) : 14.9724s +Executing time node 1 (explicit Cheby) : 28.1361s +Executing time node 2 (explicit Cheby) : 28.8268s +Executing time node 3 (explicit Cheby) : 29.5679s +Executing time node 4 (explicit Cheby) : 30.3545s +Executing time node 5 (explicit Cheby) : 26.4163s +Executing time node 6 (explicit Cheby) : 28.3624s +Executing time node 7 (explicit Cheby) : 28.8427s +Executing time node 8 (explicit Cheby) : 29.4445s +Executing time node 9 (explicit Cheby) : 29.8502s +Executing time node 10 (explicit Cheby) : 27.1067s +Executing time node 11 (explicit Cheby) : 27.2506s +Executing time node 12 (explicit Cheby) : 28.3568s +Executing time node 13 (explicit Cheby) : 29.5386s +Executing time node 14 (explicit Cheby) : 28.5243s +Executing time node 15 (explicit Cheby) : 27.455s +Executing time node 16 (explicit Cheby) : 27.439s +Executing time node 17 (explicit Cheby) : 28.1895s +Executing time node 18 (explicit Cheby) : 28.8084s +Executing time node 19 (explicit Cheby) : 27.5662s +Executing time node 20 (explicit Cheby) : 26.8049s +Executing time node 21 (explicit Cheby) : 28.8124s +Executing time node 22 (explicit Cheby) : 28.2384s +Executing time node 23 (explicit Cheby) : 27.5266s +Executing time node 24 (explicit Cheby) : 27.5838s +Executing time node 25 (explicit Cheby) : 27.3604s +Executing time node 26 (explicit Cheby) : 28.8181s +Executing time node 27 (explicit Cheby) : 28.0987s +Executing time node 28 (explicit Cheby) : 27.5754s +Executing time node 29 (explicit Cheby) : 27.8695s +Executing time node 30 (explicit Cheby) : 28.1235s +Executing time node 31 (explicit Cheby) : 27.9892s +Executing time node 32 (explicit Cheby) : 27.8463s +Executing time node 33 (explicit Cheby) : 27.744s +Executing time node 34 (explicit Cheby) : 26.5374s +Executing time node 35 (explicit Cheby) : 28.3493s +Executing time node 36 (explicit Cheby) : 28.1228s +Executing time node 37 (explicit Cheby) : 28.1991s +Executing time node 38 (explicit Cheby) : 28.021s +Executing time node 39 (explicit Cheby) : 27.5317s +Average time per node (explicit Cheby) : 27.804s +Executing time node 0 (implicit Cheby) : 7.97802s +Executing time node 1 (implicit Cheby) : 15.1593s +Executing time node 2 (implicit Cheby) : 22.7339s +Executing time node 3 (implicit Cheby) : 30.1029s +Executing time node 4 (implicit Cheby) : 38.0297s +Executing time node 5 (implicit Cheby) : 44.84s +Executing time node 6 (implicit Cheby) : 51.8852s +Executing time node 7 (implicit Cheby) : 58.7032s +Executing time node 8 (implicit Cheby) : 65.5961s +Executing time node 9 (implicit Cheby) : 72.6259s +Executing time node 10 (implicit Cheby) : 73.0871s +Executing time node 11 (implicit Cheby) : 76.8398s +Executing time node 12 (implicit Cheby) : 83.7107s +Executing time node 13 (implicit Cheby) : 91.0522s +Executing time node 14 (implicit Cheby) : 97.4556s +Executing time node 15 (implicit Cheby) : 103.77s +Executing time node 16 (implicit Cheby) : 110.615s +Executing time node 17 (implicit Cheby) : 116.897s +Executing time node 18 (implicit Cheby) : 123.433s +Executing time node 19 (implicit Cheby) : 129.222s +Executing time node 20 (implicit Cheby) : 121.964s +Executing time node 21 (implicit Cheby) : 129.865s +Executing time node 22 (implicit Cheby) : 131.474s +Executing time node 23 (implicit Cheby) : 137.668s +Executing time node 24 (implicit Cheby) : 144.047s +Executing time node 25 (implicit Cheby) : 150.888s +Executing time node 26 (implicit Cheby) : 157.931s +Executing time node 27 (implicit Cheby) : 164.466s +Executing time node 28 (implicit Cheby) : 170.164s +Executing time node 29 (implicit Cheby) : 175.757s +Executing time node 30 (implicit Cheby) : 176.22s +Executing time node 31 (implicit Cheby) : 180.678s +Executing time node 32 (implicit Cheby) : 187.144s +Executing time node 33 (implicit Cheby) : 193.305s +Executing time node 34 (implicit Cheby) : 198.414s +Executing time node 35 (implicit Cheby) : 205.278s +Executing time node 36 (implicit Cheby) : 211.486s +Executing time node 37 (implicit Cheby) : 217.305s +Executing time node 38 (implicit Cheby) : 222.823s +Executing time node 39 (implicit Cheby) : 227.275s +Average time per node (implicit Cheby) : 122.947s +#+END_EXAMPLE + +* State of the art +Nothing for now ... + +* Journal +** Implémentation mpi implicite très naïve Cette première version avait pour principal but de découvrir et à prendre en main les fonctions de StarPU MPI. Les premières étant starpu_mpi_init et starpu_mpi_shutdown. Mais rapidement ont suivies les fonctions pour /tagger/ les /handles/ de StarPU et les ajouter à des nœuds MPI. À cela c'est ajouté la transformation de tous les appels à starpu_insert_task ou starpu_task_submit par starpu_mpi_insert_task. @@ -25,19 +343,19 @@ Par soucis de simplicité chaque nœud MPI possède l'intégralité de l'arbre, Pour vérifier que tout fonctionnait correctement, je me suis amusé à /mapper/ toutes les données sur un premier nœud MPI et toutes les tâches sur un second. J'ai ensuite pu valider que l'arbre du premier nœud avait les bons résultats et que le second nœud n'avait que des erreurs. -* Implémentation moins naïve +** Implémentation moins naïve Dans l'idée de créer une version 0 un brin potable qui puisse faire du calcul avec plus de deux nœuds MPI, j'ai créé une fonction de /mapping/ des données. Elle consistait à partager chaque niveau entre tous les processus de la manière la plus équitable possible. #+CAPTION: Division de chaque niveau entre chaque processus. Groupe de l'arbre de taille 4. [[./naive_split.png]] -* Reproduction du mapping mpi explicite +** Reproduction du mapping mpi explicite Pour pouvoir effectuer des comparaisons il était nécessaire de reproduire le même /mapping/ de tâches la version MPI explicite. Dans le cas de la version implicite telle qu'elle est actuellement implémentée, le /mapping/ des données infère le /mapping/ de tâches. La façon la plus simple de procéder est de faire en sorte que les particules se retrouvent sur les mêmes nœuds MPI. -** Premier problème des groupes +*** Premier problème des groupes La disposition des particules sur les nœuds MPI étant décidé par un tri distribué, il était plus judicieux de sauvegarder le /mapping/ des particules dans un fichier puis de le charger (dans la version implicite) et d'utiliser ce /mapping/ pour influer le /mapping/ au niveau de la version implicite. Le soucis du tri distribué est qu'il essaye d'équilibrer les particules sur les nœuds sans tenir compte des groupes de l'arbre groupé (/group tree/). @@ -50,7 +368,7 @@ Or le /mapping/ des données est fait avec la granularité des groupes de l'arbr Une première solution serait de modifier un peu l'algorithme de l'arbre pour le forcer à faire des groupes un peu plus petit de telle sorte qu'ils correspondent aux groupes de la version MPI explicite. Soucis, quand il faudra remonter dans l'arbre, que faire des cellules qui sont présentes sur plusieurs nœuds MPI, que faire de la racine ? -** Solution retenue +*** Solution retenue Plutôt que d'essayer de reproduire un /mapping/ de données identique à celui de la version explicite quel que soit les particules, nous avons choisi de limiter le nombre de cas reproductibles et de ségmenter ce /mapping/ par niveau. Ainsi avec un arbre parfait où chaque indice de morton possède le même nombre de particules, il est possible de reproduire le même /mapping/ de données sur un certain de nombre de niveaux. Ce nombre varie en fonction de la taille des groupes de l'arbre groupé. @@ -59,25 +377,81 @@ Ce nombre varie en fonction de la taille des groupes de l'arbre groupé. #+NAME: fig:SED-HR4049 [[./morton_box_center.png]] -** Validation des résultats +*** Solution apportée par la suite +Après discussion avec Bérenger il s'avèra qu'il n'était pas si difficile de reproduire le tri parrallèle. Ce à quoi je me suis attelé durant les jours qui on suivi. +Ainsi un constructeur a été ajouté à l'arbre bloqué pour décrire la taille de chaque bloque à chaque étage. +Cela requière un un pré-calcul qui est effectué par une fonction intermédiaire. +Cela revient à: +- Trier les particules selon leur indice de Morton. +- Compter le nombre de feuilles différentes. +- Répartir les feuilles en utilisant l'objet FLeafBalance. +- Créer les groupe des étages supérieurs en se basant sur l'interval de travail fourni par l'algorithme 13 de la thèse de Bérenger. + +*** Validation des résultats Pour valider ces résultats, j'ai réutilisé le système de nom de tâches fait pour simgrid. Ainsi j'ai pu indiquer, dans un fichier des informations à propos de chaque tâche. Les indices de Morton ainsi que les nœuds MPI sur lesquels elles s'exécutent. -*** Observation +**** Observation Si l'on fait exception des niveaux où l'on sait que des erreurs de tâches se trouveront, on a : - Plus de tâches dans la version explicite car elle a des tâches (P2P, M2L) symetriques. - Toutes les tâches issuent de l'algorithme implicite se retrouvent dans l'ensemble des tâches explicite. - Toutes les tâches sont au moins mapper sur le même nœud MPI. Les tâches symetriques étant parfois mappé sur deux nœuds différents. -* Et après ? +*** Comparaison des performances +Pour comparer les performances entre l'approche explicite et implicite, il a été décidé d'ajouté un nouveau test judicieusement nommé testBlockedImplicitChebyshev. Ainsi les comparaisons se font sur la base d'un véritable noyaux de calcul et non un noyaux de test peu réaliste. Les résultats sont déroulés dans la section [[sec:result]]. Notez que les temps indiqués ne correspondent qu'au temps de création des noyaux ainsi que de l'objet correspondant à l'algorithme de la FMM. N'est pas compris tout le temps passé à construire l'arbre, à stocker les particules ou a les lire dans un fichier et à vérifier le résultats. + +Le temps passé est compté de la manière suivante : +#+BEGIN_SRC C +//Start the timer +FTic timerExecute; +//Creating some useful object +const MatrixKernelClass MatrixKernel; +GroupKernelClass groupkernel(NbLevels, loader.getBoxWidth(), loader.getCenterOfBox(), &MatrixKernel); +GroupAlgorithm groupalgo(&groupedTree,&groupkernel, distributedMortonIndex); +//Executing the algorithm +groupalgo.execute(); +//Stop the timer +double elapsedTime = timerExecute.tacAndElapsed(); +//Sum the result +timeAverage(mpi_rank, nproc, elapsedTime); +#+END_SRC + +Les résultats dénotent deux choses : +- L'algorithme implicite répartis mal les calculs. +- Une situation curieuse : Avec le noyaux de test, l'implicite est 10x plus rapide, avec le noyau de Chebyshev, il est 5x plus lent. + +*** Erreurs rencontrées +Un /bug/ a fait son apparition dans la version MPI explicit où des segfaults apparaissent si l'arbre n'a pas au moins une particule dans chaque indice de Morton. +Cette erreur n'impacte pas encore la bonne progression du stage, car dans la pratique, il y a suffisament de particules pour remplir l'arbre. + +** Autre /mapping/ +*** Treematch +Suite à la présentation par Emmanuel Jeannot de l'outil TreeMatch qui permettrait de proposer des /mapping/ intéressant, il serait bon de profiter dudit outil. +Une structure de fichier pour communiquer avec TreeMatch serait la suivante : +#+BEGIN_EXAMPLE +123 7 +124:6000 +45:3000 +23:400 +#+END_EXAMPLE +Cette structure (simpliste) se lirait de la manière suivante : +- Le groupe 123 est situé sur le nœud 7. +- Le groupe 123 échange 6000 octets avec le groupe 124. +- Le groupe 123 échange 3000 octets avec le groupe 45. +- Le groupe 123 échange 400 octets avec le groupe 23. + +Les groupes correspondent aux /handles/ de Starpu qui correspondent aux groupes de l'arbre bloqué. + +** Et après ? - Comparaison des performances - Répartition des GFlop - Répartition du temps de calcul - Mémoire utilisée par nœud +- Symétriser l'algorithme implicite au niveau des P2P - Étude d'autres /mapping/ + - Proposer un formalisme simple pour transmettre le graphe de flux de données (Treematch) + - Proposer un formalisme simple pour transmettre la topologie (Treematch) - Limiter l'empreinte mémoire - Ne pas allouer les cellules numériques si ce n'est pas necessaire (/up/ et /down/) - Ne pas allouer les cellules symboliques si ce n'est pas necessaire - Distribuer l'arbre - - -- GitLab