source: XIOS/dev/dev_trunk_omp/extern/src_ep_dev/ep_intercomm.cpp @ 1646

Last change on this file since 1646 was 1646, checked in by yushan, 5 years ago

branch merged with trunk @1645. arch file (ep&mpi) added for ADA

File size: 17.5 KB
Line 
1#ifdef _usingEP
2#include "ep_lib.hpp"
3#include <mpi.h>
4#include "ep_declaration.hpp"
5#include "ep_mpi.hpp"
6
7using namespace std;
8
9extern std::map<std::pair<int, int>, MPI_Group* > * tag_group_map;
10
11extern std::map<int, std::pair<ep_lib::MPI_Comm*, std::pair<int, int> > > * tag_comm_map;
12
13extern MPI_Group MPI_GROUP_WORLD;
14
15namespace ep_lib
16{
17
18  int MPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm *newintercomm)
19  {
20    if(!local_comm->is_ep) return MPI_Intercomm_create_mpi(local_comm, local_leader, peer_comm, remote_leader, tag, newintercomm);
21
22    int ep_rank = local_comm->ep_comm_ptr->size_rank_info[0].first;
23   
24   
25    // check if local leaders are in the same mpi proc
26    // by checking their mpi_rank in peer_comm
27   
28    int mpi_rank_of_leader[2];
29   
30    if(ep_rank == local_leader)
31    {
32      mpi_rank_of_leader[0] = peer_comm->ep_comm_ptr->size_rank_info[2].first;
33      mpi_rank_of_leader[1] = peer_comm->ep_rank_map->at(remote_leader).second;     
34    }
35   
36    MPI_Bcast(mpi_rank_of_leader, 2, MPI_INT, local_leader, local_comm);
37   
38    if(mpi_rank_of_leader[0] != mpi_rank_of_leader[1])
39    {
40      Debug("calling MPI_Intercomm_create_kernel\n");
41      return MPI_Intercomm_create_endpoint(local_comm, local_leader, peer_comm, remote_leader, tag, newintercomm);
42    }
43    else
44    {
45      printf("local leaders are in the same MPI proc. Routine not yet implemented\n");
46      MPI_Abort(local_comm, 0);
47    }
48  }
49 
50 
51 
52  int MPI_Intercomm_create_endpoint(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm *newintercomm)
53  {
54    int ep_rank, ep_rank_loc, mpi_rank;
55    int ep_size, num_ep, mpi_size;
56
57    ep_rank     = local_comm->ep_comm_ptr->size_rank_info[0].first;
58    ep_rank_loc = local_comm->ep_comm_ptr->size_rank_info[1].first;
59    mpi_rank    = local_comm->ep_comm_ptr->size_rank_info[2].first;
60    ep_size     = local_comm->ep_comm_ptr->size_rank_info[0].second;
61    num_ep      = local_comm->ep_comm_ptr->size_rank_info[1].second;
62    mpi_size    = local_comm->ep_comm_ptr->size_rank_info[2].second;
63
64    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
65    // step 1 : local leaders exchange ep_size, leader_rank_in_peer, leader_rank_in_peer_mpi, leader_rank_in_world. //
66    //          local leaders bcast results to all ep in local_comm                                                 //
67    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68
69    bool is_local_leader = ep_rank==local_leader? true: false;
70   
71   
72    int local_leader_rank_in_peer;
73    int local_leader_rank_in_peer_mpi;
74    int local_leader_rank_in_world;
75
76    int remote_ep_size;
77    int remote_leader_rank_in_peer;
78    int remote_leader_rank_in_peer_mpi;
79    int remote_leader_rank_in_world;
80
81    int send_quadruple[4];
82    int recv_quadruple[4];
83
84
85    if(is_local_leader)
86    {
87      MPI_Comm_rank(peer_comm, &local_leader_rank_in_peer);
88      ::MPI_Comm_rank(to_mpi_comm(peer_comm->mpi_comm), &local_leader_rank_in_peer_mpi);
89      ::MPI_Comm_rank(to_mpi_comm(MPI_COMM_WORLD->mpi_comm), &local_leader_rank_in_world);
90
91      send_quadruple[0] = ep_size;
92      send_quadruple[1] = local_leader_rank_in_peer;
93      send_quadruple[2] = local_leader_rank_in_peer_mpi;
94      send_quadruple[3] = local_leader_rank_in_world;
95
96      MPI_Request request;
97      MPI_Status status;
98
99
100      if(remote_leader > local_leader_rank_in_peer)
101      {
102        MPI_Isend(send_quadruple, 4, MPI_INT, remote_leader, tag, peer_comm, &request);
103        MPI_Wait(&request, &status);
104       
105        MPI_Irecv(recv_quadruple, 4, MPI_INT, remote_leader, tag, peer_comm, &request);
106        MPI_Wait(&request, &status);
107      }
108      else
109      {
110        MPI_Irecv(recv_quadruple, 4, MPI_INT, remote_leader, tag, peer_comm, &request);
111        MPI_Wait(&request, &status);
112         
113        MPI_Isend(send_quadruple, 4, MPI_INT, remote_leader, tag, peer_comm, &request);
114        MPI_Wait(&request, &status);
115      }
116
117      remote_ep_size                 = recv_quadruple[0];
118      remote_leader_rank_in_peer     = recv_quadruple[1];
119      remote_leader_rank_in_peer_mpi = recv_quadruple[2];
120      remote_leader_rank_in_world    = recv_quadruple[3];
121#ifdef _showinfo
122      printf("peer_rank = %d, packed exchange OK\n", local_leader_rank_in_peer);
123#endif
124    }
125
126    MPI_Bcast(send_quadruple, 4, MPI_INT, local_leader, local_comm);
127    MPI_Bcast(recv_quadruple, 4, MPI_INT, local_leader, local_comm);
128
129    if(!is_local_leader)
130    {
131      local_leader_rank_in_peer     = send_quadruple[1];
132      local_leader_rank_in_peer_mpi = send_quadruple[2];
133      local_leader_rank_in_world    = send_quadruple[3];
134
135      remote_ep_size                 = recv_quadruple[0];
136      remote_leader_rank_in_peer     = recv_quadruple[1];
137      remote_leader_rank_in_peer_mpi = recv_quadruple[2];
138      remote_leader_rank_in_world    = recv_quadruple[3];
139    }
140
141
142#ifdef _showinfo
143    MPI_Barrier(peer_comm);
144    MPI_Barrier(peer_comm);
145    printf("peer_rank = %d, ep_size = %d, remote_ep_size = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, ep_size, remote_ep_size);
146    MPI_Barrier(peer_comm);
147    MPI_Barrier(peer_comm); 
148#endif
149
150    ///////////////////////////////////////////////////////////////////
151    // step 2 : gather ranks in world for both local and remote comm //
152    ///////////////////////////////////////////////////////////////////
153
154    int rank_in_world;
155    ::MPI_Comm_rank(to_mpi_comm(MPI_COMM_WORLD->mpi_comm), &rank_in_world);
156
157    int *ranks_in_world_local  = new int[ep_size];
158    int *ranks_in_world_remote = new int[remote_ep_size];
159
160    MPI_Allgather(&rank_in_world, 1, MPI_INT, ranks_in_world_local, 1, MPI_INT, local_comm);
161
162    if(is_local_leader)
163    {
164      MPI_Request request;
165      MPI_Status status;
166
167      if(remote_leader > local_leader_rank_in_peer)
168      {
169        MPI_Isend(ranks_in_world_local,  ep_size, MPI_INT, remote_leader, tag, peer_comm, &request);
170        MPI_Wait(&request, &status);
171       
172        MPI_Irecv(ranks_in_world_remote, remote_ep_size, MPI_INT, remote_leader, tag, peer_comm, &request);
173        MPI_Wait(&request, &status);
174      }
175      else
176      {
177        MPI_Irecv(ranks_in_world_remote, remote_ep_size, MPI_INT, remote_leader, tag, peer_comm, &request);
178        MPI_Wait(&request, &status);
179         
180        MPI_Isend(ranks_in_world_local,  ep_size, MPI_INT, remote_leader, tag, peer_comm, &request);
181        MPI_Wait(&request, &status);
182      }
183#ifdef _showinfo
184      printf("peer_rank = %d, ranks_in_world exchange OK\n", local_leader_rank_in_peer);
185#endif
186    }
187
188    MPI_Bcast(ranks_in_world_remote, remote_ep_size, MPI_INT, local_leader, local_comm);
189
190#ifdef _showinfo
191
192    MPI_Barrier(peer_comm);
193    MPI_Barrier(peer_comm);
194
195    if(remote_leader == 4)
196    {
197      for(int i=0; i<ep_size; i++)
198      {
199        if(ep_rank == i)
200        {
201          printf("peer_rank = %d, ranks_in_world_local = \n", peer_comm->ep_comm_ptr->size_rank_info[0].first);
202          for(int i=0; i<ep_size; i++)
203          {
204            printf("%d\t", ranks_in_world_local[i]);
205          }
206   
207          printf("\npeer_rank = %d, ranks_in_world_remote = \n", peer_comm->ep_comm_ptr->size_rank_info[0].first);
208          for(int i=0; i<remote_ep_size; i++)
209          {
210            printf("%d\t", ranks_in_world_remote[i]);
211          }
212          printf("\n");
213         
214        }
215       
216        MPI_Barrier(local_comm);
217        MPI_Barrier(local_comm);
218        MPI_Barrier(local_comm);
219      }
220    }
221
222    MPI_Barrier(peer_comm);
223    MPI_Barrier(peer_comm);
224    MPI_Barrier(peer_comm);
225   
226    if(remote_leader == 13)
227    {
228      for(int i=0; i<ep_size; i++)
229      {
230        if(ep_rank == i)
231        {
232          printf("peer_rank = %d, ranks_in_world_local = \n", peer_comm->ep_comm_ptr->size_rank_info[0].first);
233          for(int i=0; i<ep_size; i++)
234          {
235            printf("%d\t", ranks_in_world_local[i]);
236          }
237   
238          printf("\npeer_rank = %d, ranks_in_world_remote = \n", peer_comm->ep_comm_ptr->size_rank_info[0].first);
239          for(int i=0; i<remote_ep_size; i++)
240          {
241            printf("%d\t", ranks_in_world_remote[i]);
242          }
243          printf("\n");
244         
245        }
246       
247        MPI_Barrier(local_comm);
248        MPI_Barrier(local_comm);
249        MPI_Barrier(local_comm);
250      }
251    }
252
253    MPI_Barrier(peer_comm);
254    MPI_Barrier(peer_comm);
255
256#endif
257
258    //////////////////////////////////////////////////////////////
259    // step 3 : determine the priority and ownership of each ep //
260    //////////////////////////////////////////////////////////////
261
262    bool priority = local_leader_rank_in_peer < remote_leader_rank_in_peer? true : false;
263
264
265    int ownership = 1;
266
267    if(rank_in_world == ranks_in_world_local[local_leader]) ownership = 1;
268    if(rank_in_world == remote_leader_rank_in_world)   ownership = 0;
269   
270
271#ifdef _showinfo
272    MPI_Barrier(peer_comm);
273    MPI_Barrier(peer_comm);
274    printf("peer_rank = %d, priority = %d, local_leader_rank_in_peer = %d, remote_leader_rank_in_peer = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, priority, local_leader_rank_in_peer, remote_leader_rank_in_peer);
275    MPI_Barrier(peer_comm);
276    MPI_Barrier(peer_comm);
277#endif
278
279   
280#ifdef _showinfo
281    MPI_Barrier(peer_comm);
282    MPI_Barrier(peer_comm);
283    printf("peer_rank = %d, priority = %d, ownership = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, priority, ownership);
284    MPI_Barrier(peer_comm);
285    MPI_Barrier(peer_comm);
286#endif
287
288    //////////////////////////////////////////////////////
289    // step 4 : extract local_comm and create intercomm //
290    //////////////////////////////////////////////////////
291
292    bool is_involved = is_local_leader || (!is_local_leader && ep_rank_loc == 0 && rank_in_world != local_leader_rank_in_world);
293
294#ifdef _showinfo
295
296    MPI_Barrier(peer_comm);
297    MPI_Barrier(peer_comm);
298    printf("peer_rank = %d, is_involved = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, is_involved);
299    MPI_Barrier(peer_comm);
300    MPI_Barrier(peer_comm);
301
302#endif
303
304    if(is_involved)
305    {
306      ::MPI_Group local_group;
307      ::MPI_Group extracted_group;
308      ::MPI_Comm extracted_comm;
309
310
311      ::MPI_Comm_group(to_mpi_comm(local_comm->mpi_comm), &local_group);
312
313      int *ownership_list = new int[mpi_size];
314      int *mpi_rank_list = new int[mpi_size];
315
316      ::MPI_Allgather(&ownership, 1, to_mpi_type(MPI_INT), ownership_list, 1, to_mpi_type(MPI_INT), to_mpi_comm(local_comm->mpi_comm));
317      ::MPI_Allgather(&mpi_rank,  1, to_mpi_type(MPI_INT), mpi_rank_list,  1, to_mpi_type(MPI_INT), to_mpi_comm(local_comm->mpi_comm));
318
319     
320      int n=0;
321      for(int i=0; i<mpi_size; i++)
322      { 
323        n+=ownership_list[i];
324      }
325
326      int *new_mpi_rank_list = new int[n];
327      int j=0;
328      for(int i=0; i<mpi_size; i++)
329      { 
330        if(ownership_list[i] !=0)
331        {
332          new_mpi_rank_list[j++] = mpi_rank_list[i];
333        }
334      }
335
336
337      ::MPI_Group_incl(local_group, n, new_mpi_rank_list, &extracted_group);
338
339      ::MPI_Comm_create(to_mpi_comm(local_comm->mpi_comm), extracted_group, &extracted_comm);
340
341      ::MPI_Comm mpi_inter_comm;
342
343      int local_leader_rank_in_extracted_comm;
344
345      if(is_local_leader)
346      {
347        ::MPI_Comm_rank(extracted_comm, &local_leader_rank_in_extracted_comm);
348      }
349
350      ::MPI_Bcast(&local_leader_rank_in_extracted_comm, 1, to_mpi_type(MPI_INT), local_comm->ep_rank_map->at(local_leader).second, to_mpi_comm(local_comm->mpi_comm));
351
352      ::MPI_Comm *intracomm = new ::MPI_Comm;
353      bool is_real_involved = ownership && extracted_comm != to_mpi_comm(MPI_COMM_NULL->mpi_comm);
354
355      if(is_real_involved)
356      {
357        #pragma omp critical (_mpi_call)
358        ::MPI_Intercomm_create(extracted_comm, local_leader_rank_in_extracted_comm, to_mpi_comm(peer_comm->mpi_comm), remote_leader_rank_in_peer_mpi, tag, &mpi_inter_comm);
359        ::MPI_Intercomm_merge(mpi_inter_comm, !priority, intracomm);
360      }
361       
362       
363
364      ////////////////////////////////////
365      // step 5 :: determine new num_ep //
366      ////////////////////////////////////
367
368      int num_ep_count=0;
369
370      for(int i=0; i<ep_size; i++)
371      {
372        if(rank_in_world == ranks_in_world_local[i])
373          num_ep_count++;
374      }
375     
376      for(int i=0; i<remote_ep_size; i++)
377      {
378        if(rank_in_world == ranks_in_world_remote[i])
379          num_ep_count++;
380      }
381
382
383      ///////////////////////////////////////////////////
384      // step 6 : create endpoints from extracted_comm //
385      ///////////////////////////////////////////////////
386
387      if(is_real_involved)
388      {
389        MPI_Comm *ep_comm;
390        MPI_Info info;
391        MPI_Comm_create_endpoints(intracomm, num_ep_count, info, ep_comm);
392     
393#ifdef _showinfo
394        printf("new ep_comm->ep_comm_ptr->intercomm->mpi_inter_comm = %p\n", mpi_inter_comm);
395#endif
396
397        #pragma omp critical (write_to_tag_list)     
398        intercomm_list.push_back(make_pair( make_pair(tag, min(local_leader_rank_in_world, remote_leader_rank_in_world)) , make_pair(ep_comm , make_pair(num_ep_count, 0))));
399        #pragma omp flush
400#ifdef _showinfo
401        for(int i=0; i<num_ep_count; i++)
402          printf("peer_rank = %d, ep_comm = %p, ep_comm[%d] -> new_ep_rank = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, ep_comm, i, ep_comm[i]->ep_comm_ptr->size_rank_info[0].first);
403#endif 
404        ::MPI_Comm_free(intracomm);
405        delete intracomm;
406      }
407
408
409      delete ownership_list;
410      delete mpi_rank_list;
411      delete new_mpi_rank_list;
412
413    }
414
415    int repeated=0;
416    for(int i=0; i<remote_ep_size; i++)
417    {
418      if(rank_in_world == ranks_in_world_remote[i])
419        repeated++;
420    }
421
422    int new_ep_rank_loc = ownership==1? ep_rank_loc : ep_rank_loc+repeated;
423
424#ifdef _showinfo
425
426    MPI_Barrier(peer_comm);
427    MPI_Barrier(peer_comm);
428    printf("peer_rank = %d, ep_rank_loc = %d, ownership = %d, repeated = %d, new_ep_rank_loc = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, ep_rank_loc, ownership, repeated, new_ep_rank_loc);
429    MPI_Barrier(peer_comm);
430    MPI_Barrier(peer_comm);
431
432#endif
433
434    MPI_Barrier_local(local_comm);
435
436
437    #pragma omp flush
438    #pragma omp critical (read_from_intercomm_list)
439    {
440      bool flag=true;
441      while(flag)
442      {
443        for(std::list<std::pair<std::pair<int, int> , std::pair<MPI_Comm * , std::pair<int, int> > > >::iterator iter = intercomm_list.begin(); iter!=intercomm_list.end(); iter++)
444        {
445          if(iter->first == make_pair(tag, min(local_leader_rank_in_world, remote_leader_rank_in_world)))
446          {
447            *newintercomm = iter->second.first[new_ep_rank_loc];
448           
449            iter->second.second.second++;
450           
451            if(iter->second.second.first == iter->second.second.second)
452              intercomm_list.erase(iter);
453
454            flag = false;
455            break; 
456          }
457        }
458      }
459    }
460   
461
462
463#ifdef _showinfo
464
465    MPI_Barrier(peer_comm);
466    MPI_Barrier(peer_comm);
467    printf("peer_rank = %d, test_rank = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, (*newintercomm)->ep_comm_ptr->size_rank_info[0].first);
468    MPI_Barrier(peer_comm);
469    MPI_Barrier(peer_comm);
470
471#endif
472
473    //////////////////////////////////////////////////////////
474    // step 7 : create intercomm_rank_map for local leaders //
475    //////////////////////////////////////////////////////////
476
477    (*newintercomm)->is_intercomm = true;
478   
479    (*newintercomm)->inter_rank_map = new INTER_RANK_MAP;
480   
481   
482    int rank_info[2];
483    rank_info[0] = ep_rank;
484    rank_info[1] = (*newintercomm)->ep_comm_ptr->size_rank_info[0].first;
485
486#ifdef _showinfo
487    printf("priority = %d, ep_rank = %d, new_ep_rank = %d\n", priority, rank_info[0], rank_info[1]);
488#endif
489
490    int *local_rank_info = new int[2*ep_size];
491    int *remote_rank_info = new int[2*remote_ep_size];
492
493    MPI_Allgather(rank_info, 2, MPI_INT, local_rank_info, 2, MPI_INT, local_comm);
494
495    if(is_local_leader)
496    {
497      MPI_Request request;
498      MPI_Status status;
499
500      if(priority)
501      {
502        MPI_Isend(local_rank_info, 2*ep_size, MPI_INT, remote_leader, tag, peer_comm, &request);
503        MPI_Wait(&request, &status);
504       
505        MPI_Irecv(remote_rank_info, 2*remote_ep_size, MPI_INT, remote_leader, tag, peer_comm, &request);
506        MPI_Wait(&request, &status);
507      }
508      else
509      {
510        MPI_Irecv(remote_rank_info, 2*remote_ep_size, MPI_INT, remote_leader, tag, peer_comm, &request);
511        MPI_Wait(&request, &status);
512         
513        MPI_Isend(local_rank_info, 2*ep_size, MPI_INT, remote_leader, tag, peer_comm, &request);
514        MPI_Wait(&request, &status);
515      }
516    }
517
518    MPI_Bcast(remote_rank_info, 2*remote_ep_size, MPI_INT, local_leader, local_comm);
519
520    for(int i=0; i<remote_ep_size; i++)
521    {
522      (*newintercomm)->inter_rank_map->insert(make_pair(remote_rank_info[2*i], remote_rank_info[2*i+1]));
523    }
524   
525    (*newintercomm)->ep_comm_ptr->size_rank_info[0] = local_comm->ep_comm_ptr->size_rank_info[0];
526
527   
528    delete[] local_rank_info;
529    delete[] remote_rank_info;
530    delete[] ranks_in_world_local;
531    delete[] ranks_in_world_remote;
532    /*
533    if((*newintercomm)->ep_comm_ptr->size_rank_info[0].second == 1)
534    {
535      for(INTER_RANK_MAP::iterator it = (*newintercomm)->inter_rank_map->begin(); it != (*newintercomm)->inter_rank_map->end(); it++)
536      {
537        printf("inter_rank_map[%d] = %d\n", it->first, it->second);
538      }
539    }
540    */
541   
542 
543  }
544   
545 
546 
547  int MPI_Intercomm_create_mpi(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm *newintercomm)
548  {
549    printf("MPI_Intercomm_create_mpi not yet implemented\n");
550    MPI_Abort(local_comm, 0);
551  }
552
553}
554#endif
Note: See TracBrowser for help on using the repository browser.