X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FParaMEDMEM%2FOverlapElementLocator.cxx;h=f3d373392b12fe0d159e46b4943f3357b801548c;hb=b33408f1dc045a4d0f2e16d22f4930d7029996a3;hp=93984ccce561c36b5020cbfcad687d6ed06646ff;hpb=bbf8612da96d44148a83c01c0875e665dbf7902b;p=tools%2Fmedcoupling.git diff --git a/src/ParaMEDMEM/OverlapElementLocator.cxx b/src/ParaMEDMEM/OverlapElementLocator.cxx index 93984ccce..f3d373392 100644 --- a/src/ParaMEDMEM/OverlapElementLocator.cxx +++ b/src/ParaMEDMEM/OverlapElementLocator.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2015 CEA/DEN, EDF R&D +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -37,7 +37,7 @@ using namespace std; -namespace ParaMEDMEM +namespace MEDCoupling { const int OverlapElementLocator::START_TAG_MESH_XCH = 1140; @@ -48,8 +48,8 @@ namespace ParaMEDMEM _local_source_mesh(0), _local_target_mesh(0), _domain_bounding_boxes(0), - _group(group), - _epsAbs(epsAbs) + _epsAbs(epsAbs), + _group(group) { if(_local_source_field) _local_source_mesh=_local_source_field->getSupport()->getCellMesh(); @@ -58,13 +58,17 @@ namespace ParaMEDMEM _comm=getCommunicator(); computeBoundingBoxesAndInteractionList(); - if (workSharingAlgo == 0) - computeTodoList_original(); - else - if(workSharingAlgo == 1) - computeTodoList_new(); - else + switch(workSharingAlgo) + { + case 0: + computeTodoList_original(); break; + case 1: + computeTodoList_new(false); break; + case 2: + computeTodoList_new(true); break; + default: throw INTERP_KERNEL::Exception("OverlapElementLocator::OverlapElementLocator(): invalid algorithm selected!"); + } fillProcToSend(); } @@ -125,8 +129,8 @@ namespace ParaMEDMEM _proc_pairs.resize(_group.size()); for(int i=0;i<_group.size();i++) for(int j=0;j<_group.size();j++) - if(intersectsBoundingBox(i,j)) - _proc_pairs[i].push_back(j); + if(intersectsBoundingBox(i,j)) + _proc_pairs[i].push_back(j); } void OverlapElementLocator::computeTodoList_original() @@ -160,13 +164,14 @@ namespace ParaMEDMEM } /* More efficient (?) work sharing algorithm: a job (i,j) is initially assigned twice: to proc#i and to proc#j. - * Then try to reduce as much as possible the variance of the num of jobs per proc: + * Then try to reduce as much as possible the variance of the num of jobs per proc by selecting the right duplicate + * to remove: * - take the most loaded proc i, * + select the job (i,j) for which proc#j is the less loaded - * + remove this job from proc#i + * + remove this job from proc#i, and mark it as 'unremovable' from proc#j * - repeat until no more duplicates are found */ - void OverlapElementLocator::computeTodoList_new() + void OverlapElementLocator::computeTodoList_new(bool revertIter) { using namespace std; int infinity = std::numeric_limits::max(); @@ -196,9 +201,9 @@ namespace ParaMEDMEM else { if(cpl.first == procID) - (*itMap).second = full_set[cpl.second].size(); + (*itMap).second = (int)full_set[cpl.second].size(); else // cpl.second == srcProcID - (*itMap).second = full_set[cpl.first].size(); + (*itMap).second = (int)full_set[cpl.first].size(); } } INTERP_KERNEL::AutoPtr proc_valid = new bool[grp_size]; @@ -211,10 +216,10 @@ namespace ParaMEDMEM int max_sz = -1, max_id = -1; for(itVector = full_set.begin(), procID=0; itVector != full_set.end(); itVector++, procID++) { - int sz = (*itVector).size(); + int sz = (int)(*itVector).size(); if (proc_valid[procID] && sz > max_sz) { - max_sz = (*itVector).size(); + max_sz = sz; max_id = procID; } } @@ -226,9 +231,21 @@ namespace ParaMEDMEM int min_sz = infinity; map & max_map = full_set[max_id]; ProcCouple hit_cpl = make_pair(-1,-1); - for(itMap=max_map.begin(); itMap != max_map.end(); itMap++) - if ((*itMap).second < min_sz) - hit_cpl = (*itMap).first; + if(revertIter) + { + // Use a reverse iterator here increases our chances to hit a couple of the form (i, myProcId) + // meaning that the final matrix computed won't have to be sent: save some comm. + map ::const_reverse_iterator ritMap; + for(ritMap=max_map.rbegin(); ritMap != max_map.rend(); ritMap++) + if ((*ritMap).second < min_sz) + hit_cpl = (*ritMap).first; + } + else + { + for(itMap=max_map.begin(); itMap != max_map.end(); itMap++) + if ((*itMap).second < min_sz) + hit_cpl = (*itMap).first; + } if (hit_cpl.first == -1) { // Plouf. Current proc 'max_id' can not be reduced. Invalid it: @@ -275,6 +292,15 @@ namespace ParaMEDMEM #endif } + void OverlapElementLocator::debugPrintWorkSharing(std::ostream & ostr) const + { + std::vector< std::vector< ProcCouple > >::const_iterator it = _all_todo_lists.begin(); + ostr << "TODO list lengths: "; + for(; it != _all_todo_lists.end(); ++it) + ostr << (*it).size() << " "; + ostr << "\n"; + } + void OverlapElementLocator::fillProcToSend() { // Feeding now '_procs_to_send*'. A same id can appears twice. The second parameter in pair means what @@ -367,7 +393,7 @@ namespace ParaMEDMEM return (*it).second; } - const DataArrayInt *OverlapElementLocator::getSourceIds(int procId) const + const DataArrayIdType *OverlapElementLocator::getSourceIds(int procId) const { int myProcId=_group.myRank(); if(myProcId==procId) @@ -387,7 +413,7 @@ namespace ParaMEDMEM return (*it).second; } - const DataArrayInt *OverlapElementLocator::getTargetIds(int procId) const + const DataArrayIdType *OverlapElementLocator::getTargetIds(int procId) const { int myProcId=_group.myRank(); if(myProcId==procId) @@ -443,7 +469,7 @@ namespace ParaMEDMEM field=_local_target_field; } AutoDAInt elems=local_mesh->getCellsInBoundingBox(distant_bb,getBoundingBoxAdjustment()); - DataArrayInt *old2new_map; + DataArrayIdType *old2new_map; MEDCouplingPointSet *send_mesh=static_cast(field->getField()->buildSubMeshData(elems->begin(),elems->end(),old2new_map)); if(sourceOrTarget) matrix.keepTracksOfSourceIds(procId,old2new_map); @@ -455,12 +481,12 @@ namespace ParaMEDMEM } /*! - * This method recieves source remote mesh on proc 'procId' if sourceOrTarget==True - * This method recieves target remote mesh on proc 'procId' if sourceOrTarget==False + * This method receives source remote mesh on proc 'procId' if sourceOrTarget==True + * This method receives target remote mesh on proc 'procId' if sourceOrTarget==False */ void OverlapElementLocator::receiveRemoteMeshFrom(int procId, bool sourceOrTarget) { - DataArrayInt *old2new_map=0; + DataArrayIdType *old2new_map=0; MEDCouplingPointSet *m=0; receiveMesh(procId,m,old2new_map); Proc_SrcOrTgt p(procId,sourceOrTarget); @@ -468,57 +494,57 @@ namespace ParaMEDMEM _remote_elems[p]=old2new_map; } - void OverlapElementLocator::sendMesh(int procId, const MEDCouplingPointSet *mesh, const DataArrayInt *idsToSend) const + void OverlapElementLocator::sendMesh(int procId, const MEDCouplingPointSet *mesh, const DataArrayIdType *idsToSend) const { CommInterface comInterface=_group.getCommInterface(); // First stage : exchanging sizes vector tinyInfoLocalD;//tinyInfoLocalD not used for the moment - vector tinyInfoLocal; + vector tinyInfoLocal; vector tinyInfoLocalS; mesh->getTinySerializationInformation(tinyInfoLocalD,tinyInfoLocal,tinyInfoLocalS); const MPI_Comm *comm=getCommunicator(); // - int lgth[2]; - lgth[0]=tinyInfoLocal.size(); + mcIdType lgth[2]; + lgth[0]=ToIdType(tinyInfoLocal.size()); lgth[1]=idsToSend->getNbOfElems(); - comInterface.send(&lgth,2,MPI_INT,procId,START_TAG_MESH_XCH,*_comm); - comInterface.send(&tinyInfoLocal[0],tinyInfoLocal.size(),MPI_INT,procId,START_TAG_MESH_XCH+1,*comm); + comInterface.send(&lgth,2,MPI_ID_TYPE,procId,START_TAG_MESH_XCH,*_comm); + comInterface.send(&tinyInfoLocal[0],(int)tinyInfoLocal.size(),MPI_ID_TYPE,procId,START_TAG_MESH_XCH+1,*comm); // - DataArrayInt *v1Local=0; + DataArrayIdType *v1Local=0; DataArrayDouble *v2Local=0; mesh->serialize(v1Local,v2Local); - comInterface.send(v1Local->getPointer(),v1Local->getNbOfElems(),MPI_INT,procId,START_TAG_MESH_XCH+2,*comm); - comInterface.send(v2Local->getPointer(),v2Local->getNbOfElems(),MPI_DOUBLE,procId,START_TAG_MESH_XCH+3,*comm); + comInterface.send(v1Local->getPointer(),(int)v1Local->getNbOfElems(),MPI_ID_TYPE,procId,START_TAG_MESH_XCH+2,*comm); + comInterface.send(v2Local->getPointer(),(int)v2Local->getNbOfElems(),MPI_DOUBLE,procId,START_TAG_MESH_XCH+3,*comm); //finished for mesh, ids now - comInterface.send(const_cast(idsToSend->getConstPointer()),lgth[1],MPI_INT,procId,START_TAG_MESH_XCH+4,*comm); + comInterface.send(const_cast(idsToSend->getConstPointer()),(int)lgth[1],MPI_ID_TYPE,procId,START_TAG_MESH_XCH+4,*comm); // v1Local->decrRef(); v2Local->decrRef(); } - void OverlapElementLocator::receiveMesh(int procId, MEDCouplingPointSet* &mesh, DataArrayInt *&ids) const + void OverlapElementLocator::receiveMesh(int procId, MEDCouplingPointSet* &mesh, DataArrayIdType *&ids) const { - int lgth[2]; + mcIdType lgth[2]; MPI_Status status; const MPI_Comm *comm=getCommunicator(); CommInterface comInterface=_group.getCommInterface(); - comInterface.recv(lgth,2,MPI_INT,procId,START_TAG_MESH_XCH,*_comm,&status); - std::vector tinyInfoDistant(lgth[0]); - ids=DataArrayInt::New(); + comInterface.recv(lgth,2,MPI_ID_TYPE,procId,START_TAG_MESH_XCH,*_comm,&status); + std::vector tinyInfoDistant(lgth[0]); + ids=DataArrayIdType::New(); ids->alloc(lgth[1],1); - comInterface.recv(&tinyInfoDistant[0],lgth[0],MPI_INT,procId,START_TAG_MESH_XCH+1,*comm,&status); + comInterface.recv(&tinyInfoDistant[0],(int)lgth[0],MPI_ID_TYPE,procId,START_TAG_MESH_XCH+1,*comm,&status); mesh=MEDCouplingPointSet::BuildInstanceFromMeshType((MEDCouplingMeshType)tinyInfoDistant[0]); std::vector unusedTinyDistantSts; vector tinyInfoDistantD(1);//tinyInfoDistantD not used for the moment - DataArrayInt *v1Distant=DataArrayInt::New(); + DataArrayIdType *v1Distant=DataArrayIdType::New(); DataArrayDouble *v2Distant=DataArrayDouble::New(); mesh->resizeForUnserialization(tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts); - comInterface.recv(v1Distant->getPointer(),v1Distant->getNbOfElems(),MPI_INT,procId,START_TAG_MESH_XCH+2,*comm,&status); - comInterface.recv(v2Distant->getPointer(),v2Distant->getNbOfElems(),MPI_DOUBLE,procId,START_TAG_MESH_XCH+3,*comm,&status); + comInterface.recv(v1Distant->getPointer(),(int)v1Distant->getNbOfElems(),MPI_ID_TYPE,procId,START_TAG_MESH_XCH+2,*comm,&status); + comInterface.recv(v2Distant->getPointer(),(int)v2Distant->getNbOfElems(),MPI_DOUBLE,procId,START_TAG_MESH_XCH+3,*comm,&status); mesh->unserialization(tinyInfoDistantD,tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts); //finished for mesh, ids now - comInterface.recv(ids->getPointer(),lgth[1],MPI_INT,procId,1144,*comm,&status); + comInterface.recv(ids->getPointer(),(int)lgth[1],MPI_ID_TYPE,procId,1144,*comm,&status); // v1Distant->decrRef(); v2Distant->decrRef();