/*! \file server_distribution_description.hpp \author Ha NGUYEN \since 04 Jan 2015 \date 11 Jan 2016 \brief Description of index distribution on server(s). */ #include "server_distribution_description.hpp" #include "exception.hpp" namespace xios { /*! \param [in] globalDimensionSize global dimension of grid \param [in] nServer number of server \param [in] serType type of server distribution. For now, we can distribute server by band or plan */ CServerDistributionDescription::CServerDistributionDescription(const std::vector& globalDimensionSize, int nServer, ServerDistributionType serType) : nGlobal_(globalDimensionSize), indexBegin_(), dimensionSizes_(), globalIndex_(), vecGlobalIndex_(), serverType_(serType), nServer_(nServer), positionDimensionDistributed_(1) { } CServerDistributionDescription::~CServerDistributionDescription() { /* Nothing to do */ } /*! Compute pre-defined global index distribution of server(s). \param [in] doComputeGlobalIndex flag to compute global index on each server. By default, false */ void CServerDistributionDescription::computeServerDistribution(bool doComputeGlobalIndex, int positionDimensionDistributed) { switch (serverType_) { case BAND_DISTRIBUTION: computeBandDistribution(nServer_, positionDimensionDistributed); break; default: break; } if (doComputeGlobalIndex) { vecGlobalIndex_.resize(nServer_); int dim = nGlobal_.size(); std::vector currentIndex(dim); for (int idxServer = 0; idxServer < nServer_; ++idxServer) { size_t ssize = 1, idx = 0; for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j]; vecGlobalIndex_[idxServer].resize(ssize); std::vector idxLoop(dim,0); int innerLoopSize = dimensionSizes_[idxServer][0]; while (idx& indexBeginEnd, int positionDimensionDistributed) { switch (serverType_) { case BAND_DISTRIBUTION: computeBandDistribution(nServer_, positionDimensionDistributed); break; default: break; } size_t indexBegin = indexBeginEnd.first; size_t indexEnd = indexBeginEnd.second; if (indexBegin > indexEnd) ERROR("CServerDistributionDescription::computeServerGlobalIndexInRange", << "Index begin is larger than index end"); globalIndex_.rehash(std::ceil((indexEnd-indexBegin+1)/globalIndex_.max_load_factor())); int dim = nGlobal_.size(); std::vector currentIndex(dim); for (int idxServer = 0; idxServer < nServer_; ++idxServer) { size_t ssize = 1, idx = 0; for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j]; std::vector idxLoop(dim,0); int innerLoopSize = dimensionSizes_[idxServer][0]; while (idx > >& indexServerOnElement, int clientRank, int clientSize, const CArray& axisDomainOrder, int positionDimensionDistributed) { switch (serverType_) { case BAND_DISTRIBUTION: computeBandDistribution(nServer_, positionDimensionDistributed); break; default: break; } int nbElement = axisDomainOrder.numElements(); indexServerOnElement.resize(nbElement); int idx = 0; std::vector idxMap(nbElement); for (int i = 0; i < nbElement; ++i) { idxMap[i] = idx; if (2 == axisDomainOrder(i)) idx += 2; else ++idx; } for (int idxServer = 0; idxServer < nServer_; ++idxServer) { std::vector elementDimension(4); for (int i = 0; i < nbElement; ++i) { int elementSize = 1; if (2 == axisDomainOrder(i)) { elementSize *= dimensionSizes_[idxServer][idxMap[i]] * dimensionSizes_[idxServer][idxMap[i]+1]; elementDimension[0] = indexBegin_[idxServer][idxMap[i]]; elementDimension[1] = indexBegin_[idxServer][idxMap[i]+1]; elementDimension[2] = dimensionSizes_[idxServer][idxMap[i]]; elementDimension[3] = dimensionSizes_[idxServer][idxMap[i]+1]; } else if (1 == axisDomainOrder(i)) { elementSize *= dimensionSizes_[idxServer][idxMap[i]]; elementDimension[0] = indexBegin_[idxServer][idxMap[i]]; elementDimension[1] = 0; elementDimension[2] = dimensionSizes_[idxServer][idxMap[i]]; elementDimension[3] = 1; } else { elementSize *= dimensionSizes_[idxServer][idxMap[i]]; elementDimension[0] = 0; elementDimension[1] = 0; elementDimension[2] = 1; elementDimension[3] = 1; } int rangeBegin, rangeSize; computeRangeProcIndex(clientRank, clientSize, elementSize, rangeBegin, rangeSize); size_t globalIndexElement; idx = 0; int idxRange = 0; for (int k = 0; k < elementDimension[3]; ++k) for (int l = 0; l < elementDimension[2]; ++l) { globalIndexElement = (l+elementDimension[0]) + (k+elementDimension[1])*elementDimension[2]; if ((rangeBegin <= idx) && (idxRange < rangeSize)) { indexServerOnElement[i][globalIndexElement].push_back(idxServer); ++idxRange; } ++idx; } } } } /*! Compute a range of index on server which a client holds For a range of index on a specific server, each client can hold a piece of the index range If the range size is smaller than the number of client, there are some clients holding the same index \param [in] clientRank rank of client \param [in] clientSize number of client \param [in] rangeProcSize index range size \param [out] rangeBegin begin of range index a client holds \param [out] rangeSize size of range index a client holds */ void CServerDistributionDescription::computeRangeProcIndex(int clientRank, int clientSize, int rangeProcSize, int& rangeBegin, int& rangeSize) { if (rangeProcSize < clientSize) { int rangeIndex = 0; for (int idx = 0; idx < clientSize; ++idx) { if (idx == clientRank) { rangeBegin = rangeIndex; rangeSize = 1; } ++rangeIndex; if (rangeIndex == rangeProcSize) rangeIndex = 0; } return; } int range, indexBegin = 0; for (int i = 0; i < clientSize; ++i) { range = rangeProcSize / clientSize; if (i < (rangeProcSize%clientSize)) ++range; if (i == clientRank) break; indexBegin += range; } rangeBegin = indexBegin; rangeSize = range; } /*! Compute global index of servers with band distribution \param [in] nServer number of server */ void CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed) { int dim = nGlobal_.size(); positionDimensionDistributed_ = positionDimensionDistributed; if (1 == dim) positionDimensionDistributed_ = 0; if (positionDimensionDistributed_ > dim) ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)", << "Position of distributed dimension is invalid" << std::endl << "Position of distributed dimension is " << positionDimensionDistributed_ << "Dimension " << dim) indexBegin_.resize(nServer); dimensionSizes_.resize(nServer); for (int i = 0; i< nServer; ++i) { indexBegin_[i].resize(dim); dimensionSizes_[i].resize(dim); } int njRangeSize; int nGlobTemp = 0; std::vector njRangeBegin(nServer,0); std::vector njRangeEnd(nServer,0); int positionDistributed = (1 > CServerDistributionDescription::getServerDimensionSizes() const { return dimensionSizes_; } /*! Get index begin of each dimension on distributed server \return index begin of dimensions on server(s) */ std::vector > CServerDistributionDescription::getServerIndexBegin() const { return indexBegin_; } /*! Get global index on distributed server \return global index on server(s) */ const std::vector >& CServerDistributionDescription::getGlobalIndex() const { return vecGlobalIndex_; } /*! Get global index calculated by computeServerGlobalIndexInRange */ const boost::unordered_map& CServerDistributionDescription::getGlobalIndexRange() const { return globalIndex_; } int CServerDistributionDescription::getDimensionDistributed() { return ((1