source: XIOS/dev/branch_openmp/extern/ep_dev/ep_intercomm_world.cpp @ 1381

Last change on this file since 1381 was 1381, checked in by yushan, 6 years ago

add folder for MPI EP-RMA development. Current: MPI_Win, MPI_win_create, MPI_win_fence, MPI_win_free

File size: 17.1 KB
Line 
1#include "ep_lib.hpp"
2#include <mpi.h>
3#include "ep_declaration.hpp"
4#include "ep_mpi.hpp"
5
6using namespace std;
7
8namespace ep_lib
9{
10
11  int MPI_Intercomm_create_from_world(MPI_Comm local_comm, int local_leader, void* peer_comm_ptr, int mpi_remote_leader, int tag, MPI_Comm *newintercomm)
12  {
13    int ep_rank, ep_rank_loc, mpi_rank;
14    int ep_size, num_ep, mpi_size;
15
16    ep_rank = local_comm.ep_comm_ptr->size_rank_info[0].first;
17    ep_rank_loc = local_comm.ep_comm_ptr->size_rank_info[1].first;
18    mpi_rank = local_comm.ep_comm_ptr->size_rank_info[2].first;
19    ep_size = local_comm.ep_comm_ptr->size_rank_info[0].second;
20    num_ep = local_comm.ep_comm_ptr->size_rank_info[1].second;
21    mpi_size = local_comm.ep_comm_ptr->size_rank_info[2].second;
22
23    std::vector<int> rank_info[4];  //! 0->rank_in_world of local_comm,  1->rank_in_local_parent of local_comm
24                                    //! 2->rank_in_world of remote_comm, 3->rank_in_local_parent of remote_comm
25
26    int rank_in_world;
27    int rank_in_local_parent;
28
29    int local_ep_size = ep_size;
30    int remote_ep_size;
31
32    ::MPI_Comm peer_comm = to_mpi_comm(peer_comm_ptr);
33    ::MPI_Comm local_mpi_comm = to_mpi_comm(local_comm.mpi_comm);
34
35    ::MPI_Comm_rank(peer_comm, &rank_in_world);
36
37    ::MPI_Comm_rank(local_mpi_comm, &rank_in_local_parent);
38
39    bool is_proc_master = false;
40    bool is_local_leader = false;
41    bool is_final_master = false;
42
43
44    if(ep_rank == local_leader) { is_proc_master = true; is_local_leader = true; is_final_master = true;}
45    if(ep_rank_loc == 0 && mpi_rank != local_comm.rank_map->at(local_leader).second) is_proc_master = true;
46
47
48    int size_info[4]; //! used for choose size of rank_info 0-> mpi_size of local_comm, 1-> mpi_size of remote_comm
49
50    int leader_info[4]; //! 0->world rank of local_leader, 1->world rank of remote leader
51
52
53    std::vector<int> ep_info[2]; //! 0-> num_ep in local_comm, 1->num_ep in remote_comm
54
55    std::vector<int> new_rank_info[4];
56    std::vector<int> new_ep_info[2];
57
58    std::vector<int> offset;
59
60    if(is_proc_master)
61    {
62
63      size_info[0] = mpi_size;
64
65      rank_info[0].resize(size_info[0]);
66      rank_info[1].resize(size_info[0]);
67
68      ep_info[0].resize(size_info[0]);
69
70      vector<int> send_buf(6);
71      vector<int> recv_buf(3*size_info[0]);
72
73      send_buf[0] = rank_in_world;
74      send_buf[1] = rank_in_local_parent;
75      send_buf[2] = num_ep;
76
77      ::MPI_Allgather(send_buf.data(), 3, to_mpi_type(MPI_INT), recv_buf.data(), 3, to_mpi_type(MPI_INT), local_mpi_comm);
78
79      for(int i=0; i<size_info[0]; i++)
80      {
81        rank_info[0][i] = recv_buf[3*i];
82        rank_info[1][i] = recv_buf[3*i+1];
83        ep_info[0][i]   = recv_buf[3*i+2];
84      }
85
86
87      if(is_local_leader)
88      {
89        leader_info[0] = rank_in_world;
90        leader_info[1] = mpi_remote_leader;
91
92        ::MPI_Status mpi_status;
93
94        send_buf[0] = size_info[0];
95        send_buf[1] = local_ep_size;
96
97        ::MPI_Send(send_buf.data(), 2, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm);
98
99        ::MPI_Recv(recv_buf.data(), 2, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm, &mpi_status);
100
101        recv_buf[2] = rank_in_world;
102        recv_buf[3] = mpi_remote_leader;
103
104      }
105
106      ::MPI_Bcast(recv_buf.data(), 4, to_mpi_type(MPI_INT), local_comm.rank_map->at(local_leader).second, local_mpi_comm);
107
108      size_info[1] = recv_buf[0];
109      remote_ep_size = recv_buf[1];
110      leader_info[0] = recv_buf[2];
111      leader_info[1] = recv_buf[3];
112
113      rank_info[2].resize(size_info[1]);
114      rank_info[3].resize(size_info[1]);
115
116      ep_info[1].resize(size_info[1]);
117
118      send_buf.resize(3*size_info[0]);
119      recv_buf.resize(3*size_info[1]);
120
121      if(is_local_leader)
122      {
123        ::MPI_Status mpi_status;
124
125
126        std::copy ( rank_info[0].data(), rank_info[0].data() + size_info[0], send_buf.begin() );
127        std::copy ( rank_info[1].data(), rank_info[1].data() + size_info[0], send_buf.begin() + size_info[0] );
128        std::copy ( ep_info[0].data(),   ep_info[0].data()   + size_info[0], send_buf.begin() + 2*size_info[0] );
129
130        ::MPI_Send(send_buf.data(), 3*size_info[0], to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm);
131
132        ::MPI_Recv(recv_buf.data(), 3*size_info[1], to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm, &mpi_status);
133
134      }
135
136      ::MPI_Bcast(recv_buf.data(), 3*size_info[1], to_mpi_type(MPI_INT), local_comm.rank_map->at(local_leader).second, local_mpi_comm);
137
138      std::copy ( recv_buf.data(), recv_buf.data() + size_info[1], rank_info[2].begin() );
139      std::copy ( recv_buf.data() + size_info[1], recv_buf.data() + 2*size_info[1], rank_info[3].begin()  );
140      std::copy ( recv_buf.data() + 2*size_info[1], recv_buf.data() + 3*size_info[1], ep_info[1].begin() );
141
142      offset.resize(size_info[0]);
143
144      if(leader_info[0]<leader_info[1]) // erase all ranks doubled with remote_comm, except the local leader
145      {
146
147        bool found = false;
148        int ep_tmp;
149        int ep_local;
150        int ep_remote;
151        for(int i=0; i<size_info[0]; i++)
152        {
153          int target = rank_info[0][i];
154          found = false;
155          for(int j=0; j<size_info[1]; j++)
156          {
157            if(target == rank_info[2][j])
158            {
159              found = true;
160              ep_tmp = ep_info[1][j];
161              ep_local = ep_info[0][j];
162              ep_remote = ep_info[1][j];
163              break;
164            }
165          }
166          if(found)
167          {
168
169            if(target == leader_info[0]) // the leader is doubled in remote
170            {
171              new_rank_info[0].push_back(target);
172              new_rank_info[1].push_back(rank_info[1][i]);
173
174              new_ep_info[0].push_back(ep_local + ep_remote);
175              offset[i] = 0;
176            }
177            else
178            {
179              offset[i] = ep_local;
180            }
181          }
182          else
183          {
184            new_rank_info[0].push_back(target);
185            new_rank_info[1].push_back(rank_info[1][i]);
186
187            new_ep_info[0].push_back(ep_info[0][i]);
188
189            offset[i] = 0;
190          }
191
192        }
193      }
194
195      else // erase rank doubled with remote leader
196      {
197
198        bool found = false;
199        int ep_tmp;
200        int ep_local;
201        int ep_remote;
202        for(int i=0; i<size_info[0]; i++)
203        {
204          int target = rank_info[0][i];
205          found = false;
206          for(int j=0; j<size_info[1]; j++)
207          {
208
209            if(target == rank_info[2][j])
210            {
211              found = true;
212              ep_tmp = ep_info[1][j];
213              ep_local = ep_info[0][j];
214              ep_remote = ep_info[1][j];
215              break;
216            }
217          }
218          if(found)
219          {
220            if(target != leader_info[1])
221            {
222              new_rank_info[0].push_back(target);
223              new_rank_info[1].push_back(rank_info[1][i]);
224
225              new_ep_info[0].push_back(ep_local + ep_remote);
226              offset[i] = 0;
227            }
228            else // found remote leader
229            {
230              offset[i] = ep_remote;
231            }
232          }
233          else
234          {
235            new_rank_info[0].push_back(target);
236            new_rank_info[1].push_back(rank_info[1][i]);
237
238            new_ep_info[0].push_back(ep_info[0][i]);
239            offset[i] = 0;
240          }
241        }
242      }
243
244      if(offset[mpi_rank] == 0)
245      {
246        is_final_master = true;
247      }
248
249
250      // size_info[4]: 2->size of new_ep_info for local, 3->size of new_ep_info for remote
251
252      if(is_local_leader)
253      {
254        size_info[2] = new_ep_info[0].size();
255        ::MPI_Status mpi_status;
256
257        ::MPI_Send(&size_info[2], 1, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm);
258
259        ::MPI_Recv(&size_info[3], 1, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm, &mpi_status);
260      }
261
262      ::MPI_Bcast(&size_info[2], 2, to_mpi_type(MPI_INT), local_comm.rank_map->at(local_leader).second, local_mpi_comm);
263
264      new_rank_info[2].resize(size_info[3]);
265      new_rank_info[3].resize(size_info[3]);
266      new_ep_info[1].resize(size_info[3]);
267
268      send_buf.resize(size_info[2]);
269      recv_buf.resize(size_info[3]);
270
271      if(is_local_leader)
272      {
273        ::MPI_Status mpi_status;
274
275        std::copy ( new_rank_info[0].data(), new_rank_info[0].data() + size_info[2], send_buf.begin() );
276        std::copy ( new_rank_info[1].data(), new_rank_info[1].data() + size_info[2], send_buf.begin() + size_info[2] );
277        std::copy ( new_ep_info[0].data(),   new_ep_info[0].data()   + size_info[0], send_buf.begin() + 2*size_info[2] );
278
279        ::MPI_Send(send_buf.data(), 3*size_info[2], to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm);
280
281        ::MPI_Recv(recv_buf.data(), 3*size_info[3], to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm, &mpi_status);
282      }
283
284      ::MPI_Bcast(recv_buf.data(),   3*size_info[3], to_mpi_type(MPI_INT), local_comm.rank_map->at(local_leader).second, local_mpi_comm);
285
286      std::copy ( recv_buf.data(), recv_buf.data() + size_info[3], new_rank_info[2].begin() );
287      std::copy ( recv_buf.data() + size_info[3], recv_buf.data() + 2*size_info[3], new_rank_info[3].begin()  );
288      std::copy ( recv_buf.data() + 2*size_info[3], recv_buf.data() + 3*size_info[3], new_ep_info[1].begin() );
289
290    }
291
292
293
294    if(is_proc_master)
295    {
296      // leader_info[4]: 2-> rank of local leader in new_group generated comm;
297                      // 3-> rank of remote leader in new_group generated comm;
298      ::MPI_Group local_group;
299      ::MPI_Group new_group;
300      ::MPI_Comm *new_comm = new ::MPI_Comm;
301      ::MPI_Comm *intercomm = new ::MPI_Comm;
302
303      ::MPI_Comm_group(local_mpi_comm, &local_group);
304
305      ::MPI_Group_incl(local_group, size_info[2], new_rank_info[1].data(), &new_group);
306
307      ::MPI_Comm_create(local_mpi_comm, new_group, new_comm);
308
309
310
311      if(is_local_leader)
312      {
313        ::MPI_Comm_rank(*new_comm, &leader_info[2]);
314      }
315
316      ::MPI_Bcast(&leader_info[2], 1, to_mpi_type(MPI_INT), local_comm.rank_map->at(local_leader).second, local_mpi_comm);
317
318      if(new_comm != static_cast< ::MPI_Comm* >(MPI_COMM_NULL.mpi_comm))
319      {
320        ::MPI_Barrier(*new_comm);
321
322        ::MPI_Intercomm_create(*new_comm, leader_info[2], peer_comm, leader_info[1], tag, intercomm);
323
324        int id;
325        ::MPI_Comm_rank(*new_comm, &id);
326        int my_num_ep = new_ep_info[0][id];
327
328        MPI_Comm *ep_intercomm;
329        MPI_Info info;
330        MPI_Comm_create_endpoints(new_comm, my_num_ep, info, ep_intercomm);
331
332        for(int i= 0; i<my_num_ep; i++)
333        {
334          ep_intercomm[i].is_intercomm = true;
335
336          ep_intercomm[i].ep_comm_ptr->intercomm = new ep_lib::ep_intercomm;
337          ep_intercomm[i].ep_comm_ptr->intercomm->mpi_inter_comm = intercomm;
338          ep_intercomm[i].ep_comm_ptr->comm_label = leader_info[0];
339        }
340
341
342        #pragma omp critical (write_to_tag_list)
343        tag_list.push_back(make_pair( make_pair(tag, min(leader_info[0], leader_info[1])) , ep_intercomm));
344       
345
346      }
347
348
349    }
350
351
352    vector<int> bcast_buf(8);
353    if(is_local_leader)
354    {
355      std::copy(size_info, size_info+4, bcast_buf.begin());
356      std::copy(leader_info, leader_info+4, bcast_buf.begin()+4);
357    }
358
359
360
361    MPI_Bcast(bcast_buf.data(), 8, MPI_INT, local_leader, local_comm);
362
363
364    if(!is_local_leader)
365    {
366      std::copy(bcast_buf.begin(), bcast_buf.begin()+4, size_info);
367      std::copy(bcast_buf.begin()+4, bcast_buf.begin()+8, leader_info);
368    }
369
370
371
372    if(!is_local_leader)
373    {
374      new_rank_info[1].resize(size_info[2]);
375      ep_info[1].resize(size_info[1]);
376      offset.resize(size_info[0]);
377    }
378
379    bcast_buf.resize(size_info[2]+size_info[1]+size_info[0]+1);
380
381    if(is_local_leader)
382    {
383      bcast_buf[0] = remote_ep_size;
384      std::copy(new_rank_info[1].data(), new_rank_info[1].data()+size_info[2], bcast_buf.begin()+1);
385      std::copy(ep_info[1].data(), ep_info[1].data()+size_info[1], bcast_buf.begin()+size_info[2]+1);
386      std::copy(offset.data(), offset.data()+size_info[0], bcast_buf.begin()+size_info[2]+size_info[1]+1);
387    }
388
389    MPI_Bcast(bcast_buf.data(), size_info[2]+size_info[1]+size_info[0]+1, MPI_INT, local_leader, local_comm);
390
391
392    if(!is_local_leader)
393    {
394      remote_ep_size = bcast_buf[0];
395      std::copy(bcast_buf.data()+1, bcast_buf.data()+1+size_info[2], new_rank_info[1].begin());
396      std::copy(bcast_buf.data()+1+size_info[2], bcast_buf.data()+1+size_info[2]+size_info[1], ep_info[1].begin());
397      std::copy(bcast_buf.data()+1+size_info[2]+size_info[1], bcast_buf.data()+1+size_info[2]+size_info[1]+size_info[0], offset.begin());
398    }
399
400
401    int my_position = offset[rank_in_local_parent]+ep_rank_loc;
402
403
404    #pragma omp critical (read_from_tag_list)
405    {
406      bool found = false;
407      while(!found)
408      {
409        for(std::list<std::pair < std::pair<int,int>, MPI_Comm* > >::iterator iter = tag_list.begin(); iter!=tag_list.end(); iter++)
410        {
411          if((*iter).first == make_pair(tag, min(leader_info[0], leader_info[1])))
412          {
413            *newintercomm =  iter->second[my_position];
414
415            found = true;
416            break;
417          }
418        }
419      }
420    }
421
422    MPI_Barrier(local_comm);
423
424    if(is_local_leader)
425    {
426      int local_flag = true;
427      int remote_flag = false;
428      ::MPI_Status mpi_status;
429     
430      ::MPI_Send(&local_flag, 1, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm);
431
432      ::MPI_Recv(&remote_flag, 1, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm, &mpi_status);
433    }
434
435    MPI_Barrier(local_comm);
436
437    if(is_proc_master)
438    {
439      for(std::list<std::pair < std::pair<int,int>, MPI_Comm* > >::iterator iter = tag_list.begin(); iter!=tag_list.end(); iter++)
440      {
441        if((*iter).first == make_pair(tag, min(leader_info[0], leader_info[1])))
442        {
443          tag_list.erase(iter);
444          break;
445        }
446      }
447    }
448
449    int intercomm_ep_rank, intercomm_ep_rank_loc, intercomm_mpi_rank;
450    int intercomm_ep_size, intercomm_num_ep, intercomm_mpi_size;
451
452    intercomm_ep_rank = newintercomm->ep_comm_ptr->size_rank_info[0].first;
453    intercomm_ep_rank_loc = newintercomm->ep_comm_ptr->size_rank_info[1].first;
454    intercomm_mpi_rank = newintercomm->ep_comm_ptr->size_rank_info[2].first;
455    intercomm_ep_size = newintercomm->ep_comm_ptr->size_rank_info[0].second;
456    intercomm_num_ep = newintercomm->ep_comm_ptr->size_rank_info[1].second;
457    intercomm_mpi_size = newintercomm->ep_comm_ptr->size_rank_info[2].second;
458
459
460    MPI_Bcast(&remote_ep_size, 1, MPI_INT, local_leader, local_comm);
461
462    int my_rank_map_elem[2];
463
464
465    my_rank_map_elem[0] = intercomm_ep_rank;
466
467    my_rank_map_elem[1] = (*newintercomm).ep_comm_ptr->comm_label;
468
469    vector<pair<int, int> > local_rank_map_array;
470    vector<pair<int, int> > remote_rank_map_array;
471
472
473    (*newintercomm).ep_comm_ptr->intercomm->local_rank_map = new RANK_MAP;
474    (*newintercomm).ep_comm_ptr->intercomm->local_rank_map->resize(local_ep_size);
475
476    MPI_Allgather(my_rank_map_elem, 2, MPI_INT, (*newintercomm).ep_comm_ptr->intercomm->local_rank_map->data(), 2, MPI_INT, local_comm);
477   
478    (*newintercomm).ep_comm_ptr->intercomm->remote_rank_map = new RANK_MAP;
479    (*newintercomm).ep_comm_ptr->intercomm->remote_rank_map->resize(remote_ep_size);
480
481    int local_intercomm_size = intercomm_ep_size;
482    int remote_intercomm_size;
483
484
485    if(is_local_leader)
486    {
487      ::MPI_Status status;
488
489      ::MPI_Send((*newintercomm).ep_comm_ptr->intercomm->local_rank_map->data(), 2*local_ep_size, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm);
490
491      ::MPI_Recv((*newintercomm).ep_comm_ptr->intercomm->remote_rank_map->data(), 2*remote_ep_size, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm, &status);
492
493      ::MPI_Send(&local_intercomm_size, 1, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm);
494
495      ::MPI_Recv(&remote_intercomm_size, 1, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm, &status);
496    }
497
498    MPI_Bcast((*newintercomm).ep_comm_ptr->intercomm->remote_rank_map->data(), 2*remote_ep_size, MPI_INT, local_leader, local_comm);
499    MPI_Bcast(&remote_intercomm_size, 1, MPI_INT, 0, *newintercomm);
500
501
502    (*newintercomm).ep_comm_ptr->intercomm->intercomm_rank_map = new RANK_MAP;
503    (*newintercomm).ep_comm_ptr->intercomm->intercomm_rank_map->resize(remote_intercomm_size);
504
505    (*newintercomm).ep_comm_ptr->intercomm->size_rank_info[0] = local_comm.ep_comm_ptr->size_rank_info[0];
506    (*newintercomm).ep_comm_ptr->intercomm->size_rank_info[1] = local_comm.ep_comm_ptr->size_rank_info[1];
507    (*newintercomm).ep_comm_ptr->intercomm->size_rank_info[2] = local_comm.ep_comm_ptr->size_rank_info[2];
508
509
510    if(is_local_leader)
511    {
512      ::MPI_Status status;
513
514      ::MPI_Send((*newintercomm).rank_map->data(), 2*local_intercomm_size, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm);
515
516      ::MPI_Recv((*newintercomm).ep_comm_ptr->intercomm->intercomm_rank_map->data(), 2*remote_intercomm_size, to_mpi_type(MPI_INT), mpi_remote_leader, tag, peer_comm, &status);
517    }
518
519    MPI_Bcast((*newintercomm).ep_comm_ptr->intercomm->intercomm_rank_map->data(), 2*remote_intercomm_size, MPI_INT, 0, *newintercomm);
520
521    (*newintercomm).ep_comm_ptr->intercomm->local_comm = &(local_comm.ep_comm_ptr->comm_list[ep_rank_loc]);
522    (*newintercomm).ep_comm_ptr->intercomm->intercomm_tag = local_comm.ep_comm_ptr->comm_label;
523
524    return MPI_SUCCESS;
525
526  }
527
528}
529
Note: See TracBrowser for help on using the repository browser.