From: rahuel Date: Fri, 25 Jan 2008 14:53:50 +0000 (+0000) Subject: Commentaires X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=a2634530a364a57023f61507f13d6ff9cda28e01;p=tools%2Fmedcoupling.git Commentaires --- diff --git a/src/ParaMEDMEM/MPI_AccessDEC.cxx b/src/ParaMEDMEM/MPI_AccessDEC.cxx index d72df99d9..39f284df1 100644 --- a/src/ParaMEDMEM/MPI_AccessDEC.cxx +++ b/src/ParaMEDMEM/MPI_AccessDEC.cxx @@ -374,6 +374,60 @@ int MPI_AccessDEC::AllToAllv( void* sendbuf, int* sendcounts, int* sdispls, return sts ; } +/* +MPI_AccessDEC et la gestion des SendBuffers : +============================================= + +. Comme dans les communications collectives on n'envoie que des + parties du meme buffer à chaque process "target", il faut s'assurer + en asynchrone que toutes ces parties sont disponibles pour + pouvoir liberer le buffer. + +. On suppose que ces buffers ont ete alloues avec un new double[] + +. La structure SendBuffStruct permet de conserver l'adresse du buffer + et de gerer un compteur de references de ce buffer. Elle comporte + aussi MPI_Datatype pour pouvoir faire un delete [] (double *) ... + lorsque le compteur est null. + +. La map _MapOfSendBuffers etablit la correspondance entre chaque + RequestId obtenu de MPI_Access->ISend(...) et un SendBuffStruct + pour chaque "target" d'une partie du buffer. + +. Tout cela ne concerne que les envois asynchrones. En synchrone, + on detruit senbuf juste apres l'avoir transmis. +*/ + +/* +MPI_AccessDEC et la gestion des RecvBuffers : +============================================= + +S'il n'y a pas d'interpolation, rien de particulier n'est fait. + +Avec interpolation pour chaque target : +--------------------------------------- +. On a _TimeMessages[target] qui est un vecteur de TimesMessages. + On en a 2 dans notre cas avec une interpolation lineaire qui + contiennent le time(t0)/deltatime precedent et le dernier + time(t1)/deltatime. + +. On a _DataMessages[target] qui est un vecteur de DatasMessages + On en a 2 dans notre cas avec une interpolation lineaire qui + contiennent les donnees obtenues par Recv au time(t0)/deltatime + precedent et au dernier time(t1)/deltatime. + +. Au temps _t(t*) du processus courrant on effectue l'interpolation + entre les valeurs des 2 DatasMessages que l'on rend dans la + partie de recvbuf correspondant au target pourvu que t0 < t* <= t1. + +. Par suite de la difference des "deltatimes" entre process, on + peut avoir t0 < t1 < t* auquel cas on aura une extrapolation. + +. Les vecteurs _OutOfTime, _DataMessagesRecvCount et _DataMessagesType + contiennent pour chaque target true si t* > dernier t1, recvcount et + MPI_Datatype pour finaliser la gestion des messages a la fin. +*/ + /*! Send a TimeMessage to all targets of IntraCommunicator Receive the TimeMessages from targets of IntraCommunicator if necessary. @@ -452,7 +506,7 @@ int MPI_AccessDEC::AllToAllTime( void* sendbuf, int sendcount , MPI_Datatype sen } } -//CheckTime + DoRecv +//CheckTime + DoRecv + DoInterp if ( recvbuf && recvcount ) { for ( target = 0 ; target < _GroupSize ; target++ ) { int recvsize = recvcount*_MPIAccess->Extent( recvtype ) ; @@ -519,6 +573,22 @@ int MPI_AccessDEC::AllToAllvTime( void* sendbuf, int* sendcounts, int* sdispls, CheckSent() ; } +/* +. DoSend : + + On cree un TimeMessage (voir cette structure dans MPI_Access). + + Si l'on est en asynchrone on cree deux structures SendBuffStruct + aSendTimeStruct et aSendDataStruct que l'on remplit. + + On remplit la structure aSendTimeMessage avec time/deltatime du + process courant. "deltatime" doit etre nul s'il s'agit du dernier + pas de temps. + + Puis pour chaque "target", on envoie le TimeMessage et la partie + de sendbuf concernee par ce target. + + Si l'on est en asynchrone, on incremente le compteur et on ajoute + a _MapOfSendBuffers aSendTimeStruct et aSendDataStruct avec les + identifieurs SendTimeRequestId et SendDataRequestId recus de + MPI_Access->Send(...). + + Et enfin si l'on est en synchrone, on detruit les SendMessages. +*/ //DoSend : Time + SendBuff SendBuffStruct * aSendTimeStruct = NULL ; SendBuffStruct * aSendDataStruct = NULL ; @@ -604,7 +674,18 @@ int MPI_AccessDEC::AllToAllvTime( void* sendbuf, int* sendcounts, int* sdispls, } } -//CheckTime + DoRecv +/* +. CheckTime + DoRecv + DoInterp + + Pour chaque target on appelle CheckTime + + Si on a un TimeInterpolator et si le message temps du target + n'est pas le premier, on appelle l'interpolateur qui stocke + ses resultats dans la partie du buffer de reception qui + correspond au "target". + + Sinon, on recopie les donnees recues pour ce premier pas de + temps dans la partie du buffer de reception qui correspond au + "target". +*/ +//CheckTime + DoRecv + DoInterp if ( recvbuf ) { for ( target = 0 ; target < _GroupSize ; target++ ) { if ( recvcounts[target] ) { @@ -670,6 +751,39 @@ int MPI_AccessDEC::AllToAllvTime( void* sendbuf, int* sendcounts, int* sdispls, return sts ; } +/* +. CheckTime(recvcount , recvtype , target , UntilEnd) + + Au depart, on lit le premier "Message-temps" dans + &(*_TimeMessages)[target][1] et le premier message de donnees + dans le buffer alloue (*_DataMessages)[target][1]. + + Par convention deltatime des messages temps est nul si c'est le + dernier. + + Boucle while : _t(t*) est le temps courant du processus. + "tant que _t(t*) est superieur au temps du "target" + (*_TimeMessages)[target][1].time et que + (*_TimeMessages)[target][1].deltatime n'est pas nul", + ainsi en fin de boucle on aura : + _t(t*) <= (*_TimeMessages)[target][1].time avec + _t(t*) > (*_TimeMessages)[target][0].time + ou bien on aura le dernier message temps du "target". + + S'il s'agit de la finalisation des receptions des messages + temps et donnees (UntilEnd vaut true), on effectue la + boucle jusqu'a ce que l'on trouve + (*_TimeMessages)[target][1].deltatime nul. + + Dans la boucle : + On recopie le dernier message temps dans le message temps + precedent et on lit le message temps suivant. + On detruit le buffer de donnees du temps precedent. + On recopie le pointeur du dernier buffer de donnees dans + le precedent. + On alloue un nouveau dernier buffer de donnees + (*_DataMessages)[target][1] et on lit les donnees + correspondantes dans ce buffer. + + Si le temps courant du process est plus grand que le dernier + temps (*_TimeMessages)[target][1].time du target, on donne + la valeur true a (*_OutOfTime)[target]. + (*_TimeMessages)[target][1].deltatime est alors nul. +*/ int MPI_AccessDEC::CheckTime( int recvcount , MPI_Datatype recvtype , int target , bool UntilEnd ) { // int target , bool &OutOfTime ) { @@ -759,6 +873,22 @@ int MPI_AccessDEC::CheckTime( int recvcount , MPI_Datatype recvtype , int target //cout << endl ; return sts ; } + +/* +. CheckSent() : + + appelle SendRequestIds de MPI_Access afin d'obtenir tous les + RequestIds d'envoi de messages a tous les "targets". + + Pour chaque RequestId, appelle Test de MPI_Access pour savoir + si le buffer est libre (flag = true). Lorsqu'il s'agit du + FinalCheckSent, on appelle Wait au lieu de Test. + + Si le buffer est libre, on decremente le compteur de la + structure SendBuffStruct obtenue avec _MapOfSendBuffers. + (voir MPI_AccessDEC et la gestion des SendBuffers ci-dessus) + + Si le compteur est nul on detruit le TimeMessage ou le + SendBuffer en fonction du DataType. + + Puis on detruit la structure SendBuffStruct avant de supprimer + (erase) cet item de _MapOfSendBuffers +*/ int MPI_AccessDEC::CheckSent(bool WithWait) { int sts = MPI_SUCCESS ; int flag = WithWait ;