source: XIOS/trunk/src/server_distribution_description.cpp @ 843

Last change on this file since 843 was 843, checked in by mhnguyen, 5 years ago

Several improvements

+) Replace some time-consuming operations by simpler ones

Test
+) On Curie
+) All tests pass

File size: 7.9 KB
Line 
1/*!
2   \file server_distribution_description.hpp
3   \author Ha NGUYEN
4   \since 04 Jan 2015
5   \date 11 Jan 2016
6
7   \brief Description of index distribution on server(s).
8 */
9
10#include "server_distribution_description.hpp"
11#include "exception.hpp"
12
13namespace xios
14{
15  /*!
16  \param [in] globalDimensionSize global dimension of grid
17  \param [in] nServer number of server
18  \param [in] serType type of server distribution. For now, we can distribute server by band or plan
19  */
20CServerDistributionDescription::CServerDistributionDescription(const std::vector<int>& globalDimensionSize,
21                                                               int nServer,
22                                                               ServerDistributionType serType)
23  : nGlobal_(globalDimensionSize), indexBegin_(), dimensionSizes_(), globalIndex_(),
24    vecGlobalIndex_(), serverType_(serType), nServer_(nServer), positionDimensionDistributed_(1)
25{
26}
27
28CServerDistributionDescription::~CServerDistributionDescription()
29{ /* Nothing to do */ }
30
31/*!
32  Compute pre-defined global index distribution of server(s).
33  \param [in] doComputeGlobalIndex flag to compute global index on each server. By default, false
34
35*/
36void CServerDistributionDescription::computeServerDistribution(bool doComputeGlobalIndex,
37                                                               int positionDimensionDistributed)
38{
39  switch (serverType_) {
40    case BAND_DISTRIBUTION:
41      computeBandDistribution(nServer_, positionDimensionDistributed);
42      break;
43    default:
44      break;
45  }
46
47  if (doComputeGlobalIndex)
48  {
49    vecGlobalIndex_.resize(nServer_);
50    int dim = nGlobal_.size();
51    std::vector<int> currentIndex(dim);
52
53    for (int idxServer = 0; idxServer < nServer_; ++idxServer)
54    {
55      size_t ssize = 1, idx = 0;
56      for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j];
57      vecGlobalIndex_[idxServer].resize(ssize);
58
59      std::vector<int> idxLoop(dim,0);
60
61      int innerLoopSize = dimensionSizes_[idxServer][0];
62
63      while (idx<ssize)
64      {
65        for (int idxDim = 0; idxDim < dim-1; ++idxDim)
66        {
67          if (idxLoop[idxDim] == dimensionSizes_[idxServer][idxDim])
68          {
69            idxLoop[idxDim] = 0;
70            ++idxLoop[idxDim+1];
71          }
72        }
73
74        for (int idxDim = 1; idxDim < dim; ++idxDim)  currentIndex[idxDim] = idxLoop[idxDim] + indexBegin_[idxServer][idxDim];
75
76        size_t mulDim, globalIndex;
77        for (int j = 0; j < innerLoopSize; ++j)
78        {
79          mulDim = 1;
80          globalIndex = j + indexBegin_[idxServer][0];
81
82          for (int k = 1; k < dim; ++k)
83          {
84            mulDim *= nGlobal_[k-1];
85            globalIndex += currentIndex[k] * mulDim;
86          }
87          vecGlobalIndex_[idxServer](idx) = globalIndex;
88          ++idx;
89        }
90        idxLoop[0] += innerLoopSize;
91      }
92    }
93  }
94}
95
96/*!
97  Compute global index assigned to a server with a range.E.g: if a grid has 100 points and
98  there are 2 servers, the first one takes index from 0 to 49, the second has index from 50 to 99
99
100  \param [in] indexBeginEnd begining and ending index of range
101*/
102void CServerDistributionDescription::computeServerGlobalIndexInRange(const std::pair<size_t, size_t>& indexBeginEnd,
103                                                                     int positionDimensionDistributed)
104{
105  switch (serverType_) {
106    case BAND_DISTRIBUTION:
107      computeBandDistribution(nServer_, positionDimensionDistributed);
108      break;
109    default:
110      break;
111  }
112
113  size_t indexBegin = indexBeginEnd.first;
114  size_t indexEnd   = indexBeginEnd.second;
115  if (indexBegin > indexEnd)
116     ERROR("CServerDistributionDescription::computeServerGlobalIndexInRange",
117           << "Index begin is larger than index end");
118
119  globalIndex_.rehash(std::ceil((indexEnd-indexBegin+1)/globalIndex_.max_load_factor()));
120
121  int dim = nGlobal_.size();
122  std::vector<int> currentIndex(dim);
123
124  for (int idxServer = 0; idxServer < nServer_; ++idxServer)
125  {
126    size_t ssize = 1, idx = 0;
127    for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j];
128
129    std::vector<int> idxLoop(dim,0);
130    int innerLoopSize = dimensionSizes_[idxServer][0];
131
132    while (idx<ssize)
133    {
134      for (int idxDim = 0; idxDim < dim-1; ++idxDim)
135      {
136        if (idxLoop[idxDim] == dimensionSizes_[idxServer][idxDim])
137        {
138          idxLoop[idxDim] = 0;
139          ++idxLoop[idxDim+1];
140        }
141      }
142
143      for (int idxDim = 1; idxDim < dim; ++idxDim)  currentIndex[idxDim] = idxLoop[idxDim] + indexBegin_[idxServer][idxDim];
144
145      size_t mulDim, globalIndex;
146      for (int j = 0; j < innerLoopSize; ++j)
147      {
148        mulDim = 1;
149        globalIndex = j + indexBegin_[idxServer][0];
150
151        for (int k = 1; k < dim; ++k)
152        {
153          mulDim *= nGlobal_[k-1];
154          globalIndex += (currentIndex[k])*mulDim;
155        }
156        if ((indexBegin <= globalIndex) && (globalIndex <= indexEnd))
157          globalIndex_[globalIndex] = idxServer;
158        ++idx;
159      }
160      idxLoop[0] += innerLoopSize;
161    }
162  }
163
164}
165
166/*!
167  Compute global index of servers with band distribution
168  \param [in] nServer number of server
169*/
170void CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)
171{
172  int dim = nGlobal_.size();
173  positionDimensionDistributed_ = positionDimensionDistributed;
174  if (1 == dim) positionDimensionDistributed_ = 0;
175  if (positionDimensionDistributed_ > dim)
176    ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)",
177          << "Position of distributed dimension is invalid" << std::endl
178          << "Position of distributed dimension is " << positionDimensionDistributed_
179          << "Dimension " << dim)
180
181  indexBegin_.resize(nServer);
182  dimensionSizes_.resize(nServer);
183
184  for (int i = 0; i< nServer; ++i)
185  {
186    indexBegin_[i].resize(dim);
187    dimensionSizes_[i].resize(dim);
188  }
189
190  int njRangeSize;
191  int nGlobTemp = 0;
192  std::vector<int> njRangeBegin(nServer,0);
193  std::vector<int> njRangeEnd(nServer,0);
194
195  int positionDistributed = (1<dim) ? positionDimensionDistributed_ : 0;
196  nGlobTemp = nGlobal_[positionDistributed];
197
198  for (int i = 0; i < nServer; ++i)
199  {
200    if (0 < i) njRangeBegin[i] = njRangeEnd[i-1];
201    njRangeSize = nGlobTemp / nServer;
202    if (i < nGlobTemp%nServer) ++njRangeSize;
203    njRangeEnd[i] = njRangeSize + njRangeBegin[i];
204  }
205  njRangeEnd[nServer-1] = nGlobTemp;
206
207  for (int i = 0; i < nServer; ++i)
208  {
209    for (int j = 0; j < dim; ++j)
210    {
211      if (positionDistributed != j)
212      {
213        if (1 == dim)
214        {
215          indexBegin_[i][j] = njRangeBegin[i];
216          dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
217        }
218        else
219        {
220          indexBegin_[i][j] = 0;
221          dimensionSizes_[i][j] = nGlobal_[j];
222        }
223      }
224      else
225      {
226        indexBegin_[i][j] = njRangeBegin[i];
227        dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
228      }
229    }
230  }
231}
232
233/*!
234  Get size of each dimension on distributed server
235  \return size of dimensions on server(s)
236*/
237std::vector<std::vector<int> > CServerDistributionDescription::getServerDimensionSizes() const
238{
239  return dimensionSizes_;
240}
241
242/*!
243  Get index begin of each dimension on distributed server
244  \return index begin of dimensions on server(s)
245*/
246std::vector<std::vector<int> > CServerDistributionDescription::getServerIndexBegin() const
247{
248  return indexBegin_;
249}
250
251/*!
252  Get global index on distributed server
253  \return global index on server(s)
254*/
255const std::vector<CArray<size_t,1> >& CServerDistributionDescription::getGlobalIndex() const
256{
257  return vecGlobalIndex_;
258}
259
260/*!
261  Get global index calculated by computeServerGlobalIndexInRange
262*/
263const boost::unordered_map<size_t,int>& CServerDistributionDescription::getGlobalIndexRange() const
264{
265  return globalIndex_;
266}
267
268int CServerDistributionDescription::getDimensionDistributed()
269{
270  return ((1<nGlobal_.size()) ? positionDimensionDistributed_ : 0);
271}
272
273} // namespace xios
Note: See TracBrowser for help on using the repository browser.