Attention une mise à jour du service Gitlab va être effectuée le mardi 30 novembre entre 17h30 et 18h00. Cette mise à jour va générer une interruption du service dont nous ne maîtrisons pas complètement la durée mais qui ne devrait pas excéder quelques minutes. Cette mise à jour intermédiaire en version 14.0.12 nous permettra de rapidement pouvoir mettre à votre disposition une version plus récente.

Commit 162fef44 authored by berenger-bramas's avatar berenger-bramas
Browse files

Changed the Sand Settling Algorithm.

git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/scalfmm/scalfmm/trunk@175 2616d619-271b-44dc-8df4-d4a8f33a7222
parent ec05ea8a
......@@ -324,6 +324,7 @@ public:
return true;
}
template <class OctreeClass>
static bool IntervalsToTree(OctreeClass& realTree, OctreeClass& treeInterval, const int myNbParticlesCounter){
const int rank = MpiGetRank();
......@@ -333,28 +334,13 @@ public:
// We inform the master proc about the data we have
//////////////////////////////////////////////////////////////////////////////////
FVector<ParticlesGroup> groups;
ParticleClass*const realParticles = myNbParticlesCounter?new ParticleClass[myNbParticlesCounter]:0;
int nbLeafs = 0;
// we might now have any particles in our interval
if(myNbParticlesCounter){
typename OctreeClass::Iterator octreeIterator(&treeInterval);
octreeIterator.gotoBottomLeft();
int indexPart = 0;
do{
typename ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets());
const MortonIndex indexAtThisLeaf = octreeIterator.getCurrentGlobalIndex();
groups.push(ParticlesGroup(octreeIterator.getCurrentListTargets()->getSize(),indexPart, indexAtThisLeaf));
while( iter.hasNotFinished() ){
realParticles[indexPart] = iter.data();
++indexPart;
iter.gotoNext();
}
++nbLeafs;
} while(octreeIterator.moveRight());
}
......@@ -412,150 +398,235 @@ public:
const bool iDoNotHaveEnoughtToSendRight = myRightLeaf < leftLeafs;
const bool iDoNotHaveEnoughtToSendLeft = leftLeafs + nbLeafs < myLeftLeaf;
ParticleClass* rpart(0);
int rpartSize(0);
// Do I need to send to right?
if(iNeedToSendToRight){
int iNeedToSend = leftLeafs + nbLeafs - myRightLeaf;
int iCanSend = nbLeafs;
int idxSend (0);
const int iNeedToSendLeftCount = myLeftLeaf - leftLeafs;
const int iCanSendToLeft = nbLeafs;
MPI_Send(&iNeedToSend, sizeof(int), MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
const int iNeedToSendRightCount = leftLeafs + nbLeafs - myRightLeaf;
const int iCanSendToRight = nbLeafs;
while(idxSend < iNeedToSend && idxSend < iCanSend){
MPI_Send(&groups[nbLeafs - idxSend - 1].number, sizeof(int), MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
MPI_Send(&realParticles[groups[nbLeafs - idxSend - 1].positionInArray], sizeof(ParticleClass) * groups[nbLeafs - idxSend - 1].number,
MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
MPI_Request requests[10];
int iterRequest = 0;
++idxSend;
}
// I need to wait (idxSend == iCanSend && idxSend < iNeedToSend)
if( iDoNotHaveEnoughtToSendRight ){ // I need to wait
int nbLeafsToRead(0);
receiveDataFromTag(sizeof(int), 0, &nbLeafsToRead);
for(int idxToRead = 0 ; idxToRead < nbLeafsToRead ; ++idxToRead){
int nbPartToRead(0);
receiveDataFromTag(sizeof(int), 0, &nbPartToRead);
if(rpartSize < nbPartToRead){
rpartSize = nbPartToRead;
delete [] (reinterpret_cast<char*>(rpart));
rpart = reinterpret_cast<ParticleClass*>(new char[nbPartToRead*sizeof(ParticleClass)]);
}
int hasBeenSentToLeft = 0;
int hasBeenSentToRight = 0;
receiveDataFromTag(nbPartToRead*sizeof(ParticleClass), 0, rpart);
if(idxSend < iNeedToSend){
MPI_Send(&nbPartToRead, sizeof(int), MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
MPI_Send(rpart, sizeof(ParticleClass) * nbPartToRead, MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
char* particlesToSend = 0;
++idxSend;
}
else{
//insert into tree
for(int idxPart = 0 ; idxPart < nbPartToRead ; ++idxPart){
realTree.insert(rpart[idxPart]);
}
}
///////////////////////////////
// Manage data we already have
///////////////////////////////
if(myNbParticlesCounter){
particlesToSend = new char[sizeof(ParticleClass) * myNbParticlesCounter + sizeof(int) * nbLeafs];
int idxWriteParticles = 0;
typename OctreeClass::Iterator octreeIterator(&treeInterval);
octreeIterator.gotoBottomLeft();
//Send to Left (the first leaves
if(iNeedToSendToLeft){
for(int idxLeaf = 0 ; idxLeaf < iNeedToSendLeftCount && idxLeaf < iCanSendToLeft ; ++idxLeaf){
*(int*)&particlesToSend[idxWriteParticles] = octreeIterator.getCurrentListTargets()->getSize();
idxWriteParticles += sizeof(int);
memcpy(&particlesToSend[idxWriteParticles], octreeIterator.getCurrentListTargets()->data(), sizeof(ParticleClass) * octreeIterator.getCurrentListTargets()->getSize());
idxWriteParticles += sizeof(ParticleClass) * octreeIterator.getCurrentListTargets()->getSize();
octreeIterator.moveRight();
}
hasBeenSentToLeft = FMath::Min(iNeedToSendLeftCount, iCanSendToLeft);
MPI_Send(particlesToSend, idxWriteParticles, MPI_BYTE , rank - 1, 0, MPI_COMM_WORLD);
}
}
// will I receive from left
if(iNeedToSendToLeft){
int iNeedToSend = myLeftLeaf - leftLeafs;
int iCanSend = nbLeafs;
int idxSend (0);
MPI_Send(&iNeedToSend, sizeof(int), MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
// Insert the particles I host and that belong to me
const int beginForMe = (iNeedToSendToLeft ? FMath::Min(iNeedToSendLeftCount,iCanSendToLeft) : 0);
const int endForMe = nbLeafs - (iNeedToSendToRight ? FMath::Min(iNeedToSendRightCount,iCanSendToRight) : 0);
for(int idxLeaf = beginForMe ; idxLeaf < endForMe ; ++idxLeaf){
typename ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets());
while(idxSend < iNeedToSend && idxSend < iCanSend){
MPI_Send(&groups[idxSend].number, sizeof(int), MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
MPI_Send(&realParticles[groups[idxSend].positionInArray], sizeof(ParticleClass) * groups[idxSend].number,
MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
while( iter.hasNotFinished() ){
realTree.insert(iter.data());
iter.gotoNext();
}
++idxSend;
octreeIterator.moveRight();
}
// Can I do it now?
if( iDoNotHaveEnoughtToSendLeft ){
int nbLeafsToRead(0);
receiveDataFromTag(sizeof(int), 1, &nbLeafsToRead);
for(int idxToRead = 0 ; idxToRead < nbLeafsToRead ; ++idxToRead){
int nbPartToRead(0);
receiveDataFromTag(sizeof(int), 1, &nbPartToRead);
if(rpartSize < nbPartToRead){
rpartSize = nbPartToRead;
delete [] (reinterpret_cast<char*>(rpart));
rpart = reinterpret_cast<ParticleClass*>(new char[nbPartToRead*sizeof(ParticleClass)]);
}
receiveDataFromTag(nbPartToRead*sizeof(ParticleClass), 1, rpart);
if(idxSend < iNeedToSend){
MPI_Send(&nbPartToRead, sizeof(int), MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
MPI_Send(rpart, sizeof(ParticleClass) * nbPartToRead, MPI_BYTE , rank - 1, 1, MPI_COMM_WORLD);
//Send to Right (the right-est leaves
if(iNeedToSendToRight){
const int beginWriteIndex = idxWriteParticles;
++idxSend;
}
else{
for(int idxPart = 0 ; idxPart < nbPartToRead ; ++idxPart){
realTree.insert(rpart[idxPart]);
}
}
for(int idxLeaf = 0 ; idxLeaf < iNeedToSendRightCount && idxLeaf < iCanSendToRight ; ++idxLeaf){
*(int*)&particlesToSend[idxWriteParticles] = octreeIterator.getCurrentListTargets()->getSize();
idxWriteParticles += sizeof(int);
memcpy(&particlesToSend[idxWriteParticles], octreeIterator.getCurrentListTargets()->data(), sizeof(ParticleClass) * octreeIterator.getCurrentListTargets()->getSize());
idxWriteParticles += sizeof(ParticleClass) * octreeIterator.getCurrentListTargets()->getSize();
octreeIterator.moveRight();
}
hasBeenSentToRight = FMath::Min(iNeedToSendRightCount, iCanSendToRight);
MPI_Isend( &particlesToSend[beginWriteIndex], idxWriteParticles - beginWriteIndex, MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD, &requests[iterRequest++]);
}
}
// If i will receive from left and I did no already have
if(!(iNeedToSendToRight && iDoNotHaveEnoughtToSendRight) && iWillReceiveFromLeft){
int nbLeafsToRead(0);
receiveDataFromTag(sizeof(int), 0, &nbLeafsToRead);
for(int idxToRead = 0 ; idxToRead < nbLeafsToRead ; ++idxToRead){
int nbPartToRead(0);
receiveDataFromTag(sizeof(int), 0, &nbPartToRead);
//printf("%d I will receive %d particles\n",rank, nbPartToRead);
if(rpartSize < nbPartToRead){
rpartSize = nbPartToRead;
delete [] (reinterpret_cast<char*>(rpart));
rpart = reinterpret_cast<ParticleClass*>(new char[nbPartToRead*sizeof(ParticleClass)]);
}
char* toRecvFromLeft = 0;
char* toRecvFromRight = 0;
int countReceive = int(iWillReceiveFromLeft) + int(iWillReceiveFromRight);
int bytesRecvFromLeft = 0;
int bytesRecvFromRight = 0;
receiveDataFromTag(nbPartToRead*sizeof(ParticleClass), 0, rpart);
for(int idxPart = 0 ; idxPart < nbPartToRead ; ++idxPart){
realTree.insert(rpart[idxPart]);
}
// Now prepare to receive data
while(countReceive--){
MPI_Status status;
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
// receive from left
if(status.MPI_SOURCE == rank - 1){
MPI_Get_count( &status, MPI_BYTE, &bytesRecvFromLeft);
toRecvFromLeft = new char[bytesRecvFromLeft];
MPI_Irecv(toRecvFromLeft, bytesRecvFromLeft, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, &requests[iterRequest++]);
}
// receive from right
else{
MPI_Get_count( &status, MPI_BYTE, &bytesRecvFromRight);
toRecvFromRight = new char[bytesRecvFromRight];
MPI_Irecv(toRecvFromRight, bytesRecvFromRight, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, &requests[iterRequest++]);
}
}
// If i will receive from right and I did no already have
if(!(iNeedToSendToLeft && iDoNotHaveEnoughtToSendLeft) && iWillReceiveFromRight){
int nbLeafsToRead(0);
receiveDataFromTag(sizeof(int), 1, &nbLeafsToRead);
for(int idxToRead = 0 ; idxToRead < nbLeafsToRead ; ++idxToRead){
int nbPartToRead(0);
receiveDataFromTag(sizeof(int), 1, &nbPartToRead);
//printf("%d I will receive %d particles\n",rank, nbPartToRead);
if(rpartSize < nbPartToRead){
rpartSize = nbPartToRead;
delete [] (reinterpret_cast<char*>(rpart));
rpart = reinterpret_cast<ParticleClass*>(new char[nbPartToRead*sizeof(ParticleClass)]);
///////////////////////////////
// Wait send receive
///////////////////////////////
MPI_Waitall(iterRequest, requests, 0);
// We can delete the buffer use to send our particles only
delete[] particlesToSend;
particlesToSend = 0;
///////////////////////////////
// Process received data
// and transfer if needed
///////////////////////////////
// We have to receive from right and transfere to left
int hasToBeReceivedFromLeft = leftLeafs - myLeftLeaf;
int hasToBeReceivedFromRight = myRightLeaf - (leftLeafs + nbLeafs);
int arrayIdxRight = 0;
int arrayIdxLeft = 0;
if(iDoNotHaveEnoughtToSendLeft){
do{
arrayIdxRight = 0;
while(arrayIdxRight < bytesRecvFromRight && hasBeenSentToLeft < iNeedToSendLeftCount){
const int particlesInThisLeaf = *(int*)&toRecvFromRight[arrayIdxRight];
arrayIdxRight += sizeof(int) + sizeof(ParticleClass) * particlesInThisLeaf;
--hasToBeReceivedFromRight;
}
MPI_Send(toRecvFromRight, arrayIdxRight, MPI_BYTE , rank - 1, 0, MPI_COMM_WORLD);
if(hasBeenSentToLeft < iNeedToSendLeftCount){
MPI_Status status;
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
int status_size = 0;
MPI_Get_count( &status, MPI_BYTE, &status_size);
if(bytesRecvFromRight < status_size){
bytesRecvFromRight = status_size;
delete[] toRecvFromRight;
toRecvFromRight = new char[status_size];
}
MPI_Recv(toRecvFromRight, status_size, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
} while(hasBeenSentToLeft < iNeedToSendLeftCount);
}
// We have to receive from left and transfere to right
else if(iDoNotHaveEnoughtToSendRight){
do{
arrayIdxLeft = 0;
while(arrayIdxLeft < bytesRecvFromLeft && hasBeenSentToRight < iNeedToSendRightCount){
const int particlesInThisLeaf = *(int*)&toRecvFromLeft[arrayIdxLeft];
arrayIdxLeft += sizeof(int) + sizeof(ParticleClass) * particlesInThisLeaf;
--hasToBeReceivedFromLeft;
}
MPI_Send(toRecvFromLeft, arrayIdxLeft, MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD);
if(hasBeenSentToRight < iNeedToSendRightCount){
MPI_Status status;
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
int status_size = 0;
MPI_Get_count( &status, MPI_BYTE, &status_size);
if(bytesRecvFromLeft < status_size){
bytesRecvFromLeft = status_size;
delete[] toRecvFromLeft;
toRecvFromLeft = new char[status_size];
}
MPI_Recv(toRecvFromLeft, status_size, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
} while(hasBeenSentToRight < iNeedToSendRightCount);
}
if(iWillReceiveFromLeft ){ // I need to wait
do{
while(arrayIdxLeft < bytesRecvFromLeft){
const int particlesInThisLeaf = *(int*)&toRecvFromLeft[arrayIdxLeft];
arrayIdxLeft += sizeof(int);
ParticleClass*const particles = reinterpret_cast<ParticleClass*>(&toRecvFromLeft[arrayIdxLeft]);
arrayIdxLeft += sizeof(ParticleClass) * particlesInThisLeaf;
for( int idxPart = 0 ; idxPart < particlesInThisLeaf ; ++idxPart){
realTree.insert( particles[ idxPart ] );
}
receiveDataFromTag(nbPartToRead*sizeof(ParticleClass), 1, rpart);
for(int idxPart = 0 ; idxPart < nbPartToRead ; ++idxPart){
realTree.insert(rpart[idxPart]);
--hasToBeReceivedFromLeft;
}
}
arrayIdxLeft = 0;
if(hasToBeReceivedFromLeft){
MPI_Status status;
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
int status_size = 0;
MPI_Get_count( &status, MPI_BYTE, &status_size);
if(bytesRecvFromLeft < status_size){
bytesRecvFromLeft = status_size;
delete[] toRecvFromLeft;
toRecvFromLeft = new char[status_size];
}
MPI_Recv(toRecvFromLeft, status_size, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
} while(hasToBeReceivedFromLeft);
}
if(iWillReceiveFromRight){
do{
while(arrayIdxRight < bytesRecvFromRight){
const int particlesInThisLeaf = *(int*)&toRecvFromRight[arrayIdxRight];
arrayIdxRight += sizeof(int);
ParticleClass*const particles = reinterpret_cast<ParticleClass*>(&toRecvFromRight[arrayIdxRight]);
arrayIdxRight += sizeof(ParticleClass) * particlesInThisLeaf;
for( int idxPart = 0 ; idxPart < particlesInThisLeaf ; ++idxPart){
realTree.insert( particles[ idxPart ] );
}
// insert the particles we already have
if(leftLeafs != totalNbLeafs){
for(int idxLeafInsert = FMath::Max(myLeftLeaf-leftLeafs,0) ; idxLeafInsert < totalNbLeafs - rightLeafs - leftLeafs - FMath::Max(0,leftLeafs + nbLeafs - myRightLeaf) ; ++idxLeafInsert){
for(int idxPart = 0 ; idxPart < groups[idxLeafInsert].number ; ++idxPart){
realTree.insert(realParticles[groups[idxLeafInsert].positionInArray + idxPart]);
--hasToBeReceivedFromRight;
}
}
arrayIdxRight = 0;
if(hasToBeReceivedFromRight){
MPI_Status status;
MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
int status_size = 0;
MPI_Get_count( &status, MPI_BYTE, &status_size);
if(bytesRecvFromRight < status_size){
bytesRecvFromRight = status_size;
delete[] toRecvFromRight;
toRecvFromRight = new char[status_size];
}
MPI_Recv(toRecvFromRight, status_size, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
} while(hasToBeReceivedFromRight);
}
delete [] reinterpret_cast<char*>(rpart);
// Delete reception buffers
delete[] toRecvFromLeft;
delete[] toRecvFromRight;
return true;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment