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

Last change on this file since 653 was 653, checked in by rlacroix, 9 years ago

Distributions and transformations: Avoid using heap allocations.

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