source: XIOS/dev/branch_openmp/extern/ep_dev/ep_intercomm_kernel.cpp @ 1511

Last change on this file since 1511 was 1511, checked in by yushan, 3 years ago

save dev

File size: 44.9 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
8
9namespace ep_lib
10{
11  int MPI_Intercomm_create_kernel(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int 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
24    // step 1 : local leaders exchange ep_size then bcast to all ep in local_comm
25
26    int remote_ep_size;
27    bool is_local_leader = ep_rank==local_leader? true: false;
28
29    if(is_local_leader)
30    {
31      MPI_Request request[2];
32      MPI_Status status[2];
33      MPI_Isend(&ep_size, 1, MPI_INT, remote_leader, tag, peer_comm, &request[0]);
34      MPI_Irecv(&remote_ep_size, 1, MPI_INT, remote_leader, tag, peer_comm, &request[1]);
35      MPI_Waitall(2, request, status);
36    }
37
38    MPI_Bcast(&remote_ep_size, 1, MPI_INT, local_leader, local_comm);
39
40#ifdef _showinfo
41    MPI_Barrier(peer_comm);
42    MPI_Barrier(peer_comm);
43    #pragma omp critical(stdoutput)
44    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);
45    MPI_Barrier(peer_comm);
46    MPI_Barrier(peer_comm); 
47#endif
48
49    // step 2 : gather ranks in world for both local and remote comm
50
51    int rank_in_world;
52    ::MPI_Comm_rank(to_mpi_comm(MPI_COMM_WORLD->mpi_comm), &rank_in_world);
53
54    int *ranks_in_world_local  = new int[ep_size];
55    int *ranks_in_world_remote = new int[remote_ep_size];
56
57    MPI_Allgather(&rank_in_world, 1, MPI_INT, ranks_in_world_local, 1, MPI_INT, local_comm);
58
59    if(is_local_leader)
60    {
61      MPI_Request request[2];
62      MPI_Status status[2];
63      MPI_Isend(ranks_in_world_local,  ep_size,        MPI_INT, remote_leader, tag, peer_comm, &request[0]);
64      MPI_Irecv(ranks_in_world_remote, remote_ep_size, MPI_INT, remote_leader, tag, peer_comm, &request[1]);
65      MPI_Waitall(2, request, status);
66    }
67
68    MPI_Bcast(ranks_in_world_remote, remote_ep_size, MPI_INT, local_leader, local_comm);
69
70#ifdef _showinfo
71
72    MPI_Barrier(peer_comm);
73    MPI_Barrier(peer_comm);
74
75    if(remote_leader == 4)
76    {
77      for(int i=0; i<ep_size; i++)
78      {
79        if(ep_rank == i)
80        {
81          printf("peer_rank = %d, ranks_in_world_local = \n", peer_comm->ep_comm_ptr->size_rank_info[0].first);
82          for(int i=0; i<ep_size; i++)
83          {
84            printf("%d\t", ranks_in_world_local[i]);
85          }
86   
87          printf("\npeer_rank = %d, ranks_in_world_remote = \n", peer_comm->ep_comm_ptr->size_rank_info[0].first);
88          for(int i=0; i<remote_ep_size; i++)
89          {
90            printf("%d\t", ranks_in_world_remote[i]);
91          }
92          printf("\n");
93         
94        }
95       
96        MPI_Barrier(local_comm);
97        MPI_Barrier(local_comm);
98        MPI_Barrier(local_comm);
99      }
100    }
101
102    MPI_Barrier(peer_comm);
103    MPI_Barrier(peer_comm);
104    MPI_Barrier(peer_comm);
105   
106    if(remote_leader == 13)
107    {
108      for(int i=0; i<ep_size; i++)
109      {
110        if(ep_rank == i)
111        {
112          printf("peer_rank = %d, ranks_in_world_local = \n", peer_comm->ep_comm_ptr->size_rank_info[0].first);
113          for(int i=0; i<ep_size; i++)
114          {
115            printf("%d\t", ranks_in_world_local[i]);
116          }
117   
118          printf("\npeer_rank = %d, ranks_in_world_remote = \n", peer_comm->ep_comm_ptr->size_rank_info[0].first);
119          for(int i=0; i<remote_ep_size; i++)
120          {
121            printf("%d\t", ranks_in_world_remote[i]);
122          }
123          printf("\n");
124         
125        }
126       
127        MPI_Barrier(local_comm);
128        MPI_Barrier(local_comm);
129        MPI_Barrier(local_comm);
130      }
131    }
132
133    MPI_Barrier(peer_comm);
134    MPI_Barrier(peer_comm);
135
136#endif
137
138
139    // step 3 : determine the priority and ownership of each ep
140
141    int local_leader_rank_in_peer;
142    int remote_leader_rank_in_peer;
143
144    if(is_local_leader) MPI_Comm_rank(peer_comm, &local_leader_rank_in_peer);
145
146    if(is_local_leader)
147    {
148      MPI_Request request[2];
149      MPI_Status status[2];
150      MPI_Isend(&local_leader_rank_in_peer,  1, MPI_INT, remote_leader, tag, peer_comm, &request[0]);
151      MPI_Irecv(&remote_leader_rank_in_peer, 1, MPI_INT, remote_leader, tag, peer_comm, &request[1]);
152      MPI_Waitall(2, request, status);
153    }
154
155    MPI_Bcast(&local_leader_rank_in_peer,  1, MPI_INT, local_leader, local_comm);
156    MPI_Bcast(&remote_leader_rank_in_peer, 1, MPI_INT, local_leader, local_comm);
157
158    bool priority = local_leader_rank_in_peer > remote_leader_rank_in_peer? true : false;
159
160#ifdef _showinfo
161    MPI_Barrier(peer_comm);
162    MPI_Barrier(peer_comm);
163    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);
164    MPI_Barrier(peer_comm);
165    MPI_Barrier(peer_comm);
166#endif
167
168    int local_leader_rank_in_world = ranks_in_world_local[local_leader];
169    int remote_leader_rank_in_world;
170
171    if(is_local_leader)
172    {
173      MPI_Request request[2];
174      MPI_Status status[2];
175      MPI_Isend(&local_leader_rank_in_world,  1, MPI_INT, remote_leader, tag, peer_comm, &request[0]);
176      MPI_Irecv(&remote_leader_rank_in_world, 1, MPI_INT, remote_leader, tag, peer_comm, &request[1]);
177      MPI_Waitall(2, request, status);
178    }
179
180    MPI_Bcast(&remote_leader_rank_in_world, 1, MPI_INT, local_leader, local_comm);
181
182    int ownership;
183
184    if(rank_in_world == ranks_in_world_local[local_leader]) ownership = 1;
185    else if(rank_in_world == remote_leader_rank_in_world)   ownership = 0;
186    else
187    {
188      ownership = 1;
189      for(int i=0; i<remote_ep_size; i++)
190      {
191        if(rank_in_world == ranks_in_world_remote[i])
192        {
193          ownership = priority? 1 : 0;
194          break;
195        } 
196      }
197    }
198   
199#ifdef _showinfo
200    MPI_Barrier(peer_comm);
201    MPI_Barrier(peer_comm);
202    printf("peer_rank = %d, priority = %d, ownership = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, priority, ownership);
203    MPI_Barrier(peer_comm);
204    MPI_Barrier(peer_comm);
205#endif
206
207
208    // step 4 : extract local_comm and create intercomm
209
210    bool is_involved = is_local_leader || (!is_local_leader && ep_rank_loc == 0 && rank_in_world != local_leader_rank_in_world);
211
212#ifdef _showinfo
213
214    MPI_Barrier(peer_comm);
215    MPI_Barrier(peer_comm);
216    printf("peer_rank = %d, is_involved = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, is_involved);
217    MPI_Barrier(peer_comm);
218    MPI_Barrier(peer_comm);
219
220#endif
221
222    if(is_involved)
223    {
224      ::MPI_Group local_group;
225      ::MPI_Group extracted_group;
226      ::MPI_Comm *extracted_comm = new ::MPI_Comm;
227
228
229      ::MPI_Comm_group(to_mpi_comm(local_comm->mpi_comm), &local_group);
230
231      int *ownership_list = new int[mpi_size];
232      int *mpi_rank_list = new int[mpi_size];
233
234      ::MPI_Allgather(&ownership, 1, to_mpi_type(MPI_INT), ownership_list, 1, to_mpi_type(MPI_INT), to_mpi_comm(local_comm->mpi_comm));
235      ::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));
236
237     
238      int n=0;
239      for(int i=0; i<mpi_size; i++)
240      { 
241        n+=ownership_list[i];
242      }
243
244      int *new_mpi_rank_list = new int[n];
245      int j=0;
246      for(int i=0; i<mpi_size; i++)
247      { 
248        if(ownership_list[i] !=0)
249        {
250          new_mpi_rank_list[j++] = mpi_rank_list[i];
251        }
252      }
253
254
255      ::MPI_Group_incl(local_group, n, new_mpi_rank_list, &extracted_group);
256
257      ::MPI_Comm_create(to_mpi_comm(local_comm->mpi_comm), extracted_group, extracted_comm);
258
259      ::MPI_Comm *mpi_inter_comm = new ::MPI_Comm;
260
261      int local_leader_rank_in_extracted_comm;
262
263      if(is_local_leader)
264      {
265        ::MPI_Comm_rank(*extracted_comm, &local_leader_rank_in_extracted_comm);
266      }
267
268      ::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));
269
270      int local_leader_rank_in_peer_mpi;
271      int remote_leader_rank_in_peer_mpi;
272
273      ::MPI_Comm_rank(to_mpi_comm(peer_comm->mpi_comm), &local_leader_rank_in_peer_mpi);
274
275      if(is_local_leader)
276      {
277        MPI_Request request[2];
278        MPI_Status status[2];
279        MPI_Isend(&local_leader_rank_in_peer_mpi,  1, MPI_INT, remote_leader, tag, peer_comm, &request[0]);
280        MPI_Irecv(&remote_leader_rank_in_peer_mpi, 1, MPI_INT, remote_leader, tag, peer_comm, &request[1]);
281        MPI_Waitall(2, request, status);
282      }
283
284      ::MPI_Bcast(&remote_leader_rank_in_peer_mpi, 1, to_mpi_type(MPI_INT), local_comm->ep_rank_map->at(local_leader).second, to_mpi_comm(local_comm->mpi_comm));     
285
286
287      if(ownership)
288        ::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);
289
290
291      // step 5 :: determine new num_ep
292
293      int num_ep_count=0;
294
295      for(int i=0; i<ep_size; i++)
296      {
297        if(rank_in_world == ranks_in_world_local[i])
298          num_ep_count++;
299      }
300     
301      for(int i=0; i<remote_ep_size; i++)
302      {
303        if(rank_in_world == ranks_in_world_remote[i])
304          num_ep_count++;
305      }
306
307      //printf("peer_rank = %d, num_ep_count = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, num_ep_count);
308
309
310      // step 6 : create endpoints from extracted_comm
311
312      if(ownership)
313      {
314        MPI_Comm *ep_comm;
315        MPI_Info info;
316        MPI_Comm_create_endpoints(extracted_comm, num_ep_count, info, ep_comm);
317
318        for(int i=0; i<num_ep_count; i++)
319        {
320          ep_comm[i]->is_intercomm = true;
321          ep_comm[i]->ep_comm_ptr->comm_label = ranks_in_world_local[local_leader];
322          ep_comm[i]->ep_comm_ptr->intercomm = new ep_lib::ep_intercomm;
323          ep_comm[i]->ep_comm_ptr->intercomm->mpi_inter_comm = mpi_inter_comm;
324        }
325
326        //delete ep_comm[0]->ep_rank_map;
327
328
329        #pragma omp critical (write_to_tag_list)     
330        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))));
331        #pragma omp flush
332#ifdef _showinfo
333        for(int i=0; i<num_ep_count; i++)
334          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);
335#endif
336      }
337
338
339      delete ownership_list;
340      delete mpi_rank_list;
341      delete new_mpi_rank_list;
342
343    }
344
345    int repeated=0;
346    for(int i=0; i<remote_ep_size; i++)
347    {
348      if(rank_in_world == ranks_in_world_remote[i])
349        repeated++;
350    }
351
352    int my_turn = ownership? ep_rank_loc : ep_rank_loc+repeated;
353
354#ifdef _showinfo
355
356    MPI_Barrier(peer_comm);
357    MPI_Barrier(peer_comm);
358    printf("peer_rank = %d, ep_rank_loc = %d, ownership = %d, repeated = %d, my_turn = %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, ep_rank_loc, ownership, repeated, my_turn);
359    MPI_Barrier(peer_comm);
360    MPI_Barrier(peer_comm);
361
362#endif
363
364
365    #pragma omp flush
366    #pragma omp critical (read_from_intercomm_list)
367    {
368      bool flag=true;
369      while(flag)
370      {
371        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++)
372        {
373          if(iter->first == make_pair(tag, min(local_leader_rank_in_world, remote_leader_rank_in_world)))
374          {
375            *newintercomm = iter->second.first[my_turn];
376           
377            iter->second.second.second++;
378           
379            if(iter->second.second.first == iter->second.second.second)
380              intercomm_list.erase(iter);
381
382            flag = false;
383            break; 
384          }
385        }
386      }
387    }
388
389#ifdef _showinfo
390
391    MPI_Barrier(peer_comm);
392    MPI_Barrier(peer_comm);
393    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);
394    MPI_Barrier(peer_comm);
395    MPI_Barrier(peer_comm);
396
397#endif
398
399
400    // step 7 : create intercomm_rank_map for local leaders
401   
402    int my_quadruple[4];
403
404    my_quadruple[0] = ep_rank;
405    my_quadruple[1] = (*newintercomm)->ep_comm_ptr->size_rank_info[1].first;
406    my_quadruple[2] = (*newintercomm)->ep_comm_ptr->size_rank_info[2].first;
407    my_quadruple[3] = (*newintercomm)->ep_comm_ptr->comm_label;
408
409
410#ifdef _showinfo
411
412    MPI_Barrier(peer_comm);
413    MPI_Barrier(peer_comm);
414    printf("peer_rank = %d, my_quadruple = %d %d %d %d\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, my_quadruple[0], my_quadruple[1], my_quadruple[2], my_quadruple[3]);
415    MPI_Barrier(peer_comm);
416    MPI_Barrier(peer_comm);
417#endif
418
419    int *local_quadruple_list;
420    int *remote_quadruple_list;
421    if(is_involved)
422    {
423      local_quadruple_list = new int[4*ep_size];
424      remote_quadruple_list = new int[4*remote_ep_size];
425
426    }
427
428    MPI_Gather(my_quadruple, 4, MPI_INT, local_quadruple_list, 4, MPI_INT, local_leader, local_comm);
429
430
431    if(is_local_leader)
432    {
433      MPI_Request request[2];
434      MPI_Status status[2];
435      MPI_Isend(local_quadruple_list,  4*ep_size,        MPI_INT, remote_leader, tag, peer_comm, &request[0]);
436      MPI_Irecv(remote_quadruple_list, 4*remote_ep_size, MPI_INT, remote_leader, tag, peer_comm, &request[1]);
437      MPI_Waitall(2, request, status);
438    }
439
440    if(is_involved)
441    {
442      ::MPI_Bcast(remote_quadruple_list, 4*remote_ep_size, to_mpi_type(MPI_INT), local_comm->ep_rank_map->at(local_leader).second, to_mpi_comm(local_comm->mpi_comm));
443      (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map = new INTERCOMM_RANK_MAP;
444      for(int i=0; i<remote_ep_size; i++)
445      {
446        (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->insert(std::pair<int, std::pair< int, std::pair<int, int> > >(remote_quadruple_list[4*i], remote_quadruple_list[4*i+1], remote_quadruple_list[4*i+2], remote_quadruple_list[4*i+3]));
447      }
448    }
449
450
451    // step 8 : associate intercomm_rank_map to endpoints
452
453    int *leader_rank_in_world_local_gathered = new int[(*newintercomm)->ep_comm_ptr->size_rank_info[1].second];
454
455    MPI_Allgather_local(&local_leader_rank_in_world, 1, MPI_INT, leader_rank_in_world_local_gathered, *newintercomm);
456
457
458    int new_rank_loc = (*newintercomm)->ep_comm_ptr->size_rank_info[1].first;
459    int *new_rank_loc_local_gathered = new int[(*newintercomm)->ep_comm_ptr->size_rank_info[1].second];
460
461    MPI_Allgather_local(&new_rank_loc, 1, MPI_INT, new_rank_loc_local_gathered, *newintercomm);
462
463    //printf("peer_rank = %d, leader_rank_in_world_local_gathered = %d %d %d %d, new_rank_loc_local_gathered = %d %d %d %d\n",
464    //  peer_comm->ep_comm_ptr->size_rank_info[0].first, leader_rank_in_world_local_gathered[0], leader_rank_in_world_local_gathered[1], leader_rank_in_world_local_gathered[2], leader_rank_in_world_local_gathered[3],
465    //  new_rank_loc_local_gathered[0], new_rank_loc_local_gathered[1], new_rank_loc_local_gathered[2], new_rank_loc_local_gathered[3]);
466
467    if(is_involved)
468    {
469      if((*newintercomm)->ep_comm_ptr->size_rank_info[1].first == 0)
470      {
471        (*newintercomm)->ep_rank_map->clear();
472        delete (*newintercomm)->ep_rank_map;
473      }
474      (*newintercomm)->ep_rank_map = new EP_RANK_MAP[ep_size];
475      *((*newintercomm)->ep_rank_map) = *(local_comm->ep_rank_map);
476    }
477
478    MPI_Barrier_local(*newintercomm);
479
480   
481    if(!is_involved)
482    {
483      int target;
484      for(int i=0; i<(*newintercomm)->ep_comm_ptr->size_rank_info[1].second; i++)
485      {
486        if(local_leader_rank_in_world == leader_rank_in_world_local_gathered[i])
487        {
488          target = i;
489          break;
490        }
491      }
492      (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map = (*newintercomm)->ep_comm_ptr->comm_list[target]->ep_comm_ptr->intercomm->intercomm_rank_map;
493      (*newintercomm)->ep_rank_map = (*newintercomm)->ep_comm_ptr->comm_list[target]->ep_rank_map;
494    }
495
496
497    //printf("peer_rank = %d, intercomm_rank_map add = %p\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map);
498   
499
500    if(peer_comm->ep_comm_ptr->size_rank_info[0].first == 5)
501    {
502      int receiver = rand()%10;
503      printf("receiver = %d, intercomm_local_rank = %d, intercomm_mpi_rank = %d, comm_label = %d\n", receiver, (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(receiver).first, 
504        (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(receiver).second.first, (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(receiver).second.second);
505    }
506
507    if(peer_comm->ep_comm_ptr->size_rank_info[0].first == 9)
508    {
509      int receiver = rand()%6;
510      printf("receiver = %d, intercomm_local_rank = %d, intercomm_mpi_rank = %d, comm_label = %d\n", receiver, (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(receiver).first, 
511        (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(receiver).second.first, (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(receiver).second.second);
512    }
513
514    //printf("peer_rank = %d, rank_map add = %p\n", peer_comm->ep_comm_ptr->size_rank_info[0].first, (*newintercomm)->ep_rank_map);
515
516
517    if(peer_comm->ep_comm_ptr->size_rank_info[0].first == 5)
518    {
519      for(int i=0; i<ep_size; i++)
520      {
521        printf("rank_map->at(%d) = %d, %d\n", i, (*newintercomm)->ep_rank_map->at(i).first, (*newintercomm)->ep_rank_map->at(i).second);
522      }
523    }
524
525
526    // clean up
527
528    delete ranks_in_world_local;
529    delete ranks_in_world_remote;
530
531    if(is_involved)
532    {
533      delete local_quadruple_list;
534      delete remote_quadruple_list;
535    }
536
537    delete leader_rank_in_world_local_gathered;
538    delete new_rank_loc_local_gathered;
539
540
541  }
542
543  int MPI_Intercomm_create_kernel_bkp(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm *newintercomm)
544  {
545    int ep_rank, ep_rank_loc, mpi_rank;
546    int ep_size, num_ep, mpi_size;
547
548    ep_rank = local_comm->ep_comm_ptr->size_rank_info[0].first;
549    ep_rank_loc = local_comm->ep_comm_ptr->size_rank_info[1].first;
550    mpi_rank = local_comm->ep_comm_ptr->size_rank_info[2].first;
551    ep_size = local_comm->ep_comm_ptr->size_rank_info[0].second;
552    num_ep = local_comm->ep_comm_ptr->size_rank_info[1].second;
553    mpi_size = local_comm->ep_comm_ptr->size_rank_info[2].second;
554
555
556    std::vector<int> rank_info[4];  //! 0->rank_in_world of local_comm,  1->rank_in_local_parent of local_comm
557                                    //! 2->rank_in_world of remote_comm, 3->rank_in_local_parent of remote_comm
558
559    int rank_in_world;
560    int rank_in_local_parent;
561
562    int rank_in_peer_mpi[2];
563
564    int local_ep_size = ep_size;
565    int remote_ep_size;
566
567
568    ::MPI_Comm local_mpi_comm = to_mpi_comm(local_comm->mpi_comm);
569
570   
571    ::MPI_Comm_rank(to_mpi_comm(MPI_COMM_WORLD->mpi_comm), &rank_in_world);
572    ::MPI_Comm_rank(local_mpi_comm, &rank_in_local_parent);
573   
574
575    bool is_proc_master = false;
576    bool is_local_leader = false;
577    bool is_final_master = false;
578
579
580    if(ep_rank == local_leader) { is_proc_master = true; is_local_leader = true; is_final_master = true;}
581    if(ep_rank_loc == 0 && mpi_rank != local_comm->ep_rank_map->at(local_leader).second) is_proc_master = true;
582
583
584    int size_info[4]; //! used for choose size of rank_info 0-> mpi_size of local_comm, 1-> mpi_size of remote_comm
585
586    int leader_info[4]; //! 0->world rank of local_leader, 1->world rank of remote leader
587
588
589    std::vector<int> ep_info[2]; //! 0-> num_ep in local_comm, 1->num_ep in remote_comm
590
591    std::vector<int> new_rank_info[4];
592    std::vector<int> new_ep_info[2];
593
594    std::vector<int> offset;
595
596    if(is_proc_master)
597    {
598
599      size_info[0] = mpi_size;
600
601      rank_info[0].resize(size_info[0]);
602      rank_info[1].resize(size_info[0]);
603
604
605
606      ep_info[0].resize(size_info[0]);
607
608      vector<int> send_buf(6);
609      vector<int> recv_buf(3*size_info[0]);
610
611      send_buf[0] = rank_in_world;
612      send_buf[1] = rank_in_local_parent;
613      send_buf[2] = num_ep;
614
615      ::MPI_Allgather(send_buf.data(), 3, to_mpi_type(MPI_INT), recv_buf.data(), 3, to_mpi_type(MPI_INT), local_mpi_comm);
616
617      for(int i=0; i<size_info[0]; i++)
618      {
619        rank_info[0][i] = recv_buf[3*i];
620        rank_info[1][i] = recv_buf[3*i+1];
621        ep_info[0][i]   = recv_buf[3*i+2];
622      }
623
624      if(is_local_leader)
625      {
626        leader_info[0] = rank_in_world;
627        leader_info[1] = remote_leader;
628
629        ::MPI_Comm_rank(to_mpi_comm(peer_comm->mpi_comm), &rank_in_peer_mpi[0]);
630
631        send_buf[0] = size_info[0];
632        send_buf[1] = local_ep_size;
633        send_buf[2] = rank_in_peer_mpi[0];
634
635       
636       
637        MPI_Request requests[2];
638        MPI_Status statuses[2];
639       
640        MPI_Isend(send_buf.data(), 3, MPI_INT, remote_leader, tag, peer_comm, &requests[0]);
641        MPI_Irecv(recv_buf.data(), 3, MPI_INT, remote_leader, tag, peer_comm, &requests[1]);
642
643
644        MPI_Waitall(2, requests, statuses);
645       
646        size_info[1] = recv_buf[0];
647        remote_ep_size = recv_buf[1];
648        rank_in_peer_mpi[1] = recv_buf[2];
649
650      }
651
652
653
654      send_buf[0] = size_info[1];
655      send_buf[1] = leader_info[0];
656      send_buf[2] = leader_info[1];
657      send_buf[3] = rank_in_peer_mpi[0];
658      send_buf[4] = rank_in_peer_mpi[1];
659
660      ::MPI_Bcast(send_buf.data(), 5, to_mpi_type(MPI_INT), local_comm->ep_rank_map->at(local_leader).second, local_mpi_comm);
661
662      size_info[1] = send_buf[0];
663      leader_info[0] = send_buf[1];
664      leader_info[1] = send_buf[2];
665      rank_in_peer_mpi[0] = send_buf[3];
666      rank_in_peer_mpi[1] = send_buf[4];
667
668
669      rank_info[2].resize(size_info[1]);
670      rank_info[3].resize(size_info[1]);
671
672      ep_info[1].resize(size_info[1]);
673
674      send_buf.resize(3*size_info[0]);
675      recv_buf.resize(3*size_info[1]);
676
677      if(is_local_leader)
678      {
679        MPI_Request requests[2];
680        MPI_Status statuses[2];
681
682        std::copy ( rank_info[0].data(), rank_info[0].data() + size_info[0], send_buf.begin() );
683        std::copy ( rank_info[1].data(), rank_info[1].data() + size_info[0], send_buf.begin() + size_info[0] );
684        std::copy ( ep_info[0].data(),   ep_info[0].data()   + size_info[0], send_buf.begin() + 2*size_info[0] );
685
686        MPI_Isend(send_buf.data(), 3*size_info[0], MPI_INT, remote_leader, tag+1, peer_comm, &requests[0]);
687        MPI_Irecv(recv_buf.data(), 3*size_info[1], MPI_INT, remote_leader, tag+1, peer_comm, &requests[1]);
688       
689        MPI_Waitall(2, requests, statuses);
690      }
691
692      ::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);
693
694      std::copy ( recv_buf.data(), recv_buf.data() + size_info[1], rank_info[2].begin() );
695      std::copy ( recv_buf.data() + size_info[1], recv_buf.data() + 2*size_info[1], rank_info[3].begin()  );
696      std::copy ( recv_buf.data() + 2*size_info[1], recv_buf.data() + 3*size_info[1], ep_info[1].begin() );
697
698
699      offset.resize(size_info[0]);
700
701      if(leader_info[0]<leader_info[1]) // erase all ranks doubled with remote_comm, except the local leader
702      {
703
704        bool found = false;
705        int ep_local;
706        int ep_remote;
707        for(int i=0; i<size_info[0]; i++)
708        {
709          int target = rank_info[0][i];
710          found = false;
711          for(int j=0; j<size_info[1]; j++)
712          {
713            if(target == rank_info[2][j])
714            {
715              found = true;
716              ep_local = ep_info[0][j];
717              ep_remote = ep_info[1][j];
718              break;
719            }
720          }
721          if(found)
722          {
723
724            if(target == leader_info[0]) // the leader is doubled in remote
725            {
726              new_rank_info[0].push_back(target);
727              new_rank_info[1].push_back(rank_info[1][i]);
728
729              new_ep_info[0].push_back(ep_local + ep_remote);
730              offset[i] = 0;
731            }
732            else
733            {
734              offset[i] = ep_local;
735            }
736          }
737          else
738          {
739            new_rank_info[0].push_back(target);
740            new_rank_info[1].push_back(rank_info[1][i]);
741
742            new_ep_info[0].push_back(ep_info[0][i]);
743
744            offset[i] = 0;
745          }
746
747        }
748      }
749
750      else // erase rank doubled with remote leader
751      {
752
753        bool found = false;
754        int ep_local;
755        int ep_remote;
756        for(int i=0; i<size_info[0]; i++)
757        {
758          int target = rank_info[0][i];
759          found = false;
760          for(int j=0; j<size_info[1]; j++)
761          {
762
763            if(target == rank_info[2][j])
764            {
765              found = true;
766              ep_local = ep_info[0][j];
767              ep_remote = ep_info[1][j];
768              break;
769            }
770          }
771          if(found)
772          {
773            if(target != leader_info[1])
774            {
775              new_rank_info[0].push_back(target);
776              new_rank_info[1].push_back(rank_info[1][i]);
777
778              new_ep_info[0].push_back(ep_local + ep_remote);
779              offset[i] = 0;
780            }
781            else // found remote leader
782            {
783              offset[i] = ep_remote;
784            }
785          }
786          else
787          {
788            new_rank_info[0].push_back(target);
789            new_rank_info[1].push_back(rank_info[1][i]);
790
791            new_ep_info[0].push_back(ep_info[0][i]);
792            offset[i] = 0;
793          }
794        }
795      }
796
797      if(offset[mpi_rank] == 0)
798      {
799        is_final_master = true;
800      }
801
802
803      //! size_info[4]: 2->size of new_ep_info for local, 3->size of new_ep_info for remote
804
805      if(is_local_leader)
806      {
807        size_info[2] = new_ep_info[0].size();
808        MPI_Request requests[2];
809        MPI_Status statuses[2];
810        MPI_Isend(&size_info[2], 1, MPI_INT, remote_leader, tag+2, peer_comm, &requests[0]);
811        MPI_Irecv(&size_info[3], 1, MPI_INT, remote_leader, tag+2, peer_comm, &requests[1]);
812         
813        MPI_Waitall(2, requests, statuses);
814      }
815
816      ::MPI_Bcast(&size_info[2], 2, to_mpi_type(MPI_INT), local_comm->ep_rank_map->at(local_leader).second, local_mpi_comm);
817
818      new_rank_info[2].resize(size_info[3]);
819      new_rank_info[3].resize(size_info[3]);
820      new_ep_info[1].resize(size_info[3]);
821
822      send_buf.resize(size_info[2]);
823      recv_buf.resize(size_info[3]);
824
825      if(is_local_leader)
826      {
827        MPI_Request requests[2];
828        MPI_Status statuses[2];
829
830        std::copy ( new_rank_info[0].data(), new_rank_info[0].data() + size_info[2], send_buf.begin() );
831        std::copy ( new_rank_info[1].data(), new_rank_info[1].data() + size_info[2], send_buf.begin() + size_info[2] );
832        std::copy ( new_ep_info[0].data(),   new_ep_info[0].data()   + size_info[0], send_buf.begin() + 2*size_info[2] );
833
834        MPI_Isend(send_buf.data(), 3*size_info[2], MPI_INT, remote_leader, tag+3, peer_comm, &requests[0]);
835        MPI_Irecv(recv_buf.data(), 3*size_info[3], MPI_INT, remote_leader, tag+3, peer_comm, &requests[1]);
836       
837        MPI_Waitall(2, requests, statuses);
838      }
839
840      ::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);
841
842      std::copy ( recv_buf.data(), recv_buf.data() + size_info[3], new_rank_info[2].begin() );
843      std::copy ( recv_buf.data() + size_info[3], recv_buf.data() + 2*size_info[3], new_rank_info[3].begin()  );
844      std::copy ( recv_buf.data() + 2*size_info[3], recv_buf.data() + 3*size_info[3], new_ep_info[1].begin() );
845
846    }
847
848   
849
850    if(is_proc_master)
851    {
852      //! leader_info[4]: 2-> rank of local leader in new_group generated comm;
853                      // 3-> rank of remote leader in new_group generated comm;
854      ::MPI_Group local_group;
855      ::MPI_Group new_group;
856      ::MPI_Comm *new_comm = new ::MPI_Comm;
857      ::MPI_Comm *intercomm = new ::MPI_Comm;
858
859      ::MPI_Comm_group(local_mpi_comm, &local_group);
860
861      ::MPI_Group_incl(local_group, size_info[2], new_rank_info[1].data(), &new_group);
862
863      ::MPI_Comm_create(local_mpi_comm, new_group, new_comm);
864
865
866
867      if(is_local_leader)
868      {
869        ::MPI_Comm_rank(*new_comm, &leader_info[2]);
870      }
871
872      ::MPI_Bcast(&leader_info[2], 1, to_mpi_type(MPI_INT), local_comm->ep_rank_map->at(local_leader).second, local_mpi_comm);
873
874      if(new_comm != static_cast< ::MPI_Comm*>(MPI_COMM_NULL->mpi_comm))
875      {
876
877        ::MPI_Barrier(*new_comm);
878
879        ::MPI_Intercomm_create(*new_comm, leader_info[2], to_mpi_comm(peer_comm->mpi_comm), rank_in_peer_mpi[1], tag, intercomm);
880
881        int id;
882
883        ::MPI_Comm_rank(*new_comm, &id);
884        int my_num_ep = new_ep_info[0][id];
885
886        MPI_Comm *ep_intercomm;
887        MPI_Info info;
888        MPI_Comm_create_endpoints(new_comm, my_num_ep, info, ep_intercomm);
889
890
891        for(int i= 0; i<my_num_ep; i++)
892        {
893          ep_intercomm[i]->is_intercomm = true;
894
895          ep_intercomm[i]->ep_comm_ptr->intercomm = new ep_lib::ep_intercomm;
896          ep_intercomm[i]->ep_comm_ptr->intercomm->mpi_inter_comm = intercomm;
897          ep_intercomm[i]->ep_comm_ptr->comm_label = leader_info[0];
898        }
899
900
901        #pragma omp critical (write_to_tag_list)
902        tag_list.push_back(make_pair( make_pair(tag, min(leader_info[0], leader_info[1])) , ep_intercomm));
903        //printf("tag_list size = %lu\n", tag_list.size());
904      }
905    }
906
907    vector<int> bcast_buf(8);
908    if(is_local_leader)
909    {
910      std::copy(size_info, size_info+4, bcast_buf.begin());
911      std::copy(leader_info, leader_info+4, bcast_buf.begin()+4);
912    }
913
914    MPI_Bcast(bcast_buf.data(), 8, MPI_INT, local_leader, local_comm);
915
916    if(!is_local_leader)
917    {
918      std::copy(bcast_buf.begin(), bcast_buf.begin()+4, size_info);
919      std::copy(bcast_buf.begin()+4, bcast_buf.begin()+8, leader_info);
920    }
921
922    if(!is_local_leader)
923    {
924      new_rank_info[1].resize(size_info[2]);
925      ep_info[1].resize(size_info[1]);
926      offset.resize(size_info[0]);
927    }
928
929    bcast_buf.resize(size_info[2]+size_info[1]+size_info[0]+1);
930
931    if(is_local_leader)
932    {
933      bcast_buf[0] = remote_ep_size;
934      std::copy(new_rank_info[1].data(), new_rank_info[1].data()+size_info[2], bcast_buf.begin()+1);
935      std::copy(ep_info[1].data(), ep_info[1].data()+size_info[1], bcast_buf.begin()+size_info[2]+1);
936      std::copy(offset.data(), offset.data()+size_info[0], bcast_buf.begin()+size_info[2]+size_info[1]+1);
937    }
938
939    MPI_Bcast(bcast_buf.data(), size_info[2]+size_info[1]+size_info[0]+1, MPI_INT, local_leader, local_comm);
940
941    if(!is_local_leader)
942    {
943      remote_ep_size = bcast_buf[0];
944      std::copy(bcast_buf.data()+1, bcast_buf.data()+1+size_info[2], new_rank_info[1].begin());
945      std::copy(bcast_buf.data()+1+size_info[2], bcast_buf.data()+1+size_info[2]+size_info[1], ep_info[1].begin());
946      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());
947    }
948
949    int my_position = offset[rank_in_local_parent]+ep_rank_loc;
950   
951    MPI_Barrier_local(local_comm);
952    #pragma omp flush
953
954
955    #pragma omp critical (read_from_tag_list)
956    {
957      bool found = false;
958      while(!found)
959      {
960        for(std::list<std::pair < std::pair<int,int>, MPI_Comm* > >::iterator iter = tag_list.begin(); iter!=tag_list.end(); iter++)
961        {
962          if((*iter).first == make_pair(tag, min(leader_info[0], leader_info[1])))
963          {
964            *newintercomm = iter->second[my_position];
965            found = true;
966            break;
967          }
968        }
969      }
970    }
971
972    MPI_Barrier(local_comm);
973
974    if(is_local_leader)
975    {
976      int local_flag = true;
977      int remote_flag = false;
978      MPI_Request mpi_requests[2];
979      MPI_Status mpi_statuses[2];
980     
981      MPI_Isend(&local_flag, 1, MPI_INT, remote_leader, tag, peer_comm, &mpi_requests[0]);
982      MPI_Irecv(&remote_flag, 1, MPI_INT, remote_leader, tag, peer_comm, &mpi_requests[1]);
983     
984      MPI_Waitall(2, mpi_requests, mpi_statuses);
985    }
986
987
988    MPI_Barrier(local_comm);
989
990    if(is_proc_master)
991    {
992      for(std::list<std::pair < std::pair<int,int>, MPI_Comm* > >::iterator iter = tag_list.begin(); iter!=tag_list.end(); iter++)
993      {
994        if((*iter).first == make_pair(tag, min(leader_info[0], leader_info[1])))
995        {
996          tag_list.erase(iter);
997          break;
998        }
999      }
1000    }
1001
1002    int intercomm_ep_rank, intercomm_ep_rank_loc, intercomm_mpi_rank;
1003    int intercomm_ep_size, intercomm_num_ep, intercomm_mpi_size;
1004
1005    intercomm_ep_rank = (*newintercomm)->ep_comm_ptr->size_rank_info[0].first;
1006    intercomm_ep_rank_loc = (*newintercomm)->ep_comm_ptr->size_rank_info[1].first;
1007    intercomm_mpi_rank = (*newintercomm)->ep_comm_ptr->size_rank_info[2].first;
1008    intercomm_ep_size = (*newintercomm)->ep_comm_ptr->size_rank_info[0].second;
1009    intercomm_num_ep = (*newintercomm)->ep_comm_ptr->size_rank_info[1].second;
1010    intercomm_mpi_size = (*newintercomm)->ep_comm_ptr->size_rank_info[2].second;
1011
1012    MPI_Bcast(&remote_ep_size, 1, MPI_INT, local_leader, local_comm);
1013
1014    int my_rank_map_elem[2];
1015
1016    my_rank_map_elem[0] = intercomm_ep_rank;
1017    my_rank_map_elem[1] = (*newintercomm)->ep_comm_ptr->comm_label;
1018
1019    vector<pair<int, int> > local_rank_map_array;
1020    vector<pair<int, int> > remote_rank_map_array;
1021
1022
1023    (*newintercomm)->ep_comm_ptr->intercomm->local_rank_map = new RANK_MAP;
1024    (*newintercomm)->ep_comm_ptr->intercomm->local_rank_map->resize(local_ep_size);
1025
1026    MPI_Allgather(my_rank_map_elem, 2, MPI_INT, 
1027      (*newintercomm)->ep_comm_ptr->intercomm->local_rank_map->data(), 2, MPI_INT, local_comm);
1028
1029    (*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map = new RANK_MAP;
1030    (*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map->resize(remote_ep_size);
1031
1032    (*newintercomm)->ep_comm_ptr->intercomm->size_rank_info[0] = local_comm->ep_comm_ptr->size_rank_info[0];
1033    (*newintercomm)->ep_comm_ptr->intercomm->size_rank_info[1] = local_comm->ep_comm_ptr->size_rank_info[1];
1034    (*newintercomm)->ep_comm_ptr->intercomm->size_rank_info[2] = local_comm->ep_comm_ptr->size_rank_info[2];
1035
1036    int local_intercomm_size = intercomm_ep_size;
1037    int remote_intercomm_size;
1038
1039    int new_bcast_root_0 = 0;
1040    int new_bcast_root = 0;
1041
1042
1043    if(is_local_leader)
1044    {
1045      MPI_Request requests[4];
1046      MPI_Status statuses[4];
1047     
1048      MPI_Isend((*newintercomm)->ep_comm_ptr->intercomm->local_rank_map->data(), 2*local_ep_size, MPI_INT, remote_leader, tag+4, peer_comm, &requests[0]);
1049      MPI_Irecv((*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map->data(), 2*remote_ep_size, MPI_INT, remote_leader, tag+4, peer_comm, &requests[1]);
1050
1051      MPI_Isend(&local_intercomm_size, 1, MPI_INT, remote_leader, tag+5, peer_comm, &requests[2]);
1052      MPI_Irecv(&remote_intercomm_size, 1, MPI_INT, remote_leader, tag+5, peer_comm, &requests[3]);
1053     
1054      MPI_Waitall(4, requests, statuses);
1055
1056      new_bcast_root_0 = intercomm_ep_rank;
1057    }
1058
1059    MPI_Allreduce(&new_bcast_root_0, &new_bcast_root, 1, MPI_INT, MPI_SUM, *newintercomm);
1060
1061
1062    MPI_Bcast((*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map->data(), 2*remote_ep_size, MPI_INT, local_leader, local_comm);
1063    MPI_Bcast(&remote_intercomm_size, 1, MPI_INT, new_bcast_root, *newintercomm);
1064
1065
1066    //(*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map = new RANK_MAP;
1067    //(*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->resize(remote_intercomm_size);
1068
1069
1070
1071
1072    if(is_local_leader)
1073    {
1074      MPI_Request requests[2];
1075      MPI_Status statuses[2];
1076     
1077      std::vector<std::pair<int, std::pair<int, int> > > map2vec((*newintercomm)->ep_rank_map->size());
1078      std::vector<std::pair<int, std::pair<int, int> > > vec2map((*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->size());
1079     
1080      int ii=0;
1081      for(std::map<int, std::pair<int, int> >::iterator it = (*newintercomm)->ep_rank_map->begin(); it != (*newintercomm)->ep_rank_map->end(); it++)
1082      {
1083        map2vec[ii++] = make_pair(it->first, make_pair(it->second.first, it->second.second));
1084      }
1085     
1086     
1087      MPI_Isend(map2vec.data(), 3*local_intercomm_size, MPI_INT, remote_leader, tag+6, peer_comm, &requests[0]);
1088      MPI_Irecv(vec2map.data(), 3*remote_intercomm_size, MPI_INT, remote_leader, tag+6, peer_comm, &requests[1]);
1089     
1090     
1091      for(ii=0; ii<vec2map.size(); ii++)
1092      {
1093        //(*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(vec2map[ii].first) = make_pair(vec2map[ii].second.first, vec2map[ii].second.second);
1094      }
1095     
1096      MPI_Waitall(2, requests, statuses);
1097    }
1098
1099    //MPI_Bcast((*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->data(), 2*remote_intercomm_size, MPI_INT, new_bcast_root, *newintercomm);
1100
1101    (*newintercomm)->ep_comm_ptr->intercomm->local_comm = (local_comm->ep_comm_ptr->comm_list[ep_rank_loc]);
1102    (*newintercomm)->ep_comm_ptr->intercomm->intercomm_tag = tag;
1103
1104/*
1105    for(int i=0; i<local_ep_size; i++)
1106    if(local_comm->ep_comm_ptr->comm_label == 0) printf("ep_rank (from EP) = %d, local_rank_map[%d] = (%d,%d)\n", intercomm_ep_rank, i,
1107          (*newintercomm)->ep_comm_ptr->intercomm->local_rank_map->at(i).first, (*newintercomm)->ep_comm_ptr->intercomm->local_rank_map->at(i).second);
1108
1109    for(int i=0; i<remote_ep_size; i++)
1110    if(local_comm->ep_comm_ptr->comm_label == 0) printf("ep_rank (from EP) = %d, remote_rank_map[%d] = (%d,%d)\n", intercomm_ep_rank, i,
1111          (*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map->at(i).first, (*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map->at(i).second);
1112
1113    for(int i=0; i<remote_intercomm_size; i++)
1114    if(local_comm->ep_comm_ptr->comm_label == 0) printf("ep_rank (from EP) = %d, intercomm_rank_map[%d] = (%d,%d)\n", intercomm_ep_rank, i,
1115          (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(i).first, (*newintercomm)->ep_comm_ptr->intercomm->intercomm_rank_map->at(i).second);
1116*/
1117
1118//    for(int i=0; i<(*newintercomm)->rank_map->size(); i++)
1119//    if(local_comm->ep_comm_ptr->comm_label != 99) printf("ep_rank = %d, rank_map[%d] = (%d,%d)\n", intercomm_ep_rank, i,
1120//          (*newintercomm)->rank_map->at(i).first, (*newintercomm)->rank_map->at(i).second);
1121
1122//    MPI_Comm *test_comm = newintercomm->ep_comm_ptr->intercomm->local_comm;
1123//    int test_rank;
1124//    MPI_Comm_rank(*test_comm, &test_rank);
1125//    printf("=================test_rank = %d\n", test_rank);
1126   
1127   
1128
1129    return MPI_SUCCESS;
1130
1131  }
1132
1133
1134
1135
1136  int MPI_Intercomm_create_unique_leader(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm *newintercomm)
1137  {
1138    //! mpi_size of local comm = 1
1139    //! same world rank of leaders
1140
1141    int ep_rank, ep_rank_loc, mpi_rank;
1142    int ep_size, num_ep, mpi_size;
1143
1144    ep_rank = local_comm->ep_comm_ptr->size_rank_info[0].first;
1145    ep_rank_loc = local_comm->ep_comm_ptr->size_rank_info[1].first;
1146    mpi_rank = local_comm->ep_comm_ptr->size_rank_info[2].first;
1147    ep_size = local_comm->ep_comm_ptr->size_rank_info[0].second;
1148    num_ep = local_comm->ep_comm_ptr->size_rank_info[1].second;
1149    mpi_size = local_comm->ep_comm_ptr->size_rank_info[2].second;
1150
1151
1152
1153    std::vector<int> rank_info[4];  //! 0->rank_in_world of local_comm,  1->rank_in_local_parent of local_comm
1154                                    //! 2->rank_in_world of remote_comm, 3->rank_in_local_parent of remote_comm
1155
1156    int rank_in_world;
1157
1158    int rank_in_peer_mpi[2];
1159
1160    ::MPI_Comm_rank(to_mpi_comm(MPI_COMM_WORLD->mpi_comm), &rank_in_world);
1161
1162
1163    int local_num_ep = num_ep;
1164    int remote_num_ep;
1165    int total_num_ep;
1166
1167    int leader_rank_in_peer[2];
1168
1169    int my_position;
1170    int tag_label[2];
1171
1172    vector<int> send_buf(4);
1173    vector<int> recv_buf(4);
1174
1175
1176    if(ep_rank == local_leader)
1177    {
1178      MPI_Status status;
1179
1180
1181
1182      MPI_Comm_rank(peer_comm, &leader_rank_in_peer[0]);
1183
1184      send_buf[0] = local_num_ep;
1185      send_buf[1] = leader_rank_in_peer[0];
1186
1187      MPI_Request req_s, req_r;
1188
1189      MPI_Isend(send_buf.data(), 2, MPI_INT, remote_leader, tag, peer_comm, &req_s);
1190      MPI_Irecv(recv_buf.data(), 2, MPI_INT, remote_leader, tag, peer_comm, &req_r);
1191
1192
1193      MPI_Wait(&req_s, &status);
1194      MPI_Wait(&req_r, &status);
1195
1196      recv_buf[2] = leader_rank_in_peer[0];
1197
1198    }
1199
1200    MPI_Bcast(recv_buf.data(), 3, MPI_INT, local_leader, local_comm);
1201
1202    remote_num_ep = recv_buf[0];
1203    leader_rank_in_peer[1] = recv_buf[1];
1204    leader_rank_in_peer[0] = recv_buf[2];
1205
1206    total_num_ep = local_num_ep + remote_num_ep;
1207
1208
1209    if(leader_rank_in_peer[0] < leader_rank_in_peer[1])
1210    {
1211      my_position = ep_rank_loc;
1212      //! LEADER create EP
1213      if(ep_rank == local_leader)
1214      {
1215        ::MPI_Comm *mpi_dup = new ::MPI_Comm;
1216       
1217        ::MPI_Comm_dup(to_mpi_comm(local_comm->mpi_comm), mpi_dup);
1218
1219        MPI_Comm *ep_intercomm;
1220        MPI_Info info;
1221        MPI_Comm_create_endpoints(mpi_dup, total_num_ep, info, ep_intercomm);
1222
1223
1224        for(int i=0; i<total_num_ep; i++)
1225        {
1226          ep_intercomm[i]->is_intercomm = true;
1227          ep_intercomm[i]->ep_comm_ptr->intercomm = new ep_lib::ep_intercomm;
1228          ep_intercomm[i]->ep_comm_ptr->intercomm->mpi_inter_comm = 0;
1229
1230          ep_intercomm[i]->ep_comm_ptr->comm_label = leader_rank_in_peer[0];
1231        }
1232
1233        tag_label[0] = TAG++;
1234        tag_label[1] = rank_in_world;
1235
1236        #pragma omp critical (write_to_tag_list)
1237        tag_list.push_back(make_pair( make_pair(tag_label[0], tag_label[1]) , ep_intercomm));
1238
1239        MPI_Request req_s;
1240        MPI_Status sta_s;
1241        MPI_Isend(tag_label, 2, MPI_INT, remote_leader, tag, peer_comm, &req_s);
1242
1243        MPI_Wait(&req_s, &sta_s);
1244
1245      }
1246    }
1247    else
1248    {
1249      //! Wait for EP creation
1250      my_position = remote_num_ep + ep_rank_loc;
1251      if(ep_rank == local_leader)
1252      {
1253        MPI_Status status;
1254        MPI_Request req_r;
1255        MPI_Irecv(tag_label, 2, MPI_INT, remote_leader, tag, peer_comm, &req_r);
1256        MPI_Wait(&req_r, &status);
1257      }
1258    }
1259
1260    MPI_Bcast(tag_label, 2, MPI_INT, local_leader, local_comm);
1261
1262
1263
1264
1265    #pragma omp critical (read_from_tag_list)
1266    {
1267      bool found = false;
1268      while(!found)
1269      {
1270        for(std::list<std::pair < std::pair<int,int>, MPI_Comm* > >::iterator iter = tag_list.begin(); iter!=tag_list.end(); iter++)
1271        {
1272          if((*iter).first == make_pair(tag_label[0], tag_label[1]))
1273          {
1274            *newintercomm =  iter->second[my_position];
1275            found = true;
1276            // tag_list.erase(iter);
1277            break;
1278          }
1279        }
1280      }
1281    }
1282
1283    MPI_Barrier_local(local_comm);
1284
1285    if(leader_rank_in_peer[0] < leader_rank_in_peer[1])
1286    {
1287      for(std::list<std::pair < std::pair<int,int>, MPI_Comm* > >::iterator iter = tag_list.begin(); iter!=tag_list.end(); iter++)
1288        {
1289          if((*iter).first == make_pair(tag_label[0], tag_label[1]))
1290          {
1291            tag_list.erase(iter);
1292            break;
1293          }
1294        }
1295    }
1296
1297
1298
1299    int intercomm_ep_rank, intercomm_ep_rank_loc, intercomm_mpi_rank;
1300    int intercomm_ep_size, intercomm_num_ep, intercomm_mpi_size;
1301
1302    intercomm_ep_rank = (*newintercomm)->ep_comm_ptr->size_rank_info[0].first;
1303    intercomm_ep_rank_loc = (*newintercomm)->ep_comm_ptr->size_rank_info[1].first;
1304    intercomm_mpi_rank = (*newintercomm)->ep_comm_ptr->size_rank_info[2].first;
1305    intercomm_ep_size = (*newintercomm)->ep_comm_ptr->size_rank_info[0].second;
1306    intercomm_num_ep = (*newintercomm)->ep_comm_ptr->size_rank_info[1].second;
1307    intercomm_mpi_size = (*newintercomm)->ep_comm_ptr->size_rank_info[2].second;
1308
1309
1310
1311    (*newintercomm)->ep_comm_ptr->intercomm->local_rank_map  = new RANK_MAP;
1312    (*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map = new RANK_MAP;
1313    (*newintercomm)->ep_comm_ptr->intercomm->local_rank_map->resize(local_num_ep);
1314    (*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map->resize(remote_num_ep);
1315
1316    (*newintercomm)->ep_comm_ptr->intercomm->size_rank_info[0] = local_comm->ep_comm_ptr->size_rank_info[0];
1317    (*newintercomm)->ep_comm_ptr->intercomm->size_rank_info[1] = local_comm->ep_comm_ptr->size_rank_info[1];
1318    (*newintercomm)->ep_comm_ptr->intercomm->size_rank_info[2] = local_comm->ep_comm_ptr->size_rank_info[2];
1319
1320
1321
1322    int local_rank_map_ele[2];
1323    local_rank_map_ele[0] = intercomm_ep_rank;
1324    local_rank_map_ele[1] = (*newintercomm)->ep_comm_ptr->comm_label;
1325
1326    MPI_Allgather(local_rank_map_ele, 2, MPI_INT, 
1327      (*newintercomm)->ep_comm_ptr->intercomm->local_rank_map->data(), 2, MPI_INT, local_comm);
1328
1329    if(ep_rank == local_leader)
1330    {
1331      MPI_Status status;
1332      MPI_Request req_s, req_r;
1333
1334      MPI_Isend((*newintercomm)->ep_comm_ptr->intercomm->local_rank_map->data(), 2*local_num_ep, MPI_INT, remote_leader, tag, peer_comm, &req_s);
1335      MPI_Irecv((*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map->data(), 2*remote_num_ep, MPI_INT, remote_leader, tag, peer_comm, &req_r);
1336
1337
1338      MPI_Wait(&req_s, &status);
1339      MPI_Wait(&req_r, &status);
1340
1341    }
1342
1343    MPI_Bcast((*newintercomm)->ep_comm_ptr->intercomm->remote_rank_map->data(), 2*remote_num_ep, MPI_INT, local_leader, local_comm);
1344    (*newintercomm)->ep_comm_ptr->intercomm->local_comm = (local_comm->ep_comm_ptr->comm_list[ep_rank_loc]);
1345    (*newintercomm)->ep_comm_ptr->intercomm->intercomm_tag = tag;
1346
1347
1348    return MPI_SUCCESS;
1349  }
1350
1351
1352}
Note: See TracBrowser for help on using the repository browser.