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

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

rank_map is passed from vector to map, in order to have more flexibility in comm_split

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