Bridge++  Version 1.4.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 
32 #include "IO/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 // 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 
54 // class methods
55 //====================================================================
56 int Communicator_impl::init(int *pargc, char ***pargv)
57 {
58  LOG;
59 
60 #ifdef USE_MPI
61  int required = MPI_THREAD_FUNNELED;
62  int provided;
63  MPI_Init_thread(pargc, pargv, required, &provided);
64  if (provided < required) {
65  fprintf(stderr,
66  "MPI implementation provides insufficient threading support.\n"
67  "required = %d, provided = %d : (SINGLE, FUNNELED, SERIALIZED, MULT\
68 IPLE) = (%d, %d, %d, %d)\n",
69  required, provided,
70  MPI_THREAD_SINGLE,
71  MPI_THREAD_FUNNELED,
72  MPI_THREAD_SERIALIZED,
73  MPI_THREAD_MULTIPLE);
74  abort();
75  }
76  MPI_Barrier(MPI_COMM_WORLD);
77 #endif
78 
79  // BGNET
80  BGNET_Init();
81 
82  m_global_size = BGNET_Procs();
83  m_global_rank = BGNET_Rank();
84 
85  // grid size and rank equal to global ones for a moment until layout is set.
86  m_grid_size = m_global_size;
87  m_grid_rank = m_global_rank;
88 
89  return EXIT_SUCCESS;
90 }
91 
92 
93 //====================================================================
95 {
96  LOG;
97 
98 #ifdef USE_MPI
99  MPI_Finalize();
100 #endif
101 
102  return EXIT_SUCCESS;
103 }
104 
105 
106 //====================================================================
107 int Communicator_impl::setup(int ninstance)
108 {
109  LOG;
110 
111 #ifdef ENABLE_MULTI_INSTANCE
112  if ((ninstance == 0) || (m_global_size % ninstance != 0)) {
113  printf("%s: invalid number of instance: %d\n", "Communicator::init", ninstance);
114  abort();
115  }
116 
117  if (ninstance != 1) {
118  printf("%s: sorry, multi-instance is disabled.\n", "Communicator::init");
119  abort();
120  }
121 
122  m_n_instance = ninstance;
123 
124  int gsize = m_global_size / ninstance;
125  m_instance_id = m_global_rank / gsize;
126 #else
127  m_n_instance = 1;
128  m_instance_id = 0;
129 #endif
130 
131  m_grid_size = m_global_size;
132  m_grid_rank = m_global_rank;
133 
135 
136  status();
137 
138  // BGNET parameters
139  int N_send_buf = BGNET_GetNumInjBuffer();
140  int N_fifo = BGNET_GetNumInjFIFO();
141  int N_recv_buf = BGNET_GetNumRecBuffer();
142  int N_group = BGNET_GetNumGroup();
143  int N_counter = BGNET_GetNumRecCounter();
144 
146  vout.general(vl, "BGNET parameters:\n");
147  vout.general(vl, " Number of send buffer: %d\n", N_send_buf);
148  vout.general(vl, " Number of recv buffer: %d\n", N_recv_buf);
149  vout.general(vl, " Number of fifo: %d\n", N_fifo);
150  vout.general(vl, " Number of group: %d\n", N_group);
151  vout.general(vl, " Number of counter: %d\n", N_counter);
152 
153  return EXIT_SUCCESS;
154 }
155 
156 
157 //====================================================================
159 {
160  LOG;
161 
162 #ifdef USE_MPI
163  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
164 #endif
165 
166  abort();
167 
168  // unreached.
169 }
170 
171 
172 // information
173 //====================================================================
175 {
176  return m_grid_rank == 0;
177 }
178 
179 
180 //====================================================================
182 {
183  return m_grid_rank;
184 }
185 
186 
187 //====================================================================
189 {
190  return m_grid_size;
191 }
192 
193 
194 //====================================================================
195 bool Communicator_impl::is_primary_master()
196 {
197  return m_global_rank == 0;
198 }
199 
200 
201 #ifdef ENABLE_MULTI_INSTANCE
202 //====================================================================
203 int Communicator_impl::self_global()
204 {
205  return m_global_rank;
206 }
207 
208 
209 //====================================================================
210 int Communicator_impl::world_id()
211 {
212  return m_instance_id;
213 }
214 #endif
215 
216 // synchronize
217 //====================================================================
219 {
220  LOG;
221  BGNET_GlobalBarrier();
222  return 0;
223 }
224 
225 
226 #ifdef ENABLE_MULTI_INSTANCE
227 //====================================================================
228 int Communicator_impl::sync_global()
229 {
230  LOG;
231  BGNET_GlobalBarrier();
232 
233  return 0;
234 }
235 #endif
236 
237 // data transfer: base cases
238 //====================================================================
239 int Communicator_impl::Base::broadcast(size_t count, void *data, int sender)
240 {
241  LOG;
242  BGNET_BCast(data, count, BGNET_COLLECTIVE_BYTE, sender,
243  BGNET_COMM_WORLD);
244 
245  return 0;
246 }
247 
248 
249 //====================================================================
251  void *recv_buf, void *send_buf,
252  int idir, int ipm, int itag)
253 {
254  LOG;
255 
256  // MPI_Status status;
257  int p_send, p_recv;
258 
259  assert(ipm == 1 || ipm == -1);
260 
261  if (Layout::m_grid_dims[idir] == 1) { // no need to transfer
262  memcpy(recv_buf, send_buf, size);
263  return EXIT_SUCCESS;
264  }
265 
266  if (ipm == 1) { // downward shift
267  p_send = Layout::m_ipe_dn[idir];
268  p_recv = Layout::m_ipe_up[idir];
269  } else { // upward shift
270  p_send = Layout::m_ipe_up[idir];
271  p_recv = Layout::m_ipe_dn[idir];
272  }
273 
274  int tag_send = Layout::tag(self(), idir, -ipm);
275  int tag_recv = Layout::tag(p_recv, idir, -ipm);
276 
277  return BGNET_Sendrecv(0, send_buf, size, p_send, recv_buf, size, p_recv);
278  // return BGNET_Sendrecv(itag,send_buf,size,p_send,recv_buf,size,p_recv);
279 }
280 
281 
282 //====================================================================
284  void *recv_buf, void *send_buf,
285  int send_to, int recv_from, int tag)
286 {
287  LOG;
288 
289  /*
290  MPI_Status status;
291 
292  if (send_to == recv_from) {
293 
294  memcpy(recv_buf, send_buf, size);
295 
296  } else {
297 
298  if (self() == recv_from)
299  MPI_Send(send_buf, size, MPI_BYTE, send_to, tag, MPI_COMM_WORLD);
300 
301  if (self() == send_to)
302  MPI_Recv(recv_buf, size, MPI_BYTE, recv_from, tag, MPI_COMM_WORLD, &status);
303 
304  };
305  */
306 
307  if (send_to == recv_from) {
308  memcpy(recv_buf, send_buf, size);
309  } else {
310  if (self() == recv_from)
311  BGNET_Send(0, send_buf, size, send_to);
312 
313  if (self() == send_to)
314  BGNET_Recv(0, recv_buf, size, recv_from);
315  }
316 
317 
318  // sync should be taken outside.
319 
320  return EXIT_SUCCESS;
321 }
322 
323 
324 //====================================================================
326  void *recv_buf, void *send_buf,
327  int type, int op, int pComm)
328 {
329  LOG;
330 
331  BGNET_AllReduce(send_buf, recv_buf, count, type, op, BGNET_COMM_WORLD);
332 
333  return EXIT_SUCCESS;
334 }
335 
336 
337 // data transfer for specific datatypes
338 //====================================================================
339 int Communicator_impl::broadcast_double(int count, double *data,
340  int sender)
341 {
342  LOG;
343 
344  BGNET_BCast(data, count, BGNET_COLLECTIVE_DOUBLE, sender,
345  BGNET_COMM_WORLD);
346 
347  return EXIT_SUCCESS;
348 }
349 
350 
351 //====================================================================
352 int Communicator_impl::broadcast_int(int count, int *data, int sender)
353 {
354  LOG;
355 
356  BGNET_BCast(data, count, BGNET_COLLECTIVE_INT32, sender,
357  BGNET_COMM_WORLD);
358 
359  return EXIT_SUCCESS;
360 }
361 
362 
363 //====================================================================
364 int Communicator_impl::broadcast_string(int count, string& data,
365  int sender)
366 {
367  LOG;
368  assert(count == 1);
369 
370  size_t size = 0;
371 
372  // broadcast string length.
373  if (Communicator::self() == sender) {
374  size = data.size();
375  }
376 
377  if (sizeof(size_t) == 4) {
378  BGNET_BCast(&size, 1, BGNET_COLLECTIVE_INT32, sender,
379  BGNET_COMM_WORLD);
380  } else if (sizeof(size_t) == 8) {
381  BGNET_BCast(&size, 1, BGNET_COLLECTIVE_INT64, sender,
382  BGNET_COMM_WORLD);
383  } else {
384  abort();
385  }
386 
387  // allocate buffer. pack data at sender.
388 
389  /*
390  char *buf = new char[size+1];
391  memset(buf, '\0', size+1);
392  */
393  int size2 = (size + 1) / 4;
394  if ((size + 1) % 4 != 0) size2 += 1;
395  size2 *= 4;
396  char *buf = new char[size2];
397  memset(buf, '\0', size2);
398 
399 
400  if (Communicator::self() == sender) {
401  data.copy(buf, size, 0);
402  }
403 
404  // do broadcast.
405  // int retv = MPI_Bcast((void*)buf, size, MPI_BYTE, sender, m_comm);
406  BGNET_BCast((int *)buf, size2 / 4, BGNET_COLLECTIVE_INT32, sender,
407  BGNET_COMM_WORLD);
408 
409  if (Communicator::self() != sender) {
410  //data = string(buf);
411  data.assign(buf, size);
412  }
413 
414  delete [] buf;
415 
416  // return retv;
417  return EXIT_SUCCESS;
418 }
419 
420 
421 // info
422 //====================================================================
424 {
425  uint64_t clock = GetTimeBase();
426  double dtime = clock / CLOCKRATE;
427 
428  return dtime;
429 }
430 
431 
432 // debug
433 //====================================================================
435 {
436 #ifdef DEBUG
437 #ifdef ENABLE_MULTI_INSTANCE
438  printf("global_rank=%2d/%2d: ngrid=%d, grid_id=%d: grid_rank=%2d/%2d\n",
439  m_global_rank, m_global_size,
440  m_n_instance, m_instance_id,
442 #else
443  printf("grid_rank=%2d/%2d\n",
445 #endif
446 #endif
447 
448  return EXIT_SUCCESS;
449 }
450 
451 
452 //====================================================================
453 //============================================================END=====
BridgeIO vout
Definition: bridgeIO.cpp:495
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:195
#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:42
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)