source: XIOS/trunk/extern/src_ep/ep_intercomm.cpp @ 1034

Last change on this file since 1034 was 1034, checked in by yushan, 4 years ago

adding src_ep into extern folder

File size: 5.8 KB
Line 
1#include "ep_lib.hpp"
2#include <mpi.h>
3#include "ep_declaration.hpp"
4
5using namespace std;
6
7namespace ep_lib
8{
9  int MPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm *newintercomm)
10  {
11    assert(local_comm.is_ep);
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    MPI_Barrier(local_comm);
25
26
27
28    int leader_ranks[6]; //! 0: rank in world, 1: mpi_size, 2: rank_in_peer.
29                         //! 3, 4, 5 : remote
30
31    bool is_decider = false;
32
33
34
35    if(ep_rank == local_leader)
36    {
37      ::MPI_Comm_rank(MPI_COMM_WORLD_STD, &leader_ranks[0]);
38
39      leader_ranks[1] = mpi_size;
40      MPI_Comm_rank(peer_comm, &leader_ranks[2]);
41
42      MPI_Request req_s, req_r;
43      MPI_Isend(&leader_ranks[0], 3, MPI_INT_STD, remote_leader, tag, peer_comm, &req_s);
44      MPI_Status status;
45      MPI_Irecv(&leader_ranks[3], 3, MPI_INT_STD, remote_leader, tag, peer_comm, &req_r);
46      MPI_Wait(&req_s, &status);
47      MPI_Wait(&req_r, &status);
48    }
49
50    MPI_Bcast(leader_ranks, 6, MPI_INT_STD, local_leader, local_comm);
51
52    MPI_Barrier(local_comm);
53
54    if(leader_ranks[0] == leader_ranks[3])
55    {
56      if( leader_ranks[1] * leader_ranks[4] == 1)
57      {
58        if(ep_rank == local_leader) printf("calling MPI_Intercomm_create_unique_leader\n");
59        local_comm.ep_comm_ptr->comm_label = -99;
60
61        return MPI_Intercomm_create_unique_leader(local_comm, local_leader, peer_comm, remote_leader, tag, newintercomm);
62      }
63      else // leader_ranks[1] * leader_ranks[4] != 1
64      {
65        // change leader
66        if(ep_rank == local_leader) printf("calling MPI_Intercomm_create_from_world\n");
67
68        int new_local_leader;
69
70        if(leader_ranks[2] < leader_ranks[5])
71        {
72          if(leader_ranks[1] > 1) //! change leader
73          {
74            // change leader
75            is_decider = true;
76            int target = local_comm.rank_map->at(local_leader).second;
77            {
78              for(int i=0; i<ep_size; i++)
79              {
80                if(local_comm.rank_map->at(i).second != target && local_comm.rank_map->at(i).first == 0)
81                {
82                  new_local_leader = i;
83                  break;
84                }
85              }
86            }
87          }
88          else
89          {
90            new_local_leader = local_leader;
91          }
92        }
93        else
94        {
95          if(leader_ranks[4] == 1)
96          {
97            // change leader
98            is_decider = true;
99            int target = local_comm.rank_map->at(local_leader).second;
100            {
101              for(int i=0; i<ep_size; i++)
102              {
103                if(local_comm.rank_map->at(i).second != target && local_comm.rank_map->at(i).first == 0)
104                {
105                  new_local_leader = i;
106                  break;
107                }
108              }
109            }
110          }
111          else
112          {
113            new_local_leader = local_leader;
114          }
115        }
116
117
118        int new_tag_in_world;
119
120        int leader_in_world[2];
121
122
123        if(is_decider)
124        {
125          if(ep_rank == new_local_leader)
126          {
127            new_tag_in_world = TAG++;
128          }
129          MPI_Bcast(&new_tag_in_world, 1, MPI_INT_STD, new_local_leader, local_comm);
130          if(ep_rank == local_leader) MPI_Send(&new_tag_in_world, 1, MPI_INT_STD, remote_leader, tag, peer_comm);
131        }
132        else
133        {
134          if(ep_rank == local_leader)
135          {
136            MPI_Status status;
137            MPI_Recv(&new_tag_in_world, 1, MPI_INT_STD, remote_leader, tag, peer_comm, &status);
138          }
139          MPI_Bcast(&new_tag_in_world, 1, MPI_INT_STD, new_local_leader, local_comm);
140        }
141
142
143        if(ep_rank == new_local_leader)
144        {
145          #ifdef _serialized
146          #pragma omp critical (_mpi_call)
147          #endif // _serialized
148          ::MPI_Comm_rank(MPI_COMM_WORLD_STD, &leader_in_world[0]);
149        }
150
151        MPI_Bcast(&leader_in_world[0], 1, MPI_INT_STD, new_local_leader, local_comm);
152
153
154        if(ep_rank == local_leader)
155        {
156          MPI_Request req_s, req_r;
157
158          MPI_Isend(&leader_in_world[0], 1, MPI_INT_STD, remote_leader, tag, peer_comm, &req_s);
159          MPI_Irecv(&leader_in_world[1], 1, MPI_INT_STD, remote_leader, tag, peer_comm, &req_r);
160
161          MPI_Status status;
162          MPI_Wait(&req_s, &status);
163          MPI_Wait(&req_r, &status);
164
165      /*
166          MPI_Send(&leader_in_world[0], 1, MPI_INT_STD, remote_leader, tag, peer_comm);
167          MPI_Status status;
168          MPI_Recv(&leader_in_world[1], 1, MPI_INT_STD, remote_leader, tag, peer_comm, &status);
169   */
170        }
171
172
173
174        MPI_Bcast(&leader_in_world[1], 1, MPI_INT, local_leader, local_comm);
175
176
177
178        local_comm.ep_comm_ptr->comm_label = tag;
179
180        return MPI_Intercomm_create_from_world(local_comm, new_local_leader, MPI_COMM_WORLD_STD, leader_in_world[1], new_tag_in_world, newintercomm);
181      }
182    }
183
184    if(ep_rank == local_leader) printf("calling MPI_Intercomm_create_kernel\n");
185
186    return MPI_Intercomm_create_kernel(local_comm, local_leader, peer_comm, remote_leader, tag, newintercomm);
187
188  }
189
190  int MPI_Comm_test_inter(MPI_Comm comm, int *flag)
191  {
192    if(comm.is_ep)
193    {
194      *flag = comm.is_intercomm;
195      return 0;
196    } 
197    else
198    {
199      ::MPI_Comm mpi_comm = static_cast< ::MPI_Comm> (comm.mpi_comm);
200      #ifdef _serialized
201      #pragma omp critical (_mpi_call)
202      #endif
203      ::MPI_Comm_test_inter(mpi_comm, flag);
204      return 0; 
205    }
206  }
207
208
209}
Note: See TracBrowser for help on using the repository browser.