source: XMLIO_V2/dev/dev_rv/src4/xmlio/mpi/mpi_interface.cpp @ 269

Last change on this file since 269 was 269, checked in by hozdoba, 13 years ago
File size: 10.5 KB
Line 
1/* ************************************************************************** *
2 *      Copyright © IPSL/LSCE, XMLIOServer, Avril 2010 - Octobre 2011         *
3 * ************************************************************************** */
4 
5 /**
6 * \file    mpi_interface.cpp
7 * \brief   Gestion des communications MPI via une surcouche interne (implémentation).
8 * \author  Hervé Ozdoba
9 * \version 0.4
10 * \date    28 Juin 2011
11 */
12 
13// XMLIOServer headers
14#include "mpi_interface.hpp"
15
16// /////////////////////////////// Définitions ////////////////////////////// //
17
18namespace xmlioserver {
19namespace comm {
20
21   // ---------------------- Initialisation & Finalisation ---------------------
22
23   void CMPIManager::Initialise(int * _argc, char *** _argv)
24   {
25      int flag = 0;
26      if (MPI_Initialized(&flag) != MPI_SUCCESS)
27         XIOS_ERROR("CMPIManager::Initialise(arc, argv)", << " MPI Error !");
28      if (!flag)
29      {
30         if (MPI_Init(_argc, _argv) != MPI_SUCCESS)
31            XIOS_ERROR("CMPIManager::Initialise(arc, argv)", << " MPI Error !");
32      }
33
34   }
35   
36   void CMPIManager::Finalize(void)
37   {
38      if (MPI_Finalize() != MPI_SUCCESS)
39         XIOS_ERROR("CMPIManager::Finalize(void)", << " MPI Error !");
40   }
41   
42   // ------------------------------ Communicateurs ----------------------------
43   
44   int CMPIManager::GetCommRank(MPI_Comm _comm)
45   {
46      int rank = 0;
47      if (MPI_Comm_rank(_comm, &rank) != MPI_SUCCESS)
48         XIOS_ERROR("CMPIManager::GetCommRank(comm)", << " MPI Error !");
49      return (rank);
50   }
51   
52   int CMPIManager::GetCommSize(MPI_Comm _comm)
53   {
54      int size = 0;
55      if (MPI_Comm_size(_comm, &size) != MPI_SUCCESS)
56         XIOS_ERROR("CMPIManager::GetCommSize(comm)", << " MPI Error !");
57      return (size);
58   }
59   
60   MPI_Comm CMPIManager::CreateComm(MPI_Group _group, MPI_Comm _pcomm)
61   {
62      MPI_Comm commu;     
63      if (MPI_Comm_create(_pcomm, _group, &commu) != MPI_SUCCESS)
64         XIOS_ERROR("CMPIManager::CreateComm(group, pcomm)", << " MPI Error !");
65      return (commu);
66   }
67   
68   MPI_Comm CMPIManager::GetCommWorld(void)
69   {
70      return (MPI_COMM_WORLD); 
71   }
72   
73   // ---------------------------------- Autre ---------------------------------
74         
75   void CMPIManager::Barrier(MPI_Comm _comm)
76   {
77      if (MPI_Barrier(_comm) != MPI_SUCCESS)
78         XIOS_ERROR("CMPIManager::Barrier(comm)", << " MPI Error !");
79   }
80   
81   bool CMPIManager::DispatchClient(bool       _is_server,
82                                    MPI_Comm & _comm_client,
83                                    MPI_Comm & _comm_client_server,
84                                    MPI_Comm & _comm_server,
85                                    MPI_Comm   _comm_parent)
86   {
87      int value = (_is_server) ? 1 : 2;
88      std::size_t nbClient = 0, nbServer = 0, nbClientByServer = 0;
89      std::vector<int> info, rank_client, rank_server;
90      CMPIManager::AllGather(value, info, _comm_parent);
91
92      for (std::size_t s = 0;  s < info.size(); s++)
93      {
94         if (info[s] == 1) rank_server.push_back(s);
95         else rank_client.push_back(s);
96      }
97      nbClient = rank_client.size();
98      nbServer = rank_server.size();
99         
100
101      _comm_client = CMPIManager::CreateComm(CMPIManager::CreateSubGroup(
102                     CMPIManager::GetGroupWorld(), rank_client), _comm_parent);
103
104      if (nbServer != 0)
105      {
106         std::size_t currentServer = 0;
107         nbClientByServer = nbClient/nbServer;
108         _comm_server = CMPIManager::CreateComm(CMPIManager::CreateSubGroup(
109                        CMPIManager::GetGroupWorld(), rank_server), _comm_parent);
110
111         //std::cout << nbClient << "," << nbServer  << "," << nbClientByServer << std::endl;
112
113         for (std::size_t mm = 0; mm < nbClient; mm += nbClientByServer)
114         {
115            std::vector<int> group_rank;
116            group_rank.push_back(rank_server[currentServer++]);
117            for (std::size_t nn = 0; nn < nbClientByServer; nn++)
118               group_rank.push_back(rank_client[nn+mm]);
119            MPI_Comm comm_client_server_ = CMPIManager::CreateComm(CMPIManager::CreateSubGroup(
120                                           CMPIManager::GetGroupWorld(), group_rank), _comm_parent);
121
122            if (std::find(group_rank.begin(), group_rank.end(),
123                         CMPIManager::GetCommRank(_comm_parent)) != group_rank.end())
124            {
125               _comm_client_server = comm_client_server_;
126            }
127               
128            group_rank.clear();
129         }
130         return (true);
131      }
132      else
133      {
134         _comm_server = _comm_client;
135         return (false);
136      }
137   }
138   
139
140   // --------------------------------- Groupes --------------------------------
141         
142   MPI_Group CMPIManager::GetGroupWorld(void)
143   {
144      MPI_Group group = 0;
145      if (MPI_Comm_group(CMPIManager::GetCommWorld(), &group) != MPI_SUCCESS)
146         XIOS_ERROR("CMPIManager::GetGroupWorld()", << " MPI Error !");
147      return (group);
148   }
149   
150   MPI_Group CMPIManager::CreateSubGroup(MPI_Group _pgroup, const std::vector<int> & _ranks)
151   {
152      MPI_Group group = 0;
153      if (MPI_Group_incl(_pgroup, _ranks.size(), const_cast<int*>(&(_ranks[0])), &group) != MPI_SUCCESS)
154         XIOS_ERROR("CMPIManager::CreateSubGroup(pgroup, ranks)", << " MPI Error !");
155      return (group);
156   }
157   
158   MPI_Group CMPIManager::CreateSubGroup
159      (MPI_Group _pgroup, int _min_rank, int _max_rank, int _intval)
160   {
161      std::vector<int> ranks;
162      for (int i = _min_rank; i <= _max_rank; i += _intval)
163         ranks.push_back(i);
164      return (CMPIManager::CreateSubGroup(_pgroup, ranks));
165   }
166
167   // ----------------------------------- Tests --------------------------------
168         
169   bool CMPIManager::IsMaster(MPI_Comm _comm)
170   {
171      return (CMPIManager::GetCommRank(_comm) == 0); 
172   }
173   
174   bool CMPIManager::IsRank(int _rank, MPI_Comm _comm)
175   {
176      return (CMPIManager::GetCommRank(_comm) == _rank); 
177   }
178
179   // --------------------------- Communication simple -------------------------
180         
181   void CMPIManager::Send (MPI_Comm _comm, int _dest_rank, char * _data,
182                           std::size_t _size, MPI_Request & _request)
183   {
184      int nsize = _size;   
185      if (MPI_Issend(_data, nsize, MPI_CHAR, _dest_rank, 0, _comm, &_request) != MPI_SUCCESS)
186         XIOS_ERROR("CMPIManager::Send (comm, dest_rank, data, size, request)", << " MPI Error !");
187   }
188   
189   void CMPIManager::Wait (MPI_Request & _request)
190   {
191      MPI_Status status;
192      if (MPI_Wait(&_request, &status) != MPI_SUCCESS)
193         XIOS_ERROR("CMPIManager::Wait (request)", << " MPI Error !");
194   }
195   
196   bool CMPIManager::Test (MPI_Request & _request)
197   {
198      MPI_Status status;
199      int flag = 0;
200      if (MPI_Test(&_request, &flag, &status) != MPI_SUCCESS)
201         XIOS_ERROR("CMPIManager::Test (request)", << " MPI Error !");
202      return (flag);
203   }
204
205   bool CMPIManager::HasReceivedData(MPI_Comm _comm, int _src_rank)
206   {
207      MPI_Status status;
208      int flag = 0;
209      if (MPI_Iprobe(_src_rank, MPI_ANY_TAG, _comm, &flag, &status) != MPI_SUCCESS)
210         XIOS_ERROR("CMPIManager::HasReceivedData (comm, rank)", << " MPI Error !");
211      return (flag);
212   }
213   
214   std::size_t CMPIManager::GetReceivedDataSize(MPI_Comm _comm, int _src_rank)
215   {
216      MPI_Status status;
217      int flag = 0, size = 0;
218      if (MPI_Iprobe(_src_rank, MPI_ANY_TAG, _comm, &flag, &status) != MPI_SUCCESS)
219         XIOS_ERROR("CMPIManager::getReceivedDataSize (comm, rank)", << " MPI Error !");
220      if (!flag) return (0); 
221      if (MPI_Get_count(&status, MPI_CHAR, &size) != MPI_SUCCESS)
222         XIOS_ERROR("CMPIManager::getReceivedDataSize (comm, rank)", << " MPI Error !");
223
224      return (size);
225   }
226   
227   void CMPIManager::Receive(MPI_Comm _comm, int _src_rank, char * _data)
228   {
229      MPI_Request request = 0;
230      int size = CMPIManager::GetReceivedDataSize(_comm, _src_rank);
231      if (MPI_Irecv(_data, size, MPI_CHAR, _src_rank, MPI_ANY_TAG, _comm, &request) != MPI_SUCCESS)
232         XIOS_ERROR("CMPIManager::Receive (comm, src_rank, data)", << " MPI Error !");
233      CMPIManager::Wait (request); // Temporaire
234   }
235   
236   void CMPIManager::AllGather(int _indata, std::vector<int> & _outdata, MPI_Comm _comm)
237   {
238      std::vector<int> data; data.push_back(_indata);
239      CMPIManager::AllGather(data, _outdata, _comm);
240   }
241
242   void  CMPIManager::AllGather(const std::vector<int> & _indata,
243                                      std::vector<int> & _outdata, MPI_Comm _comm)
244   {
245      int sendcount = _indata.size(),
246          recvcount = _indata.size() * CMPIManager::GetCommSize(_comm);
247      _outdata.resize(recvcount);     
248      if (MPI_Allgather ( const_cast<int*>(&(_indata[0])), sendcount, MPI_INTEGER,
249                                          &(_outdata[0]) , recvcount, MPI_INTEGER, _comm) != MPI_SUCCESS)
250         XIOS_ERROR("CMPIManager::AllGather (indata, outdata, comm)", << " MPI Error !");
251   }
252         
253   // ------------------------- Communication 'complexe' -----------------------
254         
255   /*void CMPIManager::SendLinearBuffer(MPI_Comm _comm, int _dest_rank, CLinearBuffer & _lbuffer, MPI_Request & _request)
256   {
257      CMPIManager::Send(_comm, _dest_rank, _lbuffer, _lbuffer.getUsedSize(), _request);
258      buff.clear();
259   }
260   
261   void CMPIManager::ReceiveLinearBuffer(MPI_Comm _comm, int _src_rank, CLinearBuffer & _lbuffer)
262   {
263      CMPIManager::Receive(_comm, _src_rank, _lbuffer);
264      _lbuffer.computeBufferData();
265   }
266   
267   boost::shared_ptr<CLinearBuffer> CMPIManager::ReceiveLinearBuffer(MPI_Comm _comm, int _src_rank)
268   {
269      boost::shared_ptr<CLinearBuffer> buff_ptr
270         (new CLinearBuffer(CMPIManager::GetReceivedDataSize(_comm, _src_rank)));
271      CMPIManager::ReceiveLinearBuffer(_comm, _src_rank, *buff_ptr);
272      return (buff_ptr);
273   }
274   
275   void CMPIManager::ReceiveCircularBuffer(MPI_Comm _comm, int _src_rank, CCircularBuffer & _cbuffer)
276   {
277      std::size_t data_size  = CMPIManager::GetReceivedDataSize(_comm, _src_rank);
278      std::size_t data_begin = buff.prepareNextDataPosition(data_size);
279      CMPIManager::Receive(comm, src_rank, buff.getData(data_begin));
280      _cbuffer.updateNbRequests(data_begin, data_begin + data_size);
281   }*/
282
283   // ---------------------- Mémoire (non fonctionnel ....) --------------------
284         
285   void CMPIManager::AllocMemory(void * _data, std::size_t _size)
286   {
287      if (MPI_Alloc_mem(sizeof(char) * _size, MPI_INFO_NULL, _data) != MPI_SUCCESS)
288         XIOS_ERROR("CMPIManager::AllocMem(data, size)", << " MPI Error !");
289   }
290   
291   void CMPIManager::FreeMemory (void * _data)
292   {
293      MPI_Free_mem(_data);
294   }
295
296} // namespace comm
297} // namespace xmlioserver
298
Note: See TracBrowser for help on using the repository browser.