Bridge++  Ver. 1.3.x
communicator_bgnet.cpp
Go to the documentation of this file.
1 
14 #include "communicator_bgnet.h"
15 
16 #include <cstdarg>
17 #include <cstring>
18 
19 #ifdef USE_MPI
20 #include <mpi.h>
21 #endif
22 
23 // BGNET: for Blue Gene/Q
24 #include <hwi/include/bqc/A2_inlines.h>
25 #define CLOCKRATE 1.6e9;
26 // This is temporary setting and valid only for BG/Q.
27 // If the system provide corresponding constant, to be replaced.
28 
29 #include "layout.h"
30 
31 #include "commonParameters.h"
32 #include "bridgeIO.h"
33 using Bridge::vout;
34 
35 // exception handler for uncaught throw.
36 static std::terminate_handler default_handler = std::set_terminate(Communicator::abort);
37 
38 // override built-in abort function
39 #if 0
40 extern "C" {
41 void abort()
42 {
43  fprintf(stderr, "abort() called. terminate.\n");
45 }
46 }
47 #endif
48 
49 // define static members
50 #ifdef ENABLE_MULTI_INSTANCE
51 int Communicator_impl::m_n_instance = 1; // number of instances
52 int Communicator_impl::m_instance_id = 0; // id of present instance
53 #endif
54 
55 int Communicator_impl::m_global_rank = 0;
56 int Communicator_impl::m_global_size = 1;
57 
60 
62 
63 //----------------------------------------------------------------
64 
65 // class methods
66 //====================================================================
67 int Communicator_impl::init(int *pargc, char ***pargv)
68 {
69  LOG;
70 
71 #ifdef USE_MPI
72  int required = MPI_THREAD_FUNNELED;
73  int provided;
74  MPI_Init_thread(pargc, pargv, required, &provided);
75  if (provided < required) {
76  fprintf(stderr,
77  "MPI implementation provides insufficient threading support.\n"
78  "required = %d, provided = %d : (SINGLE, FUNNELED, SERIALIZED, MULT\
79 IPLE) = (%d, %d, %d, %d)\n",
80  required, provided,
81  MPI_THREAD_SINGLE,
82  MPI_THREAD_FUNNELED,
83  MPI_THREAD_SERIALIZED,
84  MPI_THREAD_MULTIPLE);
85  abort();
86  }
87  MPI_Barrier(MPI_COMM_WORLD);
88 #endif
89 
90  // BGNET
91  BGNET_Init();
92 
93  m_global_size = BGNET_Procs();
94  m_global_rank = BGNET_Rank();
95 
96  // grid size and rank equal to global ones for a moment until layout is set.
97  m_grid_size = m_global_size;
98  m_grid_rank = m_global_rank;
99 
100  return EXIT_SUCCESS;
101 }
102 
103 
104 //====================================================================
106 {
107  LOG;
108 
109 #ifdef USE_MPI
110  MPI_Finalize();
111 #endif
112 
113  return EXIT_SUCCESS;
114 }
115 
116 
117 //====================================================================
118 int Communicator_impl::setup(int ninstance)
119 {
120  LOG;
121 
122 #ifdef ENABLE_MULTI_INSTANCE
123  if ((ninstance == 0) || (m_global_size % ninstance != 0)) {
124  printf("%s: invalid number of instance: %d\n", "Communicator::init", ninstance);
125  abort();
126  }
127 
128  if (ninstance != 1) {
129  printf("%s: sorry, multi-instance is disabled.\n", "Communicator::init");
130  abort();
131  }
132 
133  m_n_instance = ninstance;
134 
135  int gsize = m_global_size / ninstance;
136  m_instance_id = m_global_rank / gsize;
137 
138 #else
139  m_n_instance = 1;
140  m_instance_id = 0;
141 #endif
142 
143  m_grid_size = m_global_size;
144  m_grid_rank = m_global_rank;
145 
147 
148  status();
149 
150  // BGNET parameters
151  int N_send_buf = BGNET_GetNumInjBuffer();
152  int N_fifo = BGNET_GetNumInjFIFO();
153  int N_recv_buf = BGNET_GetNumRecBuffer();
154  int N_group = BGNET_GetNumGroup();
155  int N_counter = BGNET_GetNumRecCounter();
156 
158  vout.general(vl, "BGNET parameters:\n");
159  vout.general(vl, " Number of send buffer: %d\n", N_send_buf);
160  vout.general(vl, " Number of recv buffer: %d\n", N_recv_buf);
161  vout.general(vl, " Number of fifo: %d\n", N_fifo);
162  vout.general(vl, " Number of group: %d\n", N_group);
163  vout.general(vl, " Number of counter: %d\n", N_counter);
164 
165  return EXIT_SUCCESS;
166 }
167 
168 
169 //====================================================================
171 {
172  LOG;
173 
174 #ifdef USE_MPI
175  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
176 #endif
177 
178  abort();
179 
180  // unreached.
181 }
182 
183 
184 // information
185 //====================================================================
187 {
188  return m_grid_rank == 0;
189 }
190 
191 
192 //====================================================================
194 {
195  return m_grid_rank;
196 }
197 
198 
199 //====================================================================
201 {
202  return m_grid_size;
203 }
204 
205 
206 //====================================================================
207 bool Communicator_impl::is_primary_master()
208 {
209  return m_global_rank == 0;
210 }
211 
212 
213 #ifdef ENABLE_MULTI_INSTANCE
214 //====================================================================
215 int Communicator_impl::self_global()
216 {
217  return m_global_rank;
218 }
219 
220 
221 //====================================================================
222 int Communicator_impl::world_id()
223 {
224  return m_instance_id;
225 }
226 #endif
227 
228 // synchronize
229 //====================================================================
231 {
232  LOG;
233  BGNET_GlobalBarrier();
234  return 0;
235 }
236 
237 
238 #ifdef ENABLE_MULTI_INSTANCE
239 //====================================================================
240 int Communicator_impl::sync_global()
241 {
242  LOG;
243  BGNET_GlobalBarrier();
244 
245  return 0;
246 }
247 #endif
248 
249 // data transfer: base cases
250 //====================================================================
251 int Communicator_impl::Base::broadcast(size_t count, void *data, int sender)
252 {
253  LOG;
254  BGNET_BCast(data, count, BGNET_COLLECTIVE_BYTE, sender,
255  BGNET_COMM_WORLD);
256 
257  return 0;
258 }
259 
260 
261 //====================================================================
263  void *recv_buf, void *send_buf,
264  int idir, int ipm, int itag)
265 {
266  LOG;
267 
268  // MPI_Status status;
269  int p_send, p_recv;
270 
271  assert(ipm == 1 || ipm == -1);
272 
273  if (Layout::m_grid_dims[idir] == 1) { // no need to transfer
274  memcpy(recv_buf, send_buf, size);
275  return EXIT_SUCCESS;
276  }
277 
278  if (ipm == 1) { // downward shift
279  p_send = Layout::m_ipe_dn[idir];
280  p_recv = Layout::m_ipe_up[idir];
281  } else { // upward shift
282  p_send = Layout::m_ipe_up[idir];
283  p_recv = Layout::m_ipe_dn[idir];
284  }
285 
286  int tag_send = Layout::tag(self(), idir, -ipm);
287  int tag_recv = Layout::tag(p_recv, idir, -ipm);
288 
289  return BGNET_Sendrecv(0, send_buf, size, p_send, recv_buf, size, p_recv);
290  // return BGNET_Sendrecv(itag,send_buf,size,p_send,recv_buf,size,p_recv);
291 }
292 
293 
294 //====================================================================
296  void *recv_buf, void *send_buf,
297  int send_to, int recv_from, int tag)
298 {
299  LOG;
300 
301  /*
302  MPI_Status status;
303 
304  if (send_to == recv_from) {
305 
306  memcpy(recv_buf, send_buf, size);
307 
308  } else {
309 
310  if (self() == recv_from)
311  MPI_Send(send_buf, size, MPI_BYTE, send_to, tag, MPI_COMM_WORLD);
312 
313  if (self() == send_to)
314  MPI_Recv(recv_buf, size, MPI_BYTE, recv_from, tag, MPI_COMM_WORLD, &status);
315 
316  };
317  */
318 
319  if (send_to == recv_from) {
320  memcpy(recv_buf, send_buf, size);
321  } else {
322  if (self() == recv_from)
323  BGNET_Send(0, send_buf, size, send_to);
324 
325  if (self() == send_to)
326  BGNET_Recv(0, recv_buf, size, recv_from);
327  }
328 
329 
330  // sync should be taken outside.
331 
332  return EXIT_SUCCESS;
333 }
334 
335 
336 //====================================================================
338  void *recv_buf, void *send_buf,
339  int type, int op, int pComm)
340 {
341  LOG;
342 
343  BGNET_AllReduce(send_buf, recv_buf, count, type, op, BGNET_COMM_WORLD);
344 
345  return EXIT_SUCCESS;
346 }
347 
348 
349 // data transfer for specific datatypes
350 //====================================================================
351 int Communicator_impl::broadcast_double(int count, double *data,
352  int sender)
353 {
354  LOG;
355 
356  BGNET_BCast(data, count, BGNET_COLLECTIVE_DOUBLE, sender,
357  BGNET_COMM_WORLD);
358 
359  return EXIT_SUCCESS;
360 }
361 
362 
363 //====================================================================
364 int Communicator_impl::broadcast_int(int count, int *data, int sender)
365 {
366  LOG;
367 
368  BGNET_BCast(data, count, BGNET_COLLECTIVE_INT32, sender,
369  BGNET_COMM_WORLD);
370 
371  return EXIT_SUCCESS;
372 }
373 
374 
375 //====================================================================
376 int Communicator_impl::broadcast_string(int count, string& data,
377  int sender)
378 {
379  LOG;
380  assert(count == 1);
381 
382  size_t size = 0;
383 
384  // broadcast string length.
385  if (Communicator::self() == sender) {
386  size = data.size();
387  }
388 
389  if (sizeof(size_t) == 4) {
390  BGNET_BCast(&size, 1, BGNET_COLLECTIVE_INT32, sender,
391  BGNET_COMM_WORLD);
392  } else if (sizeof(size_t) == 8) {
393  BGNET_BCast(&size, 1, BGNET_COLLECTIVE_INT64, sender,
394  BGNET_COMM_WORLD);
395  } else {
396  abort();
397  }
398 
399  // allocate buffer. pack data at sender.
400 
401  /*
402  char *buf = new char[size+1];
403  memset(buf, '\0', size+1);
404  */
405  int size2 = (size + 1) / 4;
406  if ((size + 1) % 4 != 0) size2 += 1;
407  size2 *= 4;
408  char *buf = new char[size2];
409  memset(buf, '\0', size2);
410 
411 
412  if (Communicator::self() == sender) {
413  data.copy(buf, size, 0);
414  }
415 
416  // do broadcast.
417  // int retv = MPI_Bcast((void*)buf, size, MPI_BYTE, sender, m_comm);
418  BGNET_BCast((int *)buf, size2 / 4, BGNET_COLLECTIVE_INT32, sender,
419  BGNET_COMM_WORLD);
420 
421  if (Communicator::self() != sender) {
422  //data = string(buf);
423  data.assign(buf, size);
424  }
425 
426  delete [] buf;
427 
428  // return retv;
429  return EXIT_SUCCESS;
430 }
431 
432 
433 // info
434 //====================================================================
436 {
437  uint64_t clock = GetTimeBase();
438  double dtime = clock / CLOCKRATE;
439 
440  return dtime;
441 }
442 
443 
444 // debug
445 //====================================================================
447 {
448 #ifdef DEBUG
449 #ifdef ENABLE_MULTI_INSTANCE
450  printf("global_rank=%2d/%2d: ngrid=%d, grid_id=%d: grid_rank=%2d/%2d\n",
451  m_global_rank, m_global_size,
452  m_n_instance, m_instance_id,
454 
455 #else
456  printf("grid_rank=%2d/%2d\n",
458 #endif
459 #endif
460 
461  return EXIT_SUCCESS;
462 }
463 
464 
465 //====================================================================
466 //============================================================END=====
BridgeIO vout
Definition: bridgeIO.cpp:278
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.
static int broadcast_double(int count, double *data, int sender)
void general(const char *format,...)
Definition: bridgeIO.cpp:65
#define LOG
Definition: defs.h:21
static Bridge::VerboseLevel Vlevel()
static int sync()
synchronize within small world.
static int setup(int ninstance=1)
static int status()
for debug
#define CLOCKRATE
static int broadcast_int(int count, int *data, int sender)
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_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 std::terminate_handler default_handler
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
Bridge::VerboseLevel vl
Definition: checker.cpp:18
VerboseLevel
Definition: bridgeIO.h:39
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)