Bridge++  Ver. 2.0.2
communicator_mpi.cpp
Go to the documentation of this file.
1 
14 #include <unistd.h> // for usleep
15 #include "layout.h"
16 
17 // exception handler for uncaught throw.
18 static std::terminate_handler default_handler = std::set_terminate(Communicator::abort);
19 
20 // define static members
21 #ifdef ENABLE_MULTI_INSTANCE
22 int Communicator_impl::m_Ninstance = 1; // number of instances
23 int Communicator_impl::m_instance_id = 0; // id of present instance
24 #endif
25 
26 int Communicator_impl::m_global_rank = 0;
27 int Communicator_impl::m_global_size = 1;
28 
31 
33 
35 
36 //====================================================================
37 // class methods
38 int Communicator_impl::init(int *pargc, char ***pargv)
39 {
40  LOG;
41 
42  int is_initialized = 0;
43  MPI_Initialized(&is_initialized);
44 
45  if (is_initialized) {
46  fprintf(stderr, "Communicator: MPI already initialized. skip.\n");
47  } else {
48 #ifdef USE_OPENMP
49  int required = MPI_THREAD_FUNNELED;
50  int provided;
51 
52  MPI_Init_thread(pargc, pargv, required, &provided);
53 
54  if (provided < required) {
55  fprintf(stderr, "Communicator: MPI not supporting sufficient thread level. exiting.\n");
56  exit(EXIT_FAILURE);
57  }
58 #else
59  MPI_Init(pargc, pargv);
60 #endif
61  }
62 
63  MPI_Comm_size(MPI_COMM_WORLD, &m_global_size);
64  MPI_Comm_rank(MPI_COMM_WORLD, &m_global_rank);
65 
66  // grid size and rank equal to global ones for a moment until layout is set.
67  m_grid_size = m_global_size;
68  m_grid_rank = m_global_rank;
69 
70  //- initialize m_comm, thanks to Aoyama-san.
71  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
72 
73  return EXIT_SUCCESS;
74 }
75 
76 
77 //====================================================================
79 {
80  LOG;
81  return MPI_Finalize();
82 }
83 
84 
85 //====================================================================
86 int Communicator_impl::setup(int Ninstance)
87 {
88  LOG;
89 
90 #ifdef ENABLE_MULTI_INSTANCE
91  if ((Ninstance == 0) || (m_global_size % Ninstance != 0)) {
92  printf("%s: invalid number of instance: %d\n", "Communicator::init", Ninstance);
93  abort();
94  }
95 
96  m_Ninstance = Ninstance;
97 
98  int gsize = m_global_size / Ninstance;
99  m_instance_id = m_global_rank / gsize;
100 
101  MPI_Comm_split(MPI_COMM_WORLD, m_instance_id, 0 /* key */, &m_comm);
102 #else
103 // m_Ninstance = 1;
104 // m_instance_id = 0;
105 
106  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
107 #endif
108 
109  MPI_Comm_size(m_comm, &m_grid_size);
110  MPI_Comm_rank(m_comm, &m_grid_rank);
111 
113 
114  status();
115 
116  return EXIT_SUCCESS;
117 }
118 
119 
120 //====================================================================
122  const std::vector<int>& lattice_size,
123  std::vector<int>& grid_size,
124  int Ninstance)
125 {
126  LOG;
127 
128 #ifdef ENABLE_MULTI_INSTANCE
129  if ((Ninstance == 0) || (m_global_size % Ninstance != 0)) {
130  printf("%s: invalid number of instance: %d\n", "Communicator::init", Ninstance);
131  abort();
132  }
133 
134  m_Ninstance = Ninstance;
135 
136  int gsize = m_global_size / Ninstance;
137  m_instance_id = m_global_rank / gsize;
138 
139  MPI_Comm_split(MPI_COMM_WORLD, m_instance_id, 0 /* key */, &m_comm);
140 #else
141 // m_Ninstance = 1;
142 // m_instance_id = 0;
143 
144  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
145 #endif
146 
147  MPI_Comm_size(m_comm, &m_grid_size);
148  MPI_Comm_rank(m_comm, &m_grid_rank);
149 
150  Communicator_impl::Layout::layout_setup(lattice_size, grid_size);
151 
152  status();
153 
154  return EXIT_SUCCESS;
155 }
156 
157 
158 //====================================================================
160 {
161  LOG;
162  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
163  // unreached.
164 }
165 
166 
167 //====================================================================
168 // information
170 {
171  return m_grid_rank == 0;
172 }
173 
174 
175 //====================================================================
177 {
178  return m_grid_rank;
179 }
180 
181 
182 //====================================================================
184 {
185  return m_grid_size;
186 }
187 
188 
189 //====================================================================
190 bool Communicator_impl::is_primary_master()
191 {
192  return m_global_rank == 0;
193 }
194 
195 
196 //====================================================================
197 #ifdef ENABLE_MULTI_INSTANCE
198 
199 int Communicator_impl::self_global()
200 {
201  return m_global_rank;
202 }
203 
204 
205 //====================================================================
206 int Communicator_impl::world_id()
207 {
208  return m_instance_id;
209 }
210 
211 
212 #endif
213 
214 //====================================================================
215 // synchronize
217 {
218  LOG;
219  return MPI_Barrier(m_comm);
220 }
221 
222 
223 //====================================================================
224 // sync w/o (possible) busy wait
226 {
227  LOG;
228  char dummy = '\0';
229  const int interval = 100000; // 100ms
230  MPI_Request req;
231  MPI_Ibcast(&dummy, 1, MPI_BYTE, 0, m_comm, &req);
232 
233  MPI_Status status;
234  int finished = 0;
235 
236  while (!finished)
237  {
238  usleep(interval);
239  MPI_Test(&req, &finished, &status);
240  }
241  return finished;
242 }
243 
244 
245 //====================================================================
246 #ifdef ENABLE_MULTI_INSTANCE
247 
248 int Communicator_impl::sync_global()
249 {
250  LOG;
251  return MPI_Barrier(MPI_COMM_WORLD);
252 }
253 
254 
255 #endif
256 
257 //====================================================================
258 // data transfer: base cases
259 int Communicator_impl::Base::broadcast(size_t size, void *data, int sender)
260 {
261  LOG;
262  return MPI_Bcast(data, size, MPI_BYTE, sender, m_comm);
263 }
264 
265 
266 //====================================================================
267 int Communicator_impl::Base::exchange(size_t size, void *recv_buf, void *send_buf, int idir, int ipm, int itag)
268 {
269  LOG;
270 
271  MPI_Status status;
272  int p_send, p_recv;
273 
274  assert(ipm == 1 || ipm == -1);
275 
276  if (Layout::m_grid_dims[idir] == 1) { // no need to transfer
277  memcpy(recv_buf, send_buf, size);
278  return EXIT_SUCCESS;
279  }
280 
281  if (ipm == 1) { // downward shift
282  p_send = Layout::m_ipe_dn[idir];
283  p_recv = Layout::m_ipe_up[idir];
284  } else { // upward shift
285  p_send = Layout::m_ipe_up[idir];
286  p_recv = Layout::m_ipe_dn[idir];
287  }
288 
289  int tag_send = Layout::tag(self(), idir, -ipm);
290  int tag_recv = Layout::tag(p_recv, idir, -ipm);
291 
292  return MPI_Sendrecv(
293  send_buf, size, MPI_BYTE, p_send, tag_send,
294  recv_buf, size, MPI_BYTE, p_recv, tag_recv,
295  m_comm, &status);
296 }
297 
298 
299 //====================================================================
300 int Communicator_impl::Base::send_1to1(size_t size, void *recv_buf, void *send_buf, int send_to, int recv_from, int tag)
301 {
302  LOG;
303 
304  MPI_Status status;
305 
306  if (send_to == recv_from) {
307  memcpy(recv_buf, send_buf, size);
308  } else {
309  if (self() == recv_from)
310  MPI_Send(send_buf, size, MPI_BYTE, send_to, tag, m_comm);
311 
312  if (self() == send_to)
313  MPI_Recv(recv_buf, size, MPI_BYTE, recv_from, tag, m_comm, &status);
314  }
315 
316  // sync should be taken outside.
317 
318  return EXIT_SUCCESS;
319 }
320 
321 
322 //====================================================================
323 int Communicator_impl::Base::reduce(int count, void *recv_buf, void *send_buf, MPI_Datatype type, MPI_Op op, int pattern)
324 {
325  LOG;
326  return MPI_Allreduce((void *)send_buf, (void *)recv_buf, count, type, op, Layout::m_sub_comm[pattern]);
327 }
328 
329 
330 //====================================================================
331 // data transfer for specific datatypes
332 int Communicator_impl::broadcast_string(int count, string& data, int sender)
333 {
334  LOG;
335  assert(count == 1);
336 
337  size_t size = 0;
338 
339  // broadcast string length.
340  if (Communicator::self() == sender) {
341  size = data.size();
342  }
343  MPI_Bcast((void *)&size, sizeof(size_t), MPI_BYTE, sender, m_comm);
344 
345  // allocate buffer. pack data at sender.
346  char *buf = new char[size + 1];
347  memset(buf, '\0', size + 1);
348 
349  if (Communicator::self() == sender) {
350  data.copy(buf, size, 0);
351  }
352 
353  // do broadcast.
354  int retv = MPI_Bcast((void *)buf, size, MPI_BYTE, sender, m_comm);
355 
356  if (Communicator::self() != sender) {
357  data = string(buf);
358  }
359 
360  delete [] buf;
361 
362  return retv;
363 }
364 
365 
366 //====================================================================
367 // info
369 {
370  return MPI_Wtime();
371 }
372 
373 
374 //====================================================================
375 // debug
377 {
378 #ifdef DEBUG
379 #ifdef ENABLE_MULTI_INSTANCE
380  printf("global_rank=%2d/%2d: ngrid=%d, grid_id=%d: grid_rank=%2d/%2d\n",
381  m_global_rank, m_global_size,
382  m_Ninstance, m_instance_id,
384 #else
385  printf("grid_rank=%2d/%2d\n",
387 #endif
388 #endif
389 
390 
391  return EXIT_SUCCESS;
392 }
393 
394 
395 //====================================================================
396 //============================================================END=====
Communicator_impl::Base::reduce
static int reduce(int count, void *recv_buf, void *send_buf, MPI_Datatype type, MPI_Op op, int pattern)
Definition: communicator_mpi.cpp:323
Communicator_impl::Layout::m_ipe_dn
static int * m_ipe_dn
rank of downward neighbour in directions.
Definition: layout.h:54
Communicator_impl::m_grid_size
static int m_grid_size
Definition: communicator_mpi.h:110
layout.h
Communicator_impl::Layout::m_sub_comm
static MPI_Comm * m_sub_comm
subgrid
Definition: layout.h:64
Communicator_impl::Layout::tag
static int tag(int rank, int idir, int ipm)
generate tag for communication.
Definition: layout.cpp:68
Communicator::self
static int self()
rank within small world.
Definition: communicator.cpp:74
Communicator_impl::Layout::layout_setup
static int layout_setup()
initialise layout.
Definition: layout.cpp:93
Communicator_impl::setup
static int setup(int Ninstance=1)
Definition: communicator_mpi.cpp:86
default_handler
static std::terminate_handler default_handler
Definition: communicator_mpi.cpp:18
Communicator_impl::sync
static int sync()
Definition: communicator_mpi.cpp:216
Communicator_impl::Base::send_1to1
static int send_1to1(size_t size, void *recv_buf, void *send_buf, int send_to, int recv_from, int tag)
Definition: communicator_mpi.cpp:300
Communicator_impl::status
static int status()
Definition: communicator_mpi.cpp:376
Communicator_impl::abort
static void abort()
Definition: communicator_mpi.cpp:159
Communicator_impl::self
static int self()
Definition: communicator_mpi.cpp:176
Communicator_impl::Base::broadcast
static int broadcast(size_t size, void *data, int sender)
Definition: communicator_mpi.cpp:259
Communicator_impl::init
static int init(int *pargc, char ***pargv)
Definition: communicator_mpi.cpp:38
Communicator::abort
static void abort()
terminate communicator
Definition: communicator.cpp:36
Communicator_impl::m_comm
static MPI_Comm m_comm
Definition: communicator_mpi.h:112
Communicator_impl::Layout::m_grid_dims
static int * m_grid_dims
grid dimensions in directions.
Definition: layout.h:50
Communicator_impl::m_grid_rank
static int m_grid_rank
Definition: communicator_mpi.h:109
Communicator_impl::get_time
static double get_time()
Definition: communicator_mpi.cpp:368
Communicator_impl::default_grid_map
static char default_grid_map[16]
Definition: communicator_mpi.h:114
Communicator_impl::Base::exchange
static int exchange(size_t size, void *recv_buf, void *send_buf, int idir, int ipm, int tag)
Definition: communicator_mpi.cpp:267
Communicator_impl::finalize
static int finalize()
Definition: communicator_mpi.cpp:78
Communicator_impl::is_primary
static bool is_primary()
Definition: communicator_mpi.cpp:169
Communicator_impl::sync_usleep
static int sync_usleep()
Definition: communicator_mpi.cpp:225
LOG
#define LOG
Definition: bridge_defs.h:21
Communicator_impl::size
static int size()
Definition: communicator_mpi.cpp:183
Communicator_impl::broadcast_string
static int broadcast_string(int count, string &data, int sender)
Definition: communicator_mpi.cpp:332
Communicator_impl::Layout::m_ipe_up
static int * m_ipe_up
rank of upward neighbour in directions.
Definition: layout.h:53
Element_type::type
type
Definition: bridge_defs.h:41