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

Last change on this file since 828 was 815, checked in by mhnguyen, 8 years ago

Fixing the bug in ticket 72

+) The distributed axis on client side send info to correct corresponding server
+) Improve serverdistributiondescription class to make it more flexible
+) Create new test_basic_2D only for test cases of 2-d grid

Test
+) On Curie
+) All tests pass

File size: 7.8 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  int dim = nGlobal_.size();
120  std::vector<int> currentIndex(dim);
121
122  for (int idxServer = 0; idxServer < nServer_; ++idxServer)
123  {
124    size_t ssize = 1, idx = 0;
125    for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j];
126
127    std::vector<int> idxLoop(dim,0);
128    int innerLoopSize = dimensionSizes_[idxServer][0];
129
130    while (idx<ssize)
131    {
132      for (int idxDim = 0; idxDim < dim-1; ++idxDim)
133      {
134        if (idxLoop[idxDim] == dimensionSizes_[idxServer][idxDim])
135        {
136          idxLoop[idxDim] = 0;
137          ++idxLoop[idxDim+1];
138        }
139      }
140
141      for (int idxDim = 1; idxDim < dim; ++idxDim)  currentIndex[idxDim] = idxLoop[idxDim] + indexBegin_[idxServer][idxDim];
142
143      size_t mulDim, globalIndex;
144      for (int j = 0; j < innerLoopSize; ++j)
145      {
146        mulDim = 1;
147        globalIndex = j + indexBegin_[idxServer][0];
148
149        for (int k = 1; k < dim; ++k)
150        {
151          mulDim *= nGlobal_[k-1];
152          globalIndex += (currentIndex[k])*mulDim;
153        }
154        if ((indexBegin <= globalIndex) && (globalIndex <= indexEnd))
155          globalIndex_.insert(std::make_pair<size_t,int>(globalIndex, idxServer));
156        ++idx;
157      }
158      idxLoop[0] += innerLoopSize;
159    }
160  }
161
162}
163
164/*!
165  Compute global index of servers with band distribution
166  \param [in] nServer number of server
167*/
168void CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)
169{
170  int dim = nGlobal_.size();
171  positionDimensionDistributed_ = positionDimensionDistributed;
172  if (1 == dim) positionDimensionDistributed_ = 0;
173  if (positionDimensionDistributed_ > dim)
174    ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)",
175          << "Position of distributed dimension is invalid" << std::endl
176          << "Position of distributed dimension is " << positionDimensionDistributed_
177          << "Dimension " << dim)
178
179  indexBegin_.resize(nServer);
180  dimensionSizes_.resize(nServer);
181
182  for (int i = 0; i< nServer; ++i)
183  {
184    indexBegin_[i].resize(dim);
185    dimensionSizes_[i].resize(dim);
186  }
187
188  int njRangeSize;
189  int nGlobTemp = 0;
190  std::vector<int> njRangeBegin(nServer,0);
191  std::vector<int> njRangeEnd(nServer,0);
192
193  int positionDistributed = (1<dim) ? positionDimensionDistributed_ : 0;
194  nGlobTemp = nGlobal_[positionDistributed];
195
196  for (int i = 0; i < nServer; ++i)
197  {
198    if (0 < i) njRangeBegin[i] = njRangeEnd[i-1];
199    njRangeSize = nGlobTemp / nServer;
200    if (i < nGlobTemp%nServer) ++njRangeSize;
201    njRangeEnd[i] = njRangeSize + njRangeBegin[i];
202  }
203  njRangeEnd[nServer-1] = nGlobTemp;
204
205  for (int i = 0; i < nServer; ++i)
206  {
207    for (int j = 0; j < dim; ++j)
208    {
209      if (positionDistributed != j)
210      {
211        if (1 == dim)
212        {
213          indexBegin_[i][j] = njRangeBegin[i];
214          dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
215        }
216        else
217        {
218          indexBegin_[i][j] = 0;
219          dimensionSizes_[i][j] = nGlobal_[j];
220        }
221      }
222      else
223      {
224        indexBegin_[i][j] = njRangeBegin[i];
225        dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
226      }
227    }
228  }
229}
230
231/*!
232  Get size of each dimension on distributed server
233  \return size of dimensions on server(s)
234*/
235std::vector<std::vector<int> > CServerDistributionDescription::getServerDimensionSizes() const
236{
237  return dimensionSizes_;
238}
239
240/*!
241  Get index begin of each dimension on distributed server
242  \return index begin of dimensions on server(s)
243*/
244std::vector<std::vector<int> > CServerDistributionDescription::getServerIndexBegin() const
245{
246  return indexBegin_;
247}
248
249/*!
250  Get global index on distributed server
251  \return global index on server(s)
252*/
253const std::vector<CArray<size_t,1> >& CServerDistributionDescription::getGlobalIndex() const
254{
255  return vecGlobalIndex_;
256}
257
258/*!
259  Get global index calculated by computeServerGlobalIndexInRange
260*/
261const boost::unordered_map<size_t,int>& CServerDistributionDescription::getGlobalIndexRange() const
262{
263  return globalIndex_;
264}
265
266int CServerDistributionDescription::getDimensionDistributed()
267{
268  return ((1<nGlobal_.size()) ? positionDimensionDistributed_ : 0);
269}
270
271} // namespace xios
Note: See TracBrowser for help on using the repository browser.