Bridge++  Version 1.4.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 
19 // define static members
20 #ifdef ENABLE_MULTI_INSTANCE
21 int Communicator_impl::m_n_instance = 1; // number of instances
22 int Communicator_impl::m_instance_id = 0; // id of present instance
23 #endif
24 
25 int Communicator_impl::m_global_rank = 0;
26 int Communicator_impl::m_global_size = 1;
27 
30 
32 
33 //====================================================================
34 // class methods
35 int Communicator_impl::init(int *pargc, char ***pargv)
36 {
37  LOG;
38 
39  int is_initialized = 0;
40  MPI_Initialized(&is_initialized);
41 
42  if (is_initialized) {
43  fprintf(stderr, "Communicator: MPI already initialized. skip.\n");
44  } else {
45 #ifdef USE_OPENMP
46  int required = MPI_THREAD_FUNNELED;
47  int provided;
48 
49  MPI_Init_thread(pargc, pargv, required, &provided);
50 
51  if (provided < required) {
52  fprintf(stderr, "Communicator: MPI not supporting sufficient thread level. exiting.\n");
53  exit(EXIT_FAILURE);
54  }
55 #else
56  MPI_Init(pargc, pargv);
57 #endif
58  }
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 #else
100 // m_n_instance = 1;
101 // m_instance_id = 0;
102 
103  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
104 #endif
105 
106  MPI_Comm_size(m_comm, &m_grid_size);
107  MPI_Comm_rank(m_comm, &m_grid_rank);
108 
110 
111  status();
112 
113  return EXIT_SUCCESS;
114 }
115 
116 
117 //====================================================================
119 {
120  LOG;
121  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
122  // unreached.
123 }
124 
125 
126 //====================================================================
127 // information
129 {
130  return m_grid_rank == 0;
131 }
132 
133 
134 //====================================================================
136 {
137  return m_grid_rank;
138 }
139 
140 
141 //====================================================================
143 {
144  return m_grid_size;
145 }
146 
147 
148 //====================================================================
149 bool Communicator_impl::is_primary_master()
150 {
151  return m_global_rank == 0;
152 }
153 
154 
155 //====================================================================
156 #ifdef ENABLE_MULTI_INSTANCE
157 
158 int Communicator_impl::self_global()
159 {
160  return m_global_rank;
161 }
162 
163 
164 //====================================================================
165 int Communicator_impl::world_id()
166 {
167  return m_instance_id;
168 }
169 #endif
170 
171 //====================================================================
172 // synchronize
174 {
175  LOG;
176  return MPI_Barrier(m_comm);
177 }
178 
179 
180 //====================================================================
181 #ifdef ENABLE_MULTI_INSTANCE
182 
183 int Communicator_impl::sync_global()
184 {
185  LOG;
186  return MPI_Barrier(MPI_COMM_WORLD);
187 }
188 #endif
189 
190 //====================================================================
191 // data transfer: base cases
192 int Communicator_impl::Base::broadcast(size_t size, void *data, int sender)
193 {
194  LOG;
195  return MPI_Bcast(data, size, MPI_BYTE, sender, m_comm);
196 }
197 
198 
199 //====================================================================
200 int Communicator_impl::Base::exchange(size_t size, void *recv_buf, void *send_buf, int idir, int ipm, int itag)
201 {
202  LOG;
203 
204  MPI_Status status;
205  int p_send, p_recv;
206 
207  assert(ipm == 1 || ipm == -1);
208 
209  if (Layout::m_grid_dims[idir] == 1) { // no need to transfer
210  memcpy(recv_buf, send_buf, size);
211  return EXIT_SUCCESS;
212  }
213 
214  if (ipm == 1) { // downward shift
215  p_send = Layout::m_ipe_dn[idir];
216  p_recv = Layout::m_ipe_up[idir];
217  } else { // upward shift
218  p_send = Layout::m_ipe_up[idir];
219  p_recv = Layout::m_ipe_dn[idir];
220  }
221 
222  int tag_send = Layout::tag(self(), idir, -ipm);
223  int tag_recv = Layout::tag(p_recv, idir, -ipm);
224 
225  return MPI_Sendrecv(
226  send_buf, size, MPI_BYTE, p_send, tag_send,
227  recv_buf, size, MPI_BYTE, p_recv, tag_recv,
228  m_comm, &status);
229 }
230 
231 
232 //====================================================================
233 int Communicator_impl::Base::send_1to1(size_t size, void *recv_buf, void *send_buf, int send_to, int recv_from, int tag)
234 {
235  LOG;
236 
237  MPI_Status status;
238 
239  if (send_to == recv_from) {
240  memcpy(recv_buf, send_buf, size);
241  } else {
242  if (self() == recv_from)
243  MPI_Send(send_buf, size, MPI_BYTE, send_to, tag, m_comm);
244 
245  if (self() == send_to)
246  MPI_Recv(recv_buf, size, MPI_BYTE, recv_from, tag, m_comm, &status);
247  }
248 
249  // sync should be taken outside.
250 
251  return EXIT_SUCCESS;
252 }
253 
254 
255 //====================================================================
256 int Communicator_impl::Base::reduce(int count, void *recv_buf, void *send_buf, MPI_Datatype type, MPI_Op op, int pattern)
257 {
258  LOG;
259  return MPI_Allreduce((void *)send_buf, (void *)recv_buf, count, type, op, Layout::m_sub_comm[pattern]);
260 }
261 
262 
263 //====================================================================
264 // data transfer for specific datatypes
265 int Communicator_impl::broadcast_string(int count, string& data, int sender)
266 {
267  LOG;
268  assert(count == 1);
269 
270  size_t size = 0;
271 
272  // broadcast string length.
273  if (Communicator::self() == sender) {
274  size = data.size();
275  }
276  MPI_Bcast((void *)&size, sizeof(size_t), MPI_BYTE, sender, m_comm);
277 
278  // allocate buffer. pack data at sender.
279  char *buf = new char[size + 1];
280  memset(buf, '\0', size + 1);
281 
282  if (Communicator::self() == sender) {
283  data.copy(buf, size, 0);
284  }
285 
286  // do broadcast.
287  int retv = MPI_Bcast((void *)buf, size, MPI_BYTE, sender, m_comm);
288 
289  if (Communicator::self() != sender) {
290  data = string(buf);
291  }
292 
293  delete [] buf;
294 
295  return retv;
296 }
297 
298 
299 //====================================================================
300 // info
302 {
303  return MPI_Wtime();
304 }
305 
306 
307 //====================================================================
308 // debug
310 {
311 #ifdef DEBUG
312 #ifdef ENABLE_MULTI_INSTANCE
313  printf("global_rank=%2d/%2d: ngrid=%d, grid_id=%d: grid_rank=%2d/%2d\n",
314  m_global_rank, m_global_size,
315  m_n_instance, m_instance_id,
317 #else
318  printf("grid_rank=%2d/%2d\n",
320 #endif
321 #endif
322 
323 
324  return EXIT_SUCCESS;
325 }
326 
327 
328 //====================================================================
329 //============================================================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