XIOS  1.0
Xml I/O Server
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Définitions de type Énumérations Valeurs énumérées Amis Macros
server_distribution_description.cpp
Aller à la documentation de ce fichier.
1 
11 #include "exception.hpp"
12 
13 namespace xios
14 {
20 CServerDistributionDescription::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 
29 { /* Nothing to do */ }
30 
32  ServerDistributionType serType)
33 {
34  switch (serType)
35  {
36  case BAND_DISTRIBUTION:
37  return ((1 == gridDimension) ? 0 : 1);
38  break;
39  default:
40  break;
41  }
42 }
43 
50  int positionDimensionDistributed)
51 {
52  switch (serverType_) {
53  case BAND_DISTRIBUTION:
54  computeBandDistribution(nServer_, positionDimensionDistributed);
55  break;
56  default:
57  break;
58  }
59 
60  if (doComputeGlobalIndex)
61  {
62  vecGlobalIndex_.resize(nServer_);
63  int dim = nGlobal_.size();
64  std::vector<int> currentIndex(dim);
65 
66  for (int idxServer = 0; idxServer < nServer_; ++idxServer)
67  {
68  size_t ssize = 1, idx = 0;
69  for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j];
70  vecGlobalIndex_[idxServer].resize(ssize);
71 
72  std::vector<int> idxLoop(dim,0);
73 
74  int innerLoopSize = dimensionSizes_[idxServer][0];
75 
76  while (idx<ssize)
77  {
78  for (int idxDim = 0; idxDim < dim-1; ++idxDim)
79  {
80  if (idxLoop[idxDim] == dimensionSizes_[idxServer][idxDim])
81  {
82  idxLoop[idxDim] = 0;
83  ++idxLoop[idxDim+1];
84  }
85  }
86 
87  for (int idxDim = 1; idxDim < dim; ++idxDim) currentIndex[idxDim] = idxLoop[idxDim] + indexBegin_[idxServer][idxDim];
88 
89  size_t mulDim, globalIndex;
90  for (int j = 0; j < innerLoopSize; ++j)
91  {
92  mulDim = 1;
93  globalIndex = j + indexBegin_[idxServer][0];
94 
95  for (int k = 1; k < dim; ++k)
96  {
97  mulDim *= nGlobal_[k-1];
98  globalIndex += currentIndex[k] * mulDim;
99  }
100  vecGlobalIndex_[idxServer](idx) = globalIndex;
101  ++idx;
102  }
103  idxLoop[0] += innerLoopSize;
104  }
105  }
106  }
107 }
108 
115 std::vector<int> CServerDistributionDescription::computeServerGlobalIndexInRange(const std::pair<size_t, size_t>& indexBeginEnd,
116  int positionDimensionDistributed)
117 {
118  int nBand = 0;
119  switch (serverType_)
120  {
121  case BAND_DISTRIBUTION:
122  nBand = computeBandDistribution(nServer_, positionDimensionDistributed);
123  break;
124  case ROOT_DISTRIBUTION:
126  default:
127  break;
128  }
129 
130  size_t indexBegin = indexBeginEnd.first;
131  size_t indexEnd = indexBeginEnd.second;
132  if (indexBegin > indexEnd)
133  ERROR("CServerDistributionDescription::computeServerGlobalIndexInRange",
134  << "Index begin is larger than index end");
135 
136  globalIndex_.rehash(std::ceil((indexEnd-indexBegin+1)/globalIndex_.max_load_factor()));
137 
138  int dim = nGlobal_.size();
139  std::vector<int> currentIndex(dim);
140 
141  for (int idxServer = 0; idxServer < nBand; ++idxServer)
142  {
143  size_t ssize = 1, idx = 0;
144  for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j];
145 
146  std::vector<int> idxLoop(dim,0);
147  int innerLoopSize = dimensionSizes_[idxServer][0];
148 
149  while (idx<ssize)
150  {
151  for (int idxDim = 0; idxDim < dim-1; ++idxDim)
152  {
153  if (idxLoop[idxDim] == dimensionSizes_[idxServer][idxDim])
154  {
155  idxLoop[idxDim] = 0;
156  ++idxLoop[idxDim+1];
157  }
158  }
159 
160  for (int idxDim = 1; idxDim < dim; ++idxDim) currentIndex[idxDim] = idxLoop[idxDim] + indexBegin_[idxServer][idxDim];
161 
162  size_t mulDim, globalIndex;
163  for (int j = 0; j < innerLoopSize; ++j)
164  {
165  mulDim = 1;
166  globalIndex = j + indexBegin_[idxServer][0];
167 
168  for (int k = 1; k < dim; ++k)
169  {
170  mulDim *= nGlobal_[k-1];
171  globalIndex += (currentIndex[k])*mulDim;
172  }
173  if ((indexBegin <= globalIndex) && (globalIndex <= indexEnd))
174  globalIndex_[globalIndex] = idxServer;
175  ++idx;
176  }
177  idxLoop[0] += innerLoopSize;
178  }
179  }
180 
181  // List of servers without distribution (cause total number of server is greater than number of bands, for example)
182  std::vector<int> zeroIndexServer(nServer_-nBand);
183  for (int idxServer = nBand; idxServer < nServer_; ++idxServer)
184  zeroIndexServer[idxServer-nBand] = idxServer;
185 
186  return zeroIndexServer;
187 }
188 
198 std::vector<int> CServerDistributionDescription::computeServerGlobalByElement(std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
199  int clientRank,
200  int clientSize,
201  const CArray<int,1>& axisDomainOrder,
202  int positionDimensionDistributed)
203 {
204  int nBand = 0;
205  switch (serverType_) {
206  case BAND_DISTRIBUTION:
207  nBand = computeBandDistribution(nServer_, positionDimensionDistributed);
208  break;
209  default:
210  break;
211  }
212 
213  int nbElement = axisDomainOrder.numElements();
214  indexServerOnElement.resize(nbElement);
215  int idx = 0;
216  std::vector<int> idxMap(nbElement);
217  for (int i = 0; i < nbElement; ++i)
218  {
219  idxMap[i] = idx;
220  if (2 == axisDomainOrder(i)) idx += 2;
221  else if (1 == axisDomainOrder(i)) idx += 1;
222  // nothing for scalar
223  }
224 
225  for (int idxServer = 0; idxServer < nBand; ++idxServer)
226  {
227  std::vector<int> elementDimension(4);
228  for (int i = 0; i < nbElement; ++i)
229  {
230  int elementSize = 1;
231  if (2 == axisDomainOrder(i))
232  {
233  elementSize *= dimensionSizes_[idxServer][idxMap[i]] * dimensionSizes_[idxServer][idxMap[i]+1];
234  elementDimension[0] = indexBegin_[idxServer][idxMap[i]];
235  elementDimension[1] = indexBegin_[idxServer][idxMap[i]+1];
236  elementDimension[2] = dimensionSizes_[idxServer][idxMap[i]];
237  elementDimension[3] = dimensionSizes_[idxServer][idxMap[i]+1];
238  }
239 
240  else if (1 == axisDomainOrder(i))
241  {
242  elementSize *= dimensionSizes_[idxServer][idxMap[i]];
243  elementDimension[0] = indexBegin_[idxServer][idxMap[i]];
244  elementDimension[1] = 0;
245  elementDimension[2] = dimensionSizes_[idxServer][idxMap[i]];
246  elementDimension[3] = 1;
247  }
248  else
249  {
250  elementSize *= dimensionSizes_[idxServer][idxMap[i]];
251  elementDimension[0] = 0;
252  elementDimension[1] = 0;
253  elementDimension[2] = 1;
254  elementDimension[3] = 1;
255  }
256 
257  int rangeBegin, rangeSize;
258  computeRangeProcIndex(clientRank, clientSize, elementSize, rangeBegin, rangeSize);
259 
260  size_t globalIndexElement;
261  idx = 0; int idxRange = 0;
262  for (int k = 0; k < elementDimension[3]; ++k)
263  for (int l = 0; l < elementDimension[2]; ++l)
264  {
265  globalIndexElement = (l+elementDimension[0]) + (k+elementDimension[1])*elementDimension[2];
266  if ((rangeBegin <= idx) && (idxRange < rangeSize))
267  {
268  indexServerOnElement[i][globalIndexElement].push_back(idxServer);
269  ++idxRange;
270  }
271  ++idx;
272  }
273  }
274  }
275 
276  // List of servers without distribution (cause total number of server is greater than number of bands, for example)
277  std::vector<int> zeroIndexServer(nServer_-nBand);
278  for (int idxServer = nBand; idxServer < nServer_; ++idxServer)
279  zeroIndexServer[idxServer-nBand] = idxServer;
280 
281  return zeroIndexServer;
282 }
283 
295  int clientSize,
296  int rangeProcSize,
297  int& rangeBegin,
298  int& rangeSize)
299 {
300  if (rangeProcSize < clientSize)
301  {
302  int rangeIndex = 0;
303  for (int idx = 0; idx < clientSize; ++idx)
304  {
305  if (idx == clientRank)
306  {
307  rangeBegin = rangeIndex;
308  rangeSize = 1;
309  }
310  ++rangeIndex;
311  if (rangeIndex == rangeProcSize) rangeIndex = 0;
312  }
313  return;
314  }
315 
316  int range, indexBegin = 0;
317  for (int i = 0; i < clientSize; ++i)
318  {
319  range = rangeProcSize / clientSize;
320  if (i < (rangeProcSize%clientSize)) ++range;
321  if (i == clientRank) break;
322  indexBegin += range;
323  }
324  rangeBegin = indexBegin;
325  rangeSize = range;
326 }
327 
332 int CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)
333 {
334  int dim = nGlobal_.size();
335  positionDimensionDistributed_ = positionDimensionDistributed;
336  if (1 == dim) positionDimensionDistributed_ = 0;
338  ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)",
339  << "Position of distributed dimension is invalid" << std::endl
340  << "Position of distributed dimension is " << positionDimensionDistributed_
341  << "Dimension " << dim)
342 
343  indexBegin_.resize(nServer);
344  dimensionSizes_.resize(nServer);
345 
346  for (int i = 0; i< nServer; ++i)
347  {
348  indexBegin_[i].resize(dim);
349  dimensionSizes_[i].resize(dim);
350  }
351 
352  int njRangeSize;
353  int nGlobTemp = 0;
354  std::vector<int> njRangeBegin(nServer,0);
355  std::vector<int> njRangeEnd(nServer,0);
356 
357  int positionDistributed = (1<dim) ? positionDimensionDistributed_ : 0;
358  nGlobTemp = nGlobal_[positionDistributed];
359  int nbBand = std::min(nGlobTemp, nServer);
360 
361  for (int i = 0; i < nbBand; ++i)
362  {
363  if (0 < i) njRangeBegin[i] = njRangeEnd[i-1];
364  njRangeSize = nGlobTemp / nbBand;
365  if (i < nGlobTemp%nbBand) ++njRangeSize;
366  njRangeEnd[i] = njRangeSize + njRangeBegin[i];
367  }
368  njRangeEnd[nbBand-1] = nGlobTemp;
369 
370  for (int i = nbBand; i < nServer; ++i)
371  {
372  njRangeBegin[i] = njRangeEnd[i] = 0;
373  }
374 
375  for (int i = 0; i < nServer; ++i)
376  {
377  for (int j = 0; j < dim; ++j)
378  {
379  if (positionDistributed != j)
380  {
381  if (1 == dim)
382  {
383  indexBegin_[i][j] = njRangeBegin[i];
384  dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
385  }
386  else
387  {
388  indexBegin_[i][j] = 0;
389  dimensionSizes_[i][j] = nGlobal_[j];
390  }
391  }
392  else
393  {
394  indexBegin_[i][j] = njRangeBegin[i];
395  dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
396  }
397  }
398  }
399 
400  return nbBand;
401 }
402 
403 
408 int CServerDistributionDescription::computeRootDistribution(int nServer, int positionDimensionDistributed)
409 {
410  int dim = nGlobal_.size();
411  positionDimensionDistributed_ = positionDimensionDistributed;
412  if (1 == dim) positionDimensionDistributed_ = 0;
414  ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)",
415  << "Position of distributed dimension is invalid" << std::endl
416  << "Position of distributed dimension is " << positionDimensionDistributed_
417  << "Dimension " << dim)
418 
419  indexBegin_.resize(nServer);
420  dimensionSizes_.resize(nServer);
421 
422  for (int i = 0; i< nServer; ++i)
423  {
424  indexBegin_[i].resize(dim);
425  dimensionSizes_[i].resize(dim);
426  }
427 
428  int nGlobTemp = 0;
429 
430  int positionDistributed = (1<dim) ? positionDimensionDistributed_ : 0;
431  nGlobTemp = nGlobal_[positionDistributed];
432  int nbBand = 1 ;
433 
434 
435  for (int i = 0; i < nServer; ++i)
436  {
437  for (int j = 0; j < dim; ++j)
438  {
439  if (positionDistributed != j) // bad coding, need to be rewrite
440  {
441  if (1 == dim)
442  {
443  if (i==0)
444  {
445  indexBegin_[i][j] = 0;
446  dimensionSizes_[i][j] = nGlobTemp;
447  }
448  else
449  {
450  indexBegin_[i][j] = nGlobTemp-1;
451  dimensionSizes_[i][j] = 0;
452  }
453  }
454  else
455  {
456  indexBegin_[i][j] = 0;
457  dimensionSizes_[i][j] = nGlobal_[j];
458  }
459  }
460  else
461  {
462  if (i==0)
463  {
464  indexBegin_[i][j] = 0;
465  dimensionSizes_[i][j] = nGlobTemp;
466  }
467  else
468  {
469  indexBegin_[i][j] = nGlobTemp-1;
470  dimensionSizes_[i][j] = 0;
471  }
472  }
473  }
474  }
475 
476  return nbBand;
477 }
478 
479 
480 
481 
486 std::vector<std::vector<int> > CServerDistributionDescription::getServerDimensionSizes() const
487 {
488  return dimensionSizes_;
489 }
490 
495 std::vector<std::vector<int> > CServerDistributionDescription::getServerIndexBegin() const
496 {
497  return indexBegin_;
498 }
499 
504 const std::vector<CArray<size_t,1> >& CServerDistributionDescription::getGlobalIndex() const
505 {
506  return vecGlobalIndex_;
507 }
508 
512 const std::unordered_map<size_t,int>& CServerDistributionDescription::getGlobalIndexRange() const
513 {
514  return globalIndex_;
515 }
516 
518 {
519  return ((1<nGlobal_.size()) ? positionDimensionDistributed_ : 0);
520 }
521 
522 } // namespace xios
int computeRootDistribution(int nServer, int positionDimensionDistributed=1)
Compute global index of servers with root distribution : only root server will received data...
std::vector< int > computeServerGlobalIndexInRange(const std::pair< size_t, size_t > &indexBeginEnd, int positionDimensionDistributed=1)
Compute global index assigned to a server with a range.E.g: if a grid has 100 points and there are 2 ...
std::vector< std::vector< int > > getServerDimensionSizes() const
Get size of each dimension on distributed server.
#define xios(arg)
Description of index distribution on server(s).
std::vector< std::vector< int > > getServerIndexBegin() const
Get index begin of each dimension on distributed server.
const std::vector< CArray< size_t, 1 > > & getGlobalIndex() const
Get global index on distributed server.
ServerDistributionType serverType_
Number of server.
CATCH CScalarAlgorithmReduceScalar::CScalarAlgorithmReduceScalar(CScalar *scalarDestination, CScalar *scalarSource, CReduceScalarToScalar *algo ERROR)("CScalarAlgorithmReduceScalar::CScalarAlgorithmReduceScalar(CScalar* scalarDestination, CScalar* scalarSource, CReduceScalarToScalar* algo)",<< "Operation must be defined."<< "Scalar source "<< scalarSource->getId()<< std::endl<< "Scalar destination "<< scalarDestination->getId())
std::unordered_map< size_t, int > globalIndex_
Type of distribution on server side.
void resize(int extent)
Definition: array_new.hpp:320
void computeRangeProcIndex(int clientRank, int clientSize, int rangeProcSize, int &rangeBegin, int &rangeSize)
Compute a range of index on server which a client holds For a range of index on a specific server...
std::vector< std::vector< int > > indexBegin_
Begin index of each dimension.
void computeServerDistribution(bool doComputeGlobalIndex=false, int positionDimensionDistributed=1)
Compute pre-defined global index distribution of server(s).
int nServer_
Position of dimension distributed on server side (by default, the second dimension) ...
std::vector< std::vector< int > > dimensionSizes_
Size of each dimension.
const std::unordered_map< size_t, int > & getGlobalIndexRange() const
Get global index calculated by computeServerGlobalIndexInRange.
std::vector< int > nGlobal_
Global size of each dimension.
CServerDistributionDescription(const std::vector< int > &globalDimensionSize, int nServer, ServerDistributionType serType=BAND_DISTRIBUTION)
std::vector< int > computeServerGlobalByElement(std::vector< std::unordered_map< size_t, std::vector< int > > > &indexServerOnElement, int rank, int clientSize, const CArray< int, 1 > &axisDomainOrder, int positionDimensionDistributed=1)
Compute the global index of grid elements (domain, axis) and their associated server rank...
static int defaultDistributedDimension(int gridDimension, ServerDistributionType serType=BAND_DISTRIBUTION)
int computeBandDistribution(int nServer, int positionDimensionDistributed=1)
Compute global index of servers with band distribution.
std::vector< CArray< size_t, 1 > > vecGlobalIndex_
In case we need only global index of one server with specific rank.