MultiBlockManagement3D reparallelize(MultiBlockManagement3D const& management, plint blockLx, plint blockLy, plint blockLz) { SparseBlockStructure3D resultStructure = reparallelize(management.getSparseBlockStructure(), blockLx, blockLy, blockLz); plint numBlocks = resultStructure.nextIncrementalId(); plint numProcs = global::mpi().getSize(); // Create a thread attribution from scratch, by partitioning the // available blocks equally. ExplicitThreadAttribution* threadAttribution = new ExplicitThreadAttribution; plint iBlock=0; for (plint iProc=0; iProc<numProcs; ++iProc) { plint localNumBlocks = numBlocks/numProcs; if (iProc<numBlocks%numProcs) { ++localNumBlocks; } for (plint iLocal=0; iLocal<localNumBlocks; ++iLocal) { threadAttribution->addBlock(iBlock, iProc); ++iBlock; } } return MultiBlockManagement3D ( resultStructure, threadAttribution, management.getEnvelopeWidth(), management.getRefinementLevel() ); }
MultiBlockManagement3D RandomRedistribute3D::redistribute ( MultiBlockManagement3D const& original ) const { ThreadAttribution const& originalAttribution = original.getThreadAttribution(); SparseBlockStructure3D const& originalSparseBlock = original.getSparseBlockStructure(); std::map<plint,Box3D> const& domains = originalSparseBlock.getBulks(); std::vector<std::pair<plint,plint> > blockToProc(domains.size()); std::map<plint,Box3D>::const_iterator it = domains.begin(); for (plint pos=0; it != domains.end(); ++it, ++pos) { plint blockId = it->first; plint procId = originalAttribution.getMpiProcess(blockId); blockToProc[pos] = std::pair<plint,plint>(blockId,procId); } srand(rseed); plint numExchange = (plint)blockToProc.size()*10; for (plint iExch=0; iExch<numExchange; ++iExch) { plint id1 = rand() % blockToProc.size(); plint id2 = rand() % blockToProc.size(); std::swap(blockToProc[id1].second, blockToProc[id2].second); } ExplicitThreadAttribution* newAttribution = new ExplicitThreadAttribution; for (pluint i=0; i<blockToProc.size(); ++i) { newAttribution->addBlock(blockToProc[i].first, blockToProc[i].second); } return MultiBlockManagement3D ( originalSparseBlock, newAttribution, original.getEnvelopeWidth(), original.getRefinementLevel() ); }
MultiBlockManagement3D align( MultiBlockManagement3D const& originalManagement, MultiBlockManagement3D const& partnerManagement ) { std::vector<plint> newIds; std::map<plint,std::vector<plint> > remappedFromPartner; SparseBlockStructure3D resultStructure = alignDistribution3D(originalManagement.getSparseBlockStructure(), partnerManagement.getSparseBlockStructure(), newIds, remappedFromPartner); // 1. Parallelize the left-over blocks (the ones which don't overlap // with partnerManagement) evenly. ExplicitThreadAttribution attribution; plint numBlocks = (plint) newIds.size(); plint numProcs = global::mpi().getSize(); plint iBlock=0; for (plint iProc=0; iProc<numProcs; ++iProc) { plint localNumBlocks = numBlocks/numProcs; if (iProc<numBlocks%numProcs) { ++localNumBlocks; } for (plint iLocal=0; iLocal<localNumBlocks; ++iLocal) { attribution.addBlock(newIds[iBlock], iProc); ++iBlock; } } // 2. Merge remapped ids into the thread attribution, and return a // corresponding MultiBlockManagement3D object. return MultiBlockManagement3D ( resultStructure, attribution.merge ( partnerManagement.getThreadAttribution(), remappedFromPartner ), originalManagement.getEnvelopeWidth(), originalManagement.getRefinementLevel() ); }