source: XIOS/trunk/src/transformation/axis_algorithm_inverse.cpp @ 890

Last change on this file since 890 was 869, checked in by mhnguyen, 8 years ago

Removing the usage of blocking MPI on transformations

+) Use non-blocking MPI for axis inversion

Test
+) On Curie
+) test pass

File size: 9.6 KB
Line 
1/*!
2   \file axis_algorithm_inverse.hpp
3   \author Ha NGUYEN
4   \since 14 May 2015
5   \date 29 June 2015
6
7   \brief Algorithm for inversing an axis..
8 */
9#include "axis_algorithm_inverse.hpp"
10#include "context.hpp"
11#include "context_client.hpp"
12#include "axis.hpp"
13#include "client_client_dht_template.hpp"
14
15namespace xios {
16
17CAxisAlgorithmInverse::CAxisAlgorithmInverse(CAxis* axisDestination, CAxis* axisSource)
18 : CAxisAlgorithmTransformation(axisDestination, axisSource)
19{
20  if (axisDestination->n_glo.getValue() != axisSource->n_glo.getValue())
21  {
22    ERROR("CAxisAlgorithmInverse::CAxisAlgorithmInverse(CAxis* axisDestination, CAxis* axisSource)",
23           << "Two axis have different global size"
24           << "Size of axis source " <<axisSource->getId() << " is " << axisSource->n_glo.getValue()  << std::endl
25           << "Size of axis destination " <<axisDestination->getId() << " is " << axisDestination->n_glo.getValue());
26  }
27}
28
29void CAxisAlgorithmInverse::computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs)
30{
31  this->transformationMapping_.resize(1);
32  this->transformationWeight_.resize(1);
33
34  TransformationIndexMap& transMap = this->transformationMapping_[0];
35  TransformationWeightMap& transWeight = this->transformationWeight_[0];
36
37  int globalIndexSize = axisDestGlobalIndex_.size();
38  for (int idx = 0; idx < globalIndexSize; ++idx)
39  {
40    transMap[axisDestGlobalIndex_[idx]].push_back(axisDestGlobalSize_-axisDestGlobalIndex_[idx]-1);
41    transWeight[axisDestGlobalIndex_[idx]].push_back(1.0);
42  }
43
44  int niSrc   = axisSrc_->n.getValue();
45  int sizeSrc = axisSrc_->n_glo.getValue();
46  if (niSrc != sizeSrc) updateAxisValue();
47  else
48  {
49    for (int idx = 0; idx < sizeSrc; ++idx)
50    {
51      axisDest_->value(idx) = axisSrc_->value(sizeSrc-idx-1);
52    }
53  }
54}
55
56/*!
57  Update value on axis after inversing
58  After an axis is inversed, not only the data on it must be inversed but also the value
59*/
60void CAxisAlgorithmInverse::updateAxisValue()
61{
62  CContext* context = CContext::getCurrent();
63  CContextClient* client=context->client;
64  int clientRank = client->clientRank;
65  int nbClient = client->clientSize;
66
67  int niSrc     = axisSrc_->n.getValue();
68  int ibeginSrc = axisSrc_->begin.getValue();
69  int nSrc = axisSrc_->index.numElements();
70
71  CClientClientDHTInt::Index2VectorInfoTypeMap globalIndex2ProcRank;
72  for (int idx = 0; idx < nSrc; ++idx)
73  {
74    if ((axisSrc_->mask)(idx))
75    {
76      globalIndex2ProcRank[(axisSrc_->index)(idx)].resize(1);
77      globalIndex2ProcRank[(axisSrc_->index)(idx)][0] = clientRank;
78    }
79  }
80
81  typedef boost::unordered_map<size_t, std::vector<double> > GlobalIndexMapFromSrcToDest;
82  GlobalIndexMapFromSrcToDest globalIndexMapFromSrcToDest;
83  TransformationIndexMap& transMap = this->transformationMapping_[0];
84  TransformationIndexMap::const_iterator itb = transMap.begin(), ite = transMap.end(), it;
85  CArray<size_t,1> globalSrcIndex(transMap.size());
86  int localIndex = 0;
87  for (it = itb; it != ite; ++it)
88  {
89    size_t srcIndex = it->second[0];
90    globalIndexMapFromSrcToDest[srcIndex].resize(1);
91    globalIndexMapFromSrcToDest[srcIndex][0] = it->first;
92    globalSrcIndex(localIndex) = srcIndex;
93    ++localIndex;
94  }
95
96  CClientClientDHTInt dhtIndexProcRank(globalIndex2ProcRank, client->intraComm);
97  dhtIndexProcRank.computeIndexInfoMapping(globalSrcIndex);
98  CClientClientDHTInt::Index2VectorInfoTypeMap& computedGlobalIndexOnProc = dhtIndexProcRank.getInfoIndexMap();
99  boost::unordered_map<int, std::vector<size_t> > globalSrcIndexSendToProc;
100  for (int idx = 0; idx < localIndex; ++idx)
101  {
102    size_t tmpIndex = globalSrcIndex(idx);
103    if (1 == computedGlobalIndexOnProc.count(tmpIndex))
104    {
105      std::vector<int>& tmpVec = computedGlobalIndexOnProc[tmpIndex];
106      globalSrcIndexSendToProc[tmpVec[0]].push_back(tmpIndex);
107    }
108  }
109
110
111  boost::unordered_map<int, std::vector<size_t> >::const_iterator itbIndex = globalSrcIndexSendToProc.begin(), itIndex,
112                                                                  iteIndex = globalSrcIndexSendToProc.end();
113  std::map<int,int> sendRankSizeMap,recvRankSizeMap;
114  int connectedClient = globalSrcIndexSendToProc.size();
115  int* recvCount=new int[nbClient];
116  int* displ=new int[nbClient];
117  int* sendRankBuff=new int[connectedClient];
118  int* sendSizeBuff=new int[connectedClient];
119  int n = 0;
120  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex, ++n)
121  {
122    sendRankBuff[n] = itIndex->first;
123    int sendSize = itIndex->second.size();
124    sendSizeBuff[n] = sendSize;
125    sendRankSizeMap[itIndex->first] = sendSize;
126  }
127  MPI_Allgather(&connectedClient,1,MPI_INT,recvCount,1,MPI_INT,client->intraComm);
128
129  displ[0]=0 ;
130  for(int n=1;n<nbClient;n++) displ[n]=displ[n-1]+recvCount[n-1];
131  int recvSize=displ[nbClient-1]+recvCount[nbClient-1];
132  int* recvRankBuff=new int[recvSize];
133  int* recvSizeBuff=new int[recvSize];
134  MPI_Allgatherv(sendRankBuff,connectedClient,MPI_INT,recvRankBuff,recvCount,displ,MPI_INT,client->intraComm);
135  MPI_Allgatherv(sendSizeBuff,connectedClient,MPI_INT,recvSizeBuff,recvCount,displ,MPI_INT,client->intraComm);
136  for (int i = 0; i < nbClient; ++i)
137  {
138    int currentPos = displ[i];
139    for (int j = 0; j < recvCount[i]; ++j)
140      if (recvRankBuff[currentPos+j] == clientRank)
141      {
142        recvRankSizeMap[i] = recvSizeBuff[currentPos+j];
143      }
144  }
145
146  // Sending global index of grid source to corresponding process as well as the corresponding mask
147  std::vector<MPI_Request> requests;
148  std::vector<MPI_Status> status;
149  boost::unordered_map<int, unsigned long* > recvGlobalIndexSrc;
150  boost::unordered_map<int, double* > sendValueToDest;
151  for (std::map<int,int>::const_iterator itRecv = recvRankSizeMap.begin(); itRecv != recvRankSizeMap.end(); ++itRecv)
152  {
153    int recvRank = itRecv->first;
154    int recvSize = itRecv->second;
155    recvGlobalIndexSrc[recvRank] = new unsigned long [recvSize];
156    sendValueToDest[recvRank] = new double [recvSize];
157
158    requests.push_back(MPI_Request());
159    MPI_Irecv(recvGlobalIndexSrc[recvRank], recvSize, MPI_UNSIGNED_LONG, recvRank, 46, client->intraComm, &requests.back());
160  }
161
162  boost::unordered_map<int, unsigned long* > sendGlobalIndexSrc;
163  boost::unordered_map<int, double* > recvValueFromSrc;
164  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex)
165  {
166    int sendRank = itIndex->first;
167    int sendSize = sendRankSizeMap[sendRank];
168    const std::vector<size_t>& sendIndexMap = itIndex->second;
169    std::vector<size_t>::const_iterator itbSend = sendIndexMap.begin(), iteSend = sendIndexMap.end(), itSend;
170    sendGlobalIndexSrc[sendRank] = new unsigned long [sendSize];
171    recvValueFromSrc[sendRank] = new double [sendSize];
172    int countIndex = 0;
173    for (itSend = itbSend; itSend != iteSend; ++itSend)
174    {
175      sendGlobalIndexSrc[sendRank][countIndex] = *itSend;
176      ++countIndex;
177    }
178
179    // Send global index source and mask
180    requests.push_back(MPI_Request());
181    MPI_Isend(sendGlobalIndexSrc[sendRank], sendSize, MPI_UNSIGNED_LONG, sendRank, 46, client->intraComm, &requests.back());
182  }
183
184  status.resize(requests.size());
185  MPI_Waitall(requests.size(), &requests[0], &status[0]);
186
187
188  std::vector<MPI_Request>().swap(requests);
189  std::vector<MPI_Status>().swap(status);
190
191  // Okie, on destination side, we will wait for information of masked index of source
192  for (std::map<int,int>::const_iterator itSend = sendRankSizeMap.begin(); itSend != sendRankSizeMap.end(); ++itSend)
193  {
194    int recvRank = itSend->first;
195    int recvSize = itSend->second;
196
197    requests.push_back(MPI_Request());
198    MPI_Irecv(recvValueFromSrc[recvRank], recvSize, MPI_DOUBLE, recvRank, 48, client->intraComm, &requests.back());
199  }
200
201  for (std::map<int,int>::const_iterator itRecv = recvRankSizeMap.begin(); itRecv != recvRankSizeMap.end(); ++itRecv)
202  {
203    int recvRank = itRecv->first;
204    int recvSize = itRecv->second;
205    double* sendValue = sendValueToDest[recvRank];
206    unsigned long* recvIndexSrc = recvGlobalIndexSrc[recvRank];
207    int realSendSize = 0;
208    for (int idx = 0; idx < recvSize; ++idx)
209    {
210      size_t globalIndex = *(recvIndexSrc+idx);
211      int localIndex = globalIndex - ibeginSrc;
212      *(sendValue + idx) = axisSrc_->value(localIndex);
213    }
214    // Okie, now inform the destination which source index are masked
215    requests.push_back(MPI_Request());
216    MPI_Isend(sendValueToDest[recvRank], recvSize, MPI_DOUBLE, recvRank, 48, client->intraComm, &requests.back());
217  }
218  status.resize(requests.size());
219  MPI_Waitall(requests.size(), &requests[0], &status[0]);
220
221
222  for (std::map<int,int>::const_iterator itSend = sendRankSizeMap.begin(); itSend != sendRankSizeMap.end(); ++itSend)
223  {
224    int recvRank = itSend->first;
225    int recvSize = itSend->second;
226
227    double* recvValue = recvValueFromSrc[recvRank];
228    unsigned long* recvIndex = sendGlobalIndexSrc[recvRank];
229    for (int idx = 0; idx < recvSize; ++idx)
230    {
231      size_t globalIndex = *(recvIndex+idx);
232      int localIndex = globalIndex - axisDest_->begin;
233      axisDest_->value(localIndex) = *(recvValue + idx);
234    }
235  }
236
237  delete [] recvCount;
238  delete [] displ;
239  delete [] sendRankBuff;
240  delete [] recvRankBuff;
241  delete [] sendSizeBuff;
242  delete [] recvSizeBuff;
243
244  boost::unordered_map<int, double* >::const_iterator itChar;
245  for (itChar = sendValueToDest.begin(); itChar != sendValueToDest.end(); ++itChar)
246    delete [] itChar->second;
247  for (itChar = recvValueFromSrc.begin(); itChar != recvValueFromSrc.end(); ++itChar)
248    delete [] itChar->second;
249  boost::unordered_map<int, unsigned long* >::const_iterator itLong;
250  for (itLong = sendGlobalIndexSrc.begin(); itLong != sendGlobalIndexSrc.end(); ++itLong)
251    delete [] itLong->second;
252  for (itLong = recvGlobalIndexSrc.begin(); itLong != recvGlobalIndexSrc.end(); ++itLong)
253    delete [] itLong->second;
254}
255
256}
Note: See TracBrowser for help on using the repository browser.