Bridge++  Ver. 1.2.x
 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 // static const char rcsid[] = "$Id: communicator_mpi.cpp 1145 2014-09-16 09:27:22Z namekawa $";
17 
18 // exception handler for uncaught throw.
19 static std::terminate_handler default_handler = std::set_terminate(Communicator::abort);
20 
22 
30 #if 0
31 extern "C" {
32 void abort()
33 {
34  fprintf(stderr, "abort() called. terminate.\n");
36 }
37 }
38 #endif
39 
40 // define static members
41 #ifdef ENABLE_MULTI_INSTANCE
42 int Communicator_impl::m_n_instance = 1; // number of instances
43 int Communicator_impl::m_instance_id = 0; // id of present instance
44 #endif
45 
46 int Communicator_impl::m_global_rank = 0;
47 int Communicator_impl::m_global_size = 1;
48 
51 
53 
54 //----------------------------------------------------------------
55 
56 // class methods
57 int Communicator_impl::init(int *pargc, char ***pargv)
58 {
59  LOG;
60 
61  MPI_Init(pargc, pargv);
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 
78 {
79  LOG;
80  return MPI_Finalize();
81 }
82 
83 
84 int Communicator_impl::setup(int ninstance)
85 {
86  LOG;
87 
88 #ifdef ENABLE_MULTI_INSTANCE
89  if ((ninstance == 0) || (m_global_size % ninstance != 0)) {
90  printf("%s: invalid number of instance: %d\n", "Communicator::init", ninstance);
91  abort();
92  }
93 
94  m_n_instance = ninstance;
95 
96  int gsize = m_global_size / ninstance;
97  m_instance_id = m_global_rank / gsize;
98 
99  MPI_Comm_split(MPI_COMM_WORLD, m_instance_id, 0 /* key */, &m_comm);
100 
101 #else
102 // m_n_instance = 1;
103 // m_instance_id = 0;
104 
105  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
106 #endif
107 
108  MPI_Comm_size(m_comm, &m_grid_size);
109  MPI_Comm_rank(m_comm, &m_grid_rank);
110 
112 
113  status();
114 
115  return EXIT_SUCCESS;
116 }
117 
118 
120 {
121  LOG;
122  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
123  // unreached.
124 }
125 
126 
127 //----------------------------------------------------------------
128 
129 // information
130 
132 {
133  return m_grid_rank == 0;
134 }
135 
136 
138 {
139  return m_grid_rank;
140 }
141 
142 
144 {
145  return m_grid_size;
146 }
147 
148 
149 bool Communicator_impl::is_primary_master()
150 {
151  return m_global_rank == 0;
152 }
153 
154 
155 #ifdef ENABLE_MULTI_INSTANCE
156 
157 int Communicator_impl::self_global()
158 {
159  return m_global_rank;
160 }
161 
162 
163 int Communicator_impl::world_id()
164 {
165  return m_instance_id;
166 }
167 
168 
169 #endif
170 
171 //----------------------------------------------------------------
172 
173 // synchronize
174 
176 {
177  LOG;
178  return MPI_Barrier(m_comm);
179 }
180 
181 
182 #ifdef ENABLE_MULTI_INSTANCE
183 
184 int Communicator_impl::sync_global()
185 {
186  LOG;
187  return MPI_Barrier(MPI_COMM_WORLD);
188 }
189 
190 
191 #endif
192 
193 //----------------------------------------------------------------
194 
195 // data transfer: base cases
196 
197 int Communicator_impl::Base::broadcast(size_t size, void *data, int sender)
198 {
199  LOG;
200  return MPI_Bcast(data, size, MPI_BYTE, sender, m_comm);
201 }
202 
203 
204 int Communicator_impl::Base::exchange(size_t size, void *recv_buf, void *send_buf, int idir, int ipm, int itag)
205 {
206  LOG;
207 
208  MPI_Status status;
209  int p_send, p_recv;
210 
211  assert(ipm == 1 || ipm == -1);
212 
213  if (Layout::m_grid_dims[idir] == 1) { // no need to transfer
214  memcpy(recv_buf, send_buf, size);
215  return EXIT_SUCCESS;
216  }
217 
218  if (ipm == 1) { // downward shift
219  p_send = Layout::m_ipe_dn[idir];
220  p_recv = Layout::m_ipe_up[idir];
221  } else { // upward shift
222  p_send = Layout::m_ipe_up[idir];
223  p_recv = Layout::m_ipe_dn[idir];
224  }
225 
226  int tag_send = Layout::tag(self(), idir, -ipm);
227  int tag_recv = Layout::tag(p_recv, idir, -ipm);
228 
229  return MPI_Sendrecv(
230  send_buf, size, MPI_BYTE, p_send, tag_send,
231  recv_buf, size, MPI_BYTE, p_recv, tag_recv,
232  m_comm, &status);
233 }
234 
235 
236 int Communicator_impl::Base::send_1to1(size_t size, void *recv_buf, void *send_buf, int send_to, int recv_from, int tag)
237 {
238  LOG;
239 
240  MPI_Status status;
241 
242  if (send_to == recv_from) {
243  memcpy(recv_buf, send_buf, size);
244  } else {
245  if (self() == recv_from)
246  MPI_Send(send_buf, size, MPI_BYTE, send_to, tag, m_comm);
247 
248  if (self() == send_to)
249  MPI_Recv(recv_buf, size, MPI_BYTE, recv_from, tag, m_comm, &status);
250  }
251 
252  // sync should be taken outside.
253 
254  return EXIT_SUCCESS;
255 }
256 
257 
258 int Communicator_impl::Base::reduce(int count, void *recv_buf, void *send_buf, MPI_Datatype type, MPI_Op op, int pattern)
259 {
260  LOG;
261  return MPI_Allreduce((void *)send_buf, (void *)recv_buf, count, type, op, Layout::m_sub_comm[pattern]);
262 }
263 
264 
265 //----------------------------------------------------------------
266 // data transfer for specific datatypes
267 
268 int Communicator_impl::broadcast_string(int count, string& data, int sender)
269 {
270  LOG;
271  assert(count == 1);
272 
273  size_t size = 0;
274 
275  // broadcast string length.
276  if (Communicator::self() == sender) {
277  size = data.size();
278  }
279  MPI_Bcast((void *)&size, sizeof(size_t), MPI_BYTE, sender, m_comm);
280 
281  // allocate buffer. pack data at sender.
282  char *buf = new char[size + 1];
283  memset(buf, '\0', size + 1);
284 
285  if (Communicator::self() == sender) {
286  data.copy(buf, size, 0);
287  }
288 
289  // do broadcast.
290  int retv = MPI_Bcast((void *)buf, size, MPI_BYTE, sender, m_comm);
291 
292  if (Communicator::self() != sender) {
293  data = string(buf);
294  }
295 
296  delete [] buf;
297 
298  return retv;
299 }
300 
301 
302 //----------------------------------------------------------------
303 
304 // info
305 
307 {
308  return MPI_Wtime();
309 }
310 
311 
312 // debug
313 
315 {
316 #ifdef DEBUG
317 #ifdef ENABLE_MULTI_INSTANCE
318  printf("global_rank=%2d/%2d: ngrid=%d, grid_id=%d: grid_rank=%2d/%2d\n",
319  m_global_rank, m_global_size,
320  m_n_instance, m_instance_id,
322 
323 #else
324  printf("grid_rank=%2d/%2d\n",
326 #endif
327 #endif
328 
329 
330  return EXIT_SUCCESS;
331 }
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.
#define LOG
Definition: defs.h:8
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:54
static int m_comm
instead of MPI_Comm m_comm;
static int * m_grid_dims
grid dimensions in directions.
Definition: layout.h:39
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:42
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)
static std::terminate_handler default_handler