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.
}
}
-//CheckTime + DoRecv
+//CheckTime + DoRecv + DoInterp
if ( recvbuf && recvcount ) {
for ( target = 0 ; target < _GroupSize ; target++ ) {
int recvsize = recvcount*_MPIAccess->Extent( recvtype ) ;
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 ;
}
}
-//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] ) {
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 ) {
//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 ;