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