Bridge++  Ver. 1.3.x
communicator_mpi.cpp
Go to the documentation of this file.
1 
14 #include "layout.h"
15 
16 // exception handler for uncaught throw.
17 static std::terminate_handler default_handler = std::set_terminate(Communicator::abort);
18 
20 
28 #if 0
29 extern "C" {
30 void abort()
31 {
32  fprintf(stderr, "abort() called. terminate.\n");
34 }
35 }
36 #endif
37 
38 // define static members
39 #ifdef ENABLE_MULTI_INSTANCE
40 int Communicator_impl::m_n_instance = 1; // number of instances
41 int Communicator_impl::m_instance_id = 0; // id of present instance
42 #endif
43 
44 int Communicator_impl::m_global_rank = 0;
45 int Communicator_impl::m_global_size = 1;
46 
49 
51 
52 //====================================================================
53 // class methods
54 int Communicator_impl::init(int *pargc, char ***pargv)
55 {
56  LOG;
57 
58  MPI_Init(pargc, pargv);
59 
60  MPI_Comm_size(MPI_COMM_WORLD, &m_global_size);
61  MPI_Comm_rank(MPI_COMM_WORLD, &m_global_rank);
62 
63  // grid size and rank equal to global ones for a moment until layout is set.
64  m_grid_size = m_global_size;
65  m_grid_rank = m_global_rank;
66 
67  //- initialize m_comm, thanks to Aoyama-san.
68  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
69 
70  return EXIT_SUCCESS;
71 }
72 
73 
74 //====================================================================
76 {
77  LOG;
78  return MPI_Finalize();
79 }
80 
81 
82 //====================================================================
83 int Communicator_impl::setup(int ninstance)
84 {
85  LOG;
86 
87 #ifdef ENABLE_MULTI_INSTANCE
88  if ((ninstance == 0) || (m_global_size % ninstance != 0)) {
89  printf("%s: invalid number of instance: %d\n", "Communicator::init", ninstance);
90  abort();
91  }
92 
93  m_n_instance = ninstance;
94 
95  int gsize = m_global_size / ninstance;
96  m_instance_id = m_global_rank / gsize;
97 
98  MPI_Comm_split(MPI_COMM_WORLD, m_instance_id, 0 /* key */, &m_comm);
99 
100 #else
101 // m_n_instance = 1;
102 // m_instance_id = 0;
103 
104  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
105 #endif
106 
107  MPI_Comm_size(m_comm, &m_grid_size);
108  MPI_Comm_rank(m_comm, &m_grid_rank);
109 
111 
112  status();
113 
114  return EXIT_SUCCESS;
115 }
116 
117 
118 //====================================================================
120 {
121  LOG;
122  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
123  // unreached.
124 }
125 
126 
127 //====================================================================
128 // information
130 {
131  return m_grid_rank == 0;
132 }
133 
134 
135 //====================================================================
137 {
138  return m_grid_rank;
139 }
140 
141 
142 //====================================================================
144 {
145  return m_grid_size;
146 }
147 
148 
149 //====================================================================
150 bool Communicator_impl::is_primary_master()
151 {
152  return m_global_rank == 0;
153 }
154 
155 
156 //====================================================================
157 #ifdef ENABLE_MULTI_INSTANCE
158 
159 int Communicator_impl::self_global()
160 {
161  return m_global_rank;
162 }
163 
164 
165 //====================================================================
166 int Communicator_impl::world_id()
167 {
168  return m_instance_id;
169 }
170 #endif
171 
172 //====================================================================
173 // synchronize
175 {
176  LOG;
177  return MPI_Barrier(m_comm);
178 }
179 
180 
181 //====================================================================
182 #ifdef ENABLE_MULTI_INSTANCE
183 
184 int Communicator_impl::sync_global()
185 {
186  LOG;
187  return MPI_Barrier(MPI_COMM_WORLD);
188 }
189 #endif
190 
191 //====================================================================
192 // data transfer: base cases
193 int Communicator_impl::Base::broadcast(size_t size, void *data, int sender)
194 {
195  LOG;
196  return MPI_Bcast(data, size, MPI_BYTE, sender, m_comm);
197 }
198 
199 
200 //====================================================================
201 int Communicator_impl::Base::exchange(size_t size, void *recv_buf, void *send_buf, int idir, int ipm, int itag)
202 {
203  LOG;
204 
205  MPI_Status status;
206  int p_send, p_recv;
207 
208  assert(ipm == 1 || ipm == -1);
209 
210  if (Layout::m_grid_dims[idir] == 1) { // no need to transfer
211  memcpy(recv_buf, send_buf, size);
212  return EXIT_SUCCESS;
213  }
214 
215  if (ipm == 1) { // downward shift
216  p_send = Layout::m_ipe_dn[idir];
217  p_recv = Layout::m_ipe_up[idir];
218  } else { // upward shift
219  p_send = Layout::m_ipe_up[idir];
220  p_recv = Layout::m_ipe_dn[idir];
221  }
222 
223  int tag_send = Layout::tag(self(), idir, -ipm);
224  int tag_recv = Layout::tag(p_recv, idir, -ipm);
225 
226  return MPI_Sendrecv(
227  send_buf, size, MPI_BYTE, p_send, tag_send,
228  recv_buf, size, MPI_BYTE, p_recv, tag_recv,
229  m_comm, &status);
230 }
231 
232 
233 //====================================================================
234 int Communicator_impl::Base::send_1to1(size_t size, void *recv_buf, void *send_buf, int send_to, int recv_from, int tag)
235 {
236  LOG;
237 
238  MPI_Status status;
239 
240  if (send_to == recv_from) {
241  memcpy(recv_buf, send_buf, size);
242  } else {
243  if (self() == recv_from)
244  MPI_Send(send_buf, size, MPI_BYTE, send_to, tag, m_comm);
245 
246  if (self() == send_to)
247  MPI_Recv(recv_buf, size, MPI_BYTE, recv_from, tag, m_comm, &status);
248  }
249 
250  // sync should be taken outside.
251 
252  return EXIT_SUCCESS;
253 }
254 
255 
256 //====================================================================
257 int Communicator_impl::Base::reduce(int count, void *recv_buf, void *send_buf, MPI_Datatype type, MPI_Op op, int pattern)
258 {
259  LOG;
260  return MPI_Allreduce((void *)send_buf, (void *)recv_buf, count, type, op, Layout::m_sub_comm[pattern]);
261 }
262 
263 
264 //====================================================================
265 // data transfer for specific datatypes
266 int Communicator_impl::broadcast_string(int count, string& data, int sender)
267 {
268  LOG;
269  assert(count == 1);
270 
271  size_t size = 0;
272 
273  // broadcast string length.
274  if (Communicator::self() == sender) {
275  size = data.size();
276  }
277  MPI_Bcast((void *)&size, sizeof(size_t), MPI_BYTE, sender, m_comm);
278 
279  // allocate buffer. pack data at sender.
280  char *buf = new char[size + 1];
281  memset(buf, '\0', size + 1);
282 
283  if (Communicator::self() == sender) {
284  data.copy(buf, size, 0);
285  }
286 
287  // do broadcast.
288  int retv = MPI_Bcast((void *)buf, size, MPI_BYTE, sender, m_comm);
289 
290  if (Communicator::self() != sender) {
291  data = string(buf);
292  }
293 
294  delete [] buf;
295 
296  return retv;
297 }
298 
299 
300 //====================================================================
301 // info
303 {
304  return MPI_Wtime();
305 }
306 
307 
308 //====================================================================
309 // debug
311 {
312 #ifdef DEBUG
313 #ifdef ENABLE_MULTI_INSTANCE
314  printf("global_rank=%2d/%2d: ngrid=%d, grid_id=%d: grid_rank=%2d/%2d\n",
315  m_global_rank, m_global_size,
316  m_n_instance, m_instance_id,
318 
319 #else
320  printf("grid_rank=%2d/%2d\n",
322 #endif
323 #endif
324 
325 
326  return EXIT_SUCCESS;
327 }
328 
329 
330 //====================================================================
331 //============================================================END=====
static int send_1to1(size_t size, void *recv_buf, void *send_buf, int send_to, int recv_from, int tag)
static int broadcast(size_t size, void *data, int sender)
static int layout_setup()
layout_setup() – setup logical layout
Definition: layout.cpp:82
static void abort()
terminate communicator
static int self()
rank within small world.
#define LOG
Definition: defs.h:21
static int sync()
synchronize within small world.
static int setup(int ninstance=1)
static int status()
for debug
static bool is_primary()
info about rank
static int reduce(int count, void *recv_buf, void *send_buf, int type, int op, int pattern)
static int init(int *pargc, char ***pargv)
static int * m_sub_comm
Definition: layout.h:53
static int m_comm
instead of MPI_Comm m_comm;
static int * m_grid_dims
grid dimensions in directions.
Definition: layout.h:38
static int broadcast_string(int count, string &data, int sender)
for specific datatypes
static double get_time()
for getting time interval using clock count.
static int * m_ipe_up
rank of upward neighbour in directions.
Definition: layout.h:41
static int tag(int rank, int idir, int ipm)
Definition: layout.cpp:75
static int * m_ipe_dn
rank of downward neighbour in directions.
Definition: layout.h:42
static int exchange(size_t size, void *recv_buf, void *send_buf, int idir, int ipm, int tag)
static std::terminate_handler default_handler