diff --git a/Src/Files/FMpiTreeBuilder.hpp b/Src/Files/FMpiTreeBuilder.hpp index 0bb492a5c0f0abc9dd6bea19a6e5d4b0af051281..5f301d9b7656662095947142e5c13a34ceaad010 100644 --- a/Src/Files/FMpiTreeBuilder.hpp +++ b/Src/Files/FMpiTreeBuilder.hpp @@ -4,7 +4,7 @@ #include "../Utils/FQuickSort.hpp" -template<class ContainerClass, class ParticleClass> +template<class ParticleClass> class FMpiTreeBuilder{ static long getTreeCoordinate(const FReal inRelativePosition, const FReal boxWidthAtLeafLevel) { const FReal indexFReal = inRelativePosition / boxWidthAtLeafLevel; @@ -77,12 +77,26 @@ class FMpiTreeBuilder{ } }; + IndexedParticle* intervals; + int nbLeavesInIntervals; + +private: + FMpiTreeBuilder(const FMpiTreeBuilder&){} + FMpiTreeBuilder& operator=(const FMpiTreeBuilder&){return *this;} + public: - template <class OctreeClass, class LoaderClass> - static bool SplitAndSortFile(OctreeClass& treeInterval, int& myNbParticlesCounter, LoaderClass& loader){ + FMpiTreeBuilder() + : intervals(0), nbLeavesInIntervals(0) { + } + + virtual ~FMpiTreeBuilder(){ + delete [] intervals; + } + + template <class LoaderClass> + bool splitAndSortFile(LoaderClass& loader, const int NbLevels){ const int rank = MpiGetRank(); const int nbProcs = MpiGetNbProcs(); - const int NbLevels = treeInterval.getHeight(); IndexedParticle* outputArray = 0; long outputSize = 0; @@ -123,12 +137,19 @@ public: MPI_Send( &otherFirstIndex, 1, MPI_LONG_LONG, rank - 1, 0, MPI_COMM_WORLD); } } + MPI_Request req[2]; + int reqiter = 0; // at this point every one know the first index of his right neighbors - const bool needToRecvBeforeSend = (rank != 0 && ((outputSize && outputArray[0].index == otherFirstIndex) || !outputSize)); + const bool needToRecvBeforeSend = (rank != 0 && ((outputSize && otherFirstIndex == outputArray[0].index ) || !outputSize)); if( needToRecvBeforeSend || (rank == nbProcs - 1) ){ - long sendByOther = 0; - MPI_Recv(&sendByOther, 1, MPI_LONG, rank - 1, 0, MPI_COMM_WORLD,0); + int sendByOther = 0; + + MPI_Status status; + MPI_Probe(rank - 1, 0, MPI_COMM_WORLD, &status); + MPI_Get_count( &status, MPI_BYTE, &sendByOther); + if(sendByOther){ + sendByOther /= sizeof(IndexedParticle); const IndexedParticle* const reallocOutputArray = outputArray; const long reallocOutputSize = outputSize; @@ -137,7 +158,10 @@ public: memcpy(&outputArray[sendByOther], reallocOutputArray, reallocOutputSize * sizeof(IndexedParticle)); delete[] reallocOutputArray; - MPI_Recv(outputArray, sizeof(IndexedParticle) * sendByOther, MPI_BYTE, rank - 1, 0, MPI_COMM_WORLD, 0); + MPI_Irecv(outputArray, sizeof(IndexedParticle) * sendByOther, MPI_BYTE, rank - 1, 0, MPI_COMM_WORLD, &req[reqiter++]); + } + else{ + MPI_Irecv(0, 0, MPI_BYTE, rank - 1, 0, MPI_COMM_WORLD, &req[reqiter++]); } } if(rank != nbProcs - 1){ @@ -146,14 +170,24 @@ public: --idxPart; } long toSend = outputSize - 1 - idxPart; - MPI_Send( &toSend, 1, MPI_LONG, rank + 1, 0, MPI_COMM_WORLD); - if(toSend){ - MPI_Send( &outputArray[idxPart + 1], toSend * sizeof(IndexedParticle), MPI_BYTE, rank + 1, 0, MPI_COMM_WORLD); - } + MPI_Isend( &outputArray[idxPart + 1], toSend * sizeof(IndexedParticle), MPI_BYTE, rank + 1, 0, MPI_COMM_WORLD, &req[reqiter++]); + if( rank != 0 && !needToRecvBeforeSend ){ - long sendByOther = 0; - MPI_Recv(&sendByOther, 1, MPI_LONG, rank - 1, 0, MPI_COMM_WORLD, 0); + int sendByOther = 0; + + MPI_Status status; + MPI_Probe(rank - 1, 0, MPI_COMM_WORLD, &status); + MPI_Get_count( &status, MPI_BYTE, &sendByOther); + if(sendByOther){ + sendByOther /= sizeof(IndexedParticle); + char* const tempBuffer = new char[sizeof(IndexedParticle) * sendByOther]; + + MPI_Irecv(tempBuffer, sizeof(IndexedParticle) * sendByOther, MPI_BYTE, rank - 1, 0, MPI_COMM_WORLD, &req[reqiter++]); + + MPI_Waitall(reqiter,req,0); + reqiter = 0; + const IndexedParticle* const reallocOutputArray = outputArray; const long reallocOutputSize = outputSize; @@ -161,190 +195,59 @@ public: outputArray = new IndexedParticle[outputSize]; memcpy(&outputArray[sendByOther], reallocOutputArray, reallocOutputSize * sizeof(IndexedParticle)); delete[] reallocOutputArray; - - MPI_Recv(outputArray, sizeof(IndexedParticle) * sendByOther, MPI_BYTE, rank - 1, 0, MPI_COMM_WORLD,0); - } - } - } - } - - // we can insert into the tree - for(int idxPart = 0 ; idxPart < outputSize ; ++idxPart){ - treeInterval.insert(outputArray[idxPart].particle); - } - myNbParticlesCounter = outputSize; - delete[] outputArray; - - return true; - } - - template <class OctreeClass, class LoaderClass> - static bool SplitAndSortFileWithoutQS(OctreeClass& treeInterval, int& myNbParticlesCounter, LoaderClass& loader){ - const int rank = MpiGetRank(); - const int nbProcs = MpiGetNbProcs(); - - ////////////////////////////////////////////////////////////////////////////////// - // My method - ////////////////////////////////////////////////////////////////////////////////// - FVector<ParticlesGroup> groups; - ParticleClass*const realParticles = reinterpret_cast<ParticleClass*>(new char[loader.getNumberOfParticles() * sizeof(ParticleClass)]); - - { - OctreeClass sortingTree(treeInterval.getHeight(), treeInterval.getSubHeight() ,loader.getBoxWidth(),loader.getCenterOfBox()); - - ParticleClass particle; - for(long idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){ - loader.fillParticle(particle); - sortingTree.insert(particle); - } - - ////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////// - int indexPart = 0; - - typename OctreeClass::Iterator octreeIterator(&sortingTree); - octreeIterator.gotoBottomLeft(); - 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(); - } - } while(octreeIterator.moveRight()); - - } - - ////////////////////////////////////////////////////////////////////////////////// - // We send the particle that do not belong to us - ////////////////////////////////////////////////////////////////////////////////// - - MortonIndex min = 0; - MortonIndex max = 0; - - MPI_Reduce( &groups[0].index, &min, 1, MPI_LONG_LONG, MPI_MIN, 0, MPI_COMM_WORLD ); - MPI_Reduce( &groups[groups.getSize() - 1].index, &max, 1, MPI_LONG_LONG, MPI_MAX, 0, MPI_COMM_WORLD ); - - MPI_Bcast ( &min, 1, MPI_LONG_LONG, 0, MPI_COMM_WORLD ); - MPI_Bcast ( &max, 1, MPI_LONG_LONG, 0, MPI_COMM_WORLD ); - - // Used for print information - //const MortonIndex startIndex = GetLeft(max - min + 1) + min; - //const MortonIndex endIndex = GetRight(max - min + 1) + min; - - int*const needToReceive = new int[nbProcs * nbProcs]; - memset(needToReceive,0,nbProcs * nbProcs * sizeof(int)); - - FMpi::Request requests[nbProcs]; - { - int needToSend[nbProcs]; - memset(needToSend, 0, sizeof(int) * nbProcs); - - MortonIndex rightMortonIndex = min; - int groudIndex = 0; - for(int idxProc = 0 ; idxProc < nbProcs && groudIndex < groups.getSize() ; ++idxProc){ - rightMortonIndex = GetOtherRight(max - min + 1, idxProc) + min; - - if(idxProc != rank){ - int size = 0; - int currentGroupIndex = groudIndex; - while(groudIndex < groups.getSize() && groups[groudIndex].index < rightMortonIndex){ - size += groups[groudIndex].number; - ++groudIndex; + memcpy(outputArray, tempBuffer, sendByOther * sizeof(IndexedParticle)); + delete[] tempBuffer; } - needToSend[idxProc] = size; - - MPI_Isend(&realParticles[groups[currentGroupIndex].positionInArray], sizeof(ParticleClass) * size, MPI_BYTE , idxProc, 1, MPI_COMM_WORLD, &requests[idxProc]); - } - else{ - needToSend[idxProc] = 0; - while(groudIndex < groups.getSize() && groups[groudIndex].index < rightMortonIndex){ - const int end = groups[groudIndex].positionInArray + groups[groudIndex].number; - for(int idxPart = groups[groudIndex].positionInArray ; idxPart < end ; ++idxPart){ - //std::cout << "\t I keep (" << realParticles[idxPart].getPosition().getX() << ";" << realParticles[idxPart].getPosition().getY() << ";" << realParticles[idxPart].getPosition().getZ() << ")" << std::endl; - treeInterval.insert(realParticles[idxPart]); - ++myNbParticlesCounter; - } - ++groudIndex; + else{ + MPI_Irecv( 0, 0, MPI_BYTE, rank - 1, 0, MPI_COMM_WORLD, &req[reqiter++]); } } } - - MPI_Allgather( needToSend, nbProcs, MPI_INT, needToReceive, nbProcs, MPI_INT, MPI_COMM_WORLD); + MPI_Waitall(reqiter,req,0); } - ////////////////////////////////////////////////////////////////////////////////// - // We receive others particles and insert them in the tree - ////////////////////////////////////////////////////////////////////////////////// - int CounterProcToReceive(0); - int maxPartToReceive(0); - for(int idxProc = 0 ; idxProc < nbProcs ; ++idxProc){ - if(idxProc != rank && needToReceive[nbProcs * idxProc + rank]){ - ++CounterProcToReceive; - if(maxPartToReceive < needToReceive[nbProcs * idxProc + rank]){ - maxPartToReceive = needToReceive[nbProcs * idxProc + rank]; - } - } - } + int leavesCounter = 0; + MortonIndex previousIndex = -1; + char* writeIndex = reinterpret_cast<char*>(outputArray); + int* writeCounter = 0; - ParticleClass*const iterParticles = reinterpret_cast<ParticleClass*>(new char[maxPartToReceive * sizeof(ParticleClass)]); - // we receive message from nb proc - 1 (from every other procs - for(int idxProc = 0 ; idxProc < CounterProcToReceive ; ++idxProc){ - MPI_Status status; - MPI_Probe( MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status ); - const int source = status.MPI_SOURCE; + for( int idxPart = 0; idxPart < outputSize ; ++idxPart){ + if( outputArray[idxPart].index != previousIndex ){ + previousIndex = outputArray[idxPart].index; + ++leavesCounter; - const int nbPartFromProc = needToReceive[nbProcs * source + rank]; - int received(0); + writeCounter = reinterpret_cast<int*>( writeIndex ); + writeIndex += sizeof(int); - MPI_Recv(iterParticles, sizeof(ParticleClass) * nbPartFromProc, MPI_BYTE, source, 1, MPI_COMM_WORLD, &status); - MPI_Get_count(&status,MPI_BYTE, &received); - - for(int idxPart = 0 ; idxPart < nbPartFromProc ; ++idxPart){ - //std::cout << "\t We receive a new particle (" << (*iterParticles).getPosition().getX() << ";" << (*iterParticles).getPosition().getY() << ";" << (*iterParticles).getPosition().getZ() << ")" << std::endl; - treeInterval.insert(iterParticles[idxPart]); - ++myNbParticlesCounter; + (*writeCounter) = 0; } - } - for(int idxProc = 0 ; idxProc < nbProcs ; ++idxProc){ - if(idxProc != rank && needToReceive[nbProcs * rank + idxProc ]){ - MPI_Wait(&requests[idxProc], 0); - } + memcpy(writeIndex, &outputArray[idxPart].particle, sizeof(ParticleClass)); + + writeIndex += sizeof(ParticleClass); + ++(*writeCounter); } - delete [] reinterpret_cast<char*>(realParticles); - delete [] needToReceive; + intervals = outputArray; + nbLeavesInIntervals = leavesCounter; return true; } - template <class OctreeClass> - static bool IntervalsToTree(OctreeClass& realTree, OctreeClass& treeInterval, const int myNbParticlesCounter){ + bool intervalsToTree(OctreeClass& realTree){ const int rank = MpiGetRank(); const int nbProcs = MpiGetNbProcs(); + FTic counter; + counter.tic(); ////////////////////////////////////////////////////////////////////////////////// // We inform the master proc about the data we have ////////////////////////////////////////////////////////////////////////////////// - int nbLeafs = 0; - - // we might now have any particles in our interval - if(myNbParticlesCounter){ - typename OctreeClass::Iterator octreeIterator(&treeInterval); - octreeIterator.gotoBottomLeft(); - do{ - ++nbLeafs; - } while(octreeIterator.moveRight()); - } + int nbLeafs = nbLeavesInIntervals; // receive from left and right if((rank == 0)){ @@ -382,6 +285,7 @@ public: } } + ////////////////////////////////////////////////////////////////////////////////// // We balance the data ////////////////////////////////////////////////////////////////////////////////// @@ -406,7 +310,7 @@ public: const int iNeedToSendRightCount = leftLeafs + nbLeafs - myRightLeaf; const int iCanSendToRight = nbLeafs; - MPI_Request requests[10]; + MPI_Request requests[2]; int iterRequest = 0; int hasBeenSentToLeft = 0; @@ -414,87 +318,99 @@ public: char* particlesToSend = 0; + + printf("on my left %d on my right %d\n",leftLeafs, rightLeafs); + printf("iNeedToSendLeftCount %d iCanSendToLeft %d\n",iNeedToSendLeftCount, iCanSendToLeft); + printf("iNeedToSendRightCount %d iCanSendToRight %d \n",iNeedToSendRightCount, iCanSendToRight); + printf("Elapsed %lf\n", counter.tacAndElapsed()); + /////////////////////////////// // Manage data we already have /////////////////////////////// - if(myNbParticlesCounter){ - particlesToSend = new char[sizeof(ParticleClass) * myNbParticlesCounter + sizeof(int) * nbLeafs]; - int idxWriteParticles = 0; + if(nbLeafs){ + particlesToSend = reinterpret_cast<char*>(intervals); - typename OctreeClass::Iterator octreeIterator(&treeInterval); - octreeIterator.gotoBottomLeft(); + int currentLeafPosition = 0; //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(); + currentLeafPosition += ((*(int*)&particlesToSend[currentLeafPosition]) * sizeof(ParticleClass)) + sizeof(int); } - hasBeenSentToLeft = FMath::Min(iNeedToSendLeftCount, iCanSendToLeft); - MPI_Isend(particlesToSend, idxWriteParticles, MPI_BYTE , rank - 1, 0, MPI_COMM_WORLD, &requests[iterRequest++]); + MPI_Isend(particlesToSend, currentLeafPosition, MPI_BYTE , rank - 1, 0, MPI_COMM_WORLD, &requests[iterRequest++]); + printf("I send to left %d bytes %d leaves\n", currentLeafPosition, hasBeenSentToLeft); } + printf("Elapsed %lf\n", counter.tacAndElapsed()); // 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); + printf("I insert my particles from %d to %d \n", beginForMe, endForMe); for(int idxLeaf = beginForMe ; idxLeaf < endForMe ; ++idxLeaf){ - typename ContainerClass::ConstBasicIterator iter(*octreeIterator.getCurrentListTargets()); - while( iter.hasNotFinished() ){ - realTree.insert(iter.data()); - iter.gotoNext(); + const int nbPartInLeaf = (*(int*)&particlesToSend[currentLeafPosition]); + ParticleClass* const particles = reinterpret_cast<ParticleClass*>(&particlesToSend[currentLeafPosition] + sizeof(int)); + + for(int idxPart = 0 ; idxPart < nbPartInLeaf ; ++idxPart){ + realTree.insert(particles[idxPart]); } - octreeIterator.moveRight(); + currentLeafPosition += (nbPartInLeaf * sizeof(ParticleClass)) + sizeof(int); } + printf("Done\n"); + printf("Elapsed %lf\n", counter.tacAndElapsed()); //Send to Right (the right-est leaves if(iNeedToSendToRight){ - const int beginWriteIndex = idxWriteParticles; + const int beginWriteIndex = currentLeafPosition; 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(); + currentLeafPosition += (*(int*)&particlesToSend[currentLeafPosition]* sizeof(ParticleClass)) + sizeof(int); } hasBeenSentToRight = FMath::Min(iNeedToSendRightCount, iCanSendToRight); - MPI_Isend( &particlesToSend[beginWriteIndex], idxWriteParticles - beginWriteIndex, MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD, &requests[iterRequest++]); + MPI_Isend( &particlesToSend[beginWriteIndex], currentLeafPosition - beginWriteIndex, MPI_BYTE , rank + 1, 0, MPI_COMM_WORLD, &requests[iterRequest++]); + printf("I send to right %d bytes %d leaves\n", currentLeafPosition - beginWriteIndex, hasBeenSentToRight); } + printf("Elapsed %lf\n", counter.tacAndElapsed()); } char* toRecvFromLeft = 0; char* toRecvFromRight = 0; int countReceive = int(iWillReceiveFromLeft) + int(iWillReceiveFromRight); - int bytesRecvFromLeft = 0; - int bytesRecvFromRight = 0; + int sizeOfLeftBuffer = 0; + int sizeOfRightBuffer = 0; + int sizeOfRightData = 0; + int sizeOfLeftData = 0; + + int sourceToWhileRecv = MPI_ANY_SOURCE; + + printf("countReceive %d\n", countReceive); + printf("Elapsed %lf\n", counter.tacAndElapsed()); // Now prepare to receive data while(countReceive--){ MPI_Status status; - MPI_Probe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status); + MPI_Probe(sourceToWhileRecv, 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++]); + MPI_Get_count( &status, MPI_BYTE, &sizeOfLeftBuffer); + toRecvFromLeft = new char[sizeOfLeftBuffer]; + sizeOfLeftData = sizeOfLeftBuffer; + MPI_Irecv(toRecvFromLeft, sizeOfLeftBuffer, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, &requests[iterRequest++]); + sourceToWhileRecv = rank + 1; + printf("I will receive %d bytes from left\n", sizeOfLeftBuffer); } // 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++]); + MPI_Get_count( &status, MPI_BYTE, &sizeOfRightBuffer); + toRecvFromRight = new char[sizeOfRightBuffer]; + sizeOfRightData = sizeOfRightBuffer; + MPI_Irecv(toRecvFromRight, sizeOfRightBuffer, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, &requests[iterRequest++]); + sourceToWhileRecv = rank - 1; + printf("I will receive %d bytes from right\n", sizeOfRightBuffer); } } @@ -503,8 +419,9 @@ public: /////////////////////////////// MPI_Waitall(iterRequest, requests, 0); // We can delete the buffer use to send our particles only - delete[] particlesToSend; - particlesToSend = 0; + + printf("Wait passed...\n"); + printf("Elapsed %lf\n", counter.tacAndElapsed()); /////////////////////////////// // Process received data @@ -517,56 +434,67 @@ public: int arrayIdxLeft = 0; if(iDoNotHaveEnoughtToSendLeft){ + printf("iDoNotHaveEnoughtToSendLeft\n"); do{ arrayIdxRight = 0; - while(arrayIdxRight < bytesRecvFromRight && hasBeenSentToLeft < iNeedToSendLeftCount){ + while(arrayIdxRight < sizeOfRightData && hasBeenSentToLeft < iNeedToSendLeftCount){ const int particlesInThisLeaf = *(int*)&toRecvFromRight[arrayIdxRight]; arrayIdxRight += sizeof(int) + sizeof(ParticleClass) * particlesInThisLeaf; --hasToBeReceivedFromRight; + ++hasBeenSentToLeft; } + printf("Send %d to left, total leaves sent %d / %d\n", arrayIdxRight, hasBeenSentToLeft, iNeedToSendLeftCount); + printf("Elapsed %lf\n", counter.tacAndElapsed()); 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; + MPI_Get_count( &status, MPI_BYTE, &sizeOfRightData); + if(sizeOfRightBuffer < sizeOfRightData){ + sizeOfRightBuffer = sizeOfRightData; delete[] toRecvFromRight; - toRecvFromRight = new char[status_size]; + toRecvFromRight = new char[sizeOfRightData]; } - MPI_Recv(toRecvFromRight, status_size, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE); + printf("Receive %d bytes from right\n", sizeOfRightData); + MPI_Recv(toRecvFromRight, sizeOfRightData, 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){ + printf("iDoNotHaveEnoughtToSendRight\n"); do{ arrayIdxLeft = 0; - while(arrayIdxLeft < bytesRecvFromLeft && hasBeenSentToRight < iNeedToSendRightCount){ + while(arrayIdxLeft < sizeOfLeftData && hasBeenSentToRight < iNeedToSendRightCount){ const int particlesInThisLeaf = *(int*)&toRecvFromLeft[arrayIdxLeft]; arrayIdxLeft += sizeof(int) + sizeof(ParticleClass) * particlesInThisLeaf; --hasToBeReceivedFromLeft; + ++hasBeenSentToRight; } + printf("Send %d to right, total leaves sent %d / %d\n", arrayIdxLeft, hasBeenSentToRight, iNeedToSendRightCount); + printf("Elapsed %lf\n", counter.tacAndElapsed()); 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; + MPI_Get_count( &status, MPI_BYTE, &sizeOfLeftData); + if(sizeOfLeftBuffer < sizeOfLeftData){ + sizeOfLeftBuffer = sizeOfLeftData; delete[] toRecvFromLeft; - toRecvFromLeft = new char[status_size]; + toRecvFromLeft = new char[sizeOfLeftData]; } - MPI_Recv(toRecvFromLeft, status_size, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE); + printf("Receive %d bytes from left", sizeOfLeftData); + MPI_Recv(toRecvFromLeft, sizeOfLeftData, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } while(hasBeenSentToRight < iNeedToSendRightCount); } + printf("Finished to send\n"); + if(iWillReceiveFromLeft ){ // I need to wait + printf("iWillReceiveFromLeft (hasToBeReceivedFromLeft %d leaves)\n", hasToBeReceivedFromLeft); do{ - while(arrayIdxLeft < bytesRecvFromLeft){ + while(arrayIdxLeft < sizeOfLeftData){ const int particlesInThisLeaf = *(int*)&toRecvFromLeft[arrayIdxLeft]; arrayIdxLeft += sizeof(int); ParticleClass*const particles = reinterpret_cast<ParticleClass*>(&toRecvFromLeft[arrayIdxLeft]); @@ -580,23 +508,27 @@ public: } arrayIdxLeft = 0; + printf("Remains hasToBeReceivedFromLeft %d leaves to receive\n",hasToBeReceivedFromLeft); + printf("Elapsed %lf\n", counter.tacAndElapsed()); + 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; + MPI_Probe( rank - 1, 0, MPI_COMM_WORLD, &status); + MPI_Get_count( &status, MPI_BYTE, &sizeOfLeftData); + if(sizeOfLeftBuffer < sizeOfLeftData){ + sizeOfLeftBuffer = sizeOfLeftData; delete[] toRecvFromLeft; - toRecvFromLeft = new char[status_size]; + toRecvFromLeft = new char[sizeOfLeftData]; } - MPI_Recv(toRecvFromLeft, status_size, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE); + printf("Received %d bytes from left\n", sizeOfLeftData); + MPI_Recv(toRecvFromLeft, sizeOfLeftData, MPI_BYTE, rank - 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } while(hasToBeReceivedFromLeft); } if(iWillReceiveFromRight){ + printf("iWillReceiveFromRight (hasToBeReceivedFromRight %d leaves)\n", hasToBeReceivedFromRight); do{ - while(arrayIdxRight < bytesRecvFromRight){ + while(arrayIdxRight < sizeOfRightData){ const int particlesInThisLeaf = *(int*)&toRecvFromRight[arrayIdxRight]; arrayIdxRight += sizeof(int); ParticleClass*const particles = reinterpret_cast<ParticleClass*>(&toRecvFromRight[arrayIdxRight]); @@ -610,17 +542,21 @@ public: } arrayIdxRight = 0; + printf("Remains hasToBeReceivedFromRight %d leaves to receive\n",hasToBeReceivedFromRight); + printf("Elapsed %lf\n", counter.tacAndElapsed()); + 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; + printf("Probe\n"); + MPI_Probe( rank + 1, 0, MPI_COMM_WORLD, &status); + MPI_Get_count( &status, MPI_BYTE, &sizeOfRightData); + printf("Receive %d bytes from right\n", sizeOfRightData); + if(sizeOfRightBuffer < sizeOfRightData){ + sizeOfRightBuffer = sizeOfRightData; delete[] toRecvFromRight; - toRecvFromRight = new char[status_size]; + toRecvFromRight = new char[sizeOfRightData]; } - MPI_Recv(toRecvFromRight, status_size, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE); + MPI_Recv(toRecvFromRight, sizeOfRightData, MPI_BYTE, rank + 1 , 0 , MPI_COMM_WORLD, MPI_STATUS_IGNORE); } } while(hasToBeReceivedFromRight); } diff --git a/Tests/testFmbAlgorithmProc.cpp b/Tests/testFmbAlgorithmProc.cpp index f4a67781311eadad5b52e52b5c76816ed0fd9fc6..10c8c051d899d1a5c6b248df4c4a3353dab81821 100644 --- a/Tests/testFmbAlgorithmProc.cpp +++ b/Tests/testFmbAlgorithmProc.cpp @@ -257,19 +257,16 @@ int main(int argc, char ** argv){ std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl; counter.tic(); - { - // Buffer data - OctreeClass treeInterval(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); - int myNbParticlesCounter = 0; - + if( app.processCount() != 1){ ////////////////////////////////////////////////////////////////////////////////// // We sort our particles ////////////////////////////////////////////////////////////////////////////////// std::cout << "Create intervals ..." << std::endl; counter.tic(); - FMpiTreeBuilder<ContainerClass, ParticleClass>::SplitAndSortFile(treeInterval,myNbParticlesCounter,loader); - //FMpiTreeBuilder<ContainerClass, ParticleClass>::SplitAndSortFileWithoutQS(treeInterval,myNbParticlesCounter,loader); + FMpiTreeBuilder<ParticleClass> builder; + + builder.splitAndSortFile(loader, NbLevels); counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << "s)." << std::endl; @@ -280,16 +277,20 @@ int main(int argc, char ** argv){ std::cout << "Create real tree ..." << std::endl; counter.tic(); - FMpiTreeBuilder<ContainerClass, ParticleClass>::IntervalsToTree(tree,treeInterval,myNbParticlesCounter); + builder.intervalsToTree(tree); counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << "s)." << std::endl; ////////////////////////////////////////////////////////////////////////////////// - - app.processBarrier(); - - ////////////////////////////////////////////////////////////////////////////////// + } + else{ + FFmaBinLoader<ParticleClass> loaderSeq(filename); + ParticleClass partToInsert; + for(int idxPart = 0 ; idxPart < loaderSeq.getNumberOfParticles() ; ++idxPart){ + loaderSeq.fillParticle(partToInsert); + tree.insert(partToInsert); + } } counter.tac(); diff --git a/Tests/testFmmAlgorithmProc.cpp b/Tests/testFmmAlgorithmProc.cpp index 2ee6d2185f0b31367f99af35ca08810611c395a7..cab80983bd6dbc30d760dc4218cc881d936a441e 100644 --- a/Tests/testFmmAlgorithmProc.cpp +++ b/Tests/testFmmAlgorithmProc.cpp @@ -340,19 +340,16 @@ int main(int argc, char ** argv){ // The real tree to work on OctreeClass realTree(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); - { - // Buffer data - OctreeClass treeInterval(NbLevels, SizeSubLevels,loader.getBoxWidth(),loader.getCenterOfBox()); - int myNbParticlesCounter = 0; - + if( app.processCount() != 1){ ////////////////////////////////////////////////////////////////////////////////// // We sort our particles ////////////////////////////////////////////////////////////////////////////////// std::cout << "Create intervals ..." << std::endl; counter.tic(); - FMpiTreeBuilder<ContainerClass, ParticleClass>::SplitAndSortFile(treeInterval,myNbParticlesCounter,loader); - //FMpiTreeBuilder<ContainerClass, ParticleClass>::SplitAndSortFileWithoutQS(treeInterval,myNbParticlesCounter,loader); + FMpiTreeBuilder<ParticleClass> builder; + + builder.splitAndSortFile(loader, NbLevels); counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << "s)." << std::endl; @@ -363,16 +360,20 @@ int main(int argc, char ** argv){ std::cout << "Create real tree ..." << std::endl; counter.tic(); - FMpiTreeBuilder<ContainerClass, ParticleClass>::IntervalsToTree(realTree,treeInterval,myNbParticlesCounter); + builder.intervalsToTree(realTree); counter.tac(); std::cout << "Done " << "(" << counter.elapsed() << "s)." << std::endl; ////////////////////////////////////////////////////////////////////////////////// - - app.processBarrier(); - - ////////////////////////////////////////////////////////////////////////////////// + } + else{ + FFmaBinLoader<ParticleClass> loaderSeq(filename); + ParticleClass partToInsert; + for(int idxPart = 0 ; idxPart < loaderSeq.getNumberOfParticles() ; ++idxPart){ + loaderSeq.fillParticle(partToInsert); + realTree.insert(partToInsert); + } } //////////////////////////////////////////////////////////////////////////////////