Bridge++  Ver. 1.1.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 "communicator_mpi.h"
15 #include "layout.h"
16 
17 static const char rcsid[] = "$Id: communicator_mpi.cpp 942 2013-07-22 06:50:06Z aoym $";
18 
19 // exception handler for uncaught throw.
20 static std::terminate_handler default_handler = std::set_terminate(Communicator::abort);
21 
23 
31 #if 0
32 extern "C" {
33 void abort()
34 {
35  fprintf(stderr, "abort() called. terminate.\n");
37 }
38 }
39 #endif
40 
41 // define static members
42 #ifdef ENABLE_MULTI_INSTANCE
43 int Communicator_impl::m_n_instance = 1; // number of instances
44 int Communicator_impl::m_instance_id = 0; // id of present instance
45 #endif
46 
47 int Communicator_impl::m_global_rank = 0;
48 int Communicator_impl::m_global_size = 1;
49 
52 
54 
55 //----------------------------------------------------------------
56 
57 // class methods
58 int Communicator_impl::init(int *pargc, char ***pargv)
59 {
60  LOG;
61 
62  MPI_Init(pargc, pargv);
63 
64  MPI_Comm_size(MPI_COMM_WORLD, &m_global_size);
65  MPI_Comm_rank(MPI_COMM_WORLD, &m_global_rank);
66 
67  // grid size and rank equal to global ones for a moment until layout is set.
68  m_grid_size = m_global_size;
69  m_grid_rank = m_global_rank;
70 
71  //- initialize m_comm, thanks to Aoyama-san.
72  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
73 
74  return EXIT_SUCCESS;
75 }
76 
77 
79 {
80  LOG;
81  return MPI_Finalize();
82 }
83 
84 
85 int Communicator_impl::setup(int ninstance)
86 {
87  LOG;
88 
89 #ifdef ENABLE_MULTI_INSTANCE
90  if ((ninstance == 0) || (m_global_size % ninstance != 0)) {
91  printf("%s: invalid number of instance: %d\n", "Communicator::init", ninstance);
92  abort();
93  }
94 
95  m_n_instance = ninstance;
96 
97  int gsize = m_global_size / ninstance;
98  m_instance_id = m_global_rank / gsize;
99 
100  MPI_Comm_split(MPI_COMM_WORLD, m_instance_id, 0 /* key */, &m_comm);
101 
102 #else
103 // m_n_instance = 1;
104 // m_instance_id = 0;
105 
106  MPI_Comm_dup(MPI_COMM_WORLD, &m_comm);
107 #endif
108 
109  MPI_Comm_size(m_comm, &m_grid_size);
110  MPI_Comm_rank(m_comm, &m_grid_rank);
111 
113 
114  status();
115 
116  return EXIT_SUCCESS;
117 }
118 
119 
121 {
122  LOG;
123  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
124  // unreached.
125 }
126 
127 
128 //----------------------------------------------------------------
129 
130 // information
131 
133 {
134  return m_grid_rank == 0;
135 }
136 
137 
139 {
140  return m_grid_rank;
141 }
142 
143 
145 {
146  return m_grid_size;
147 }
148 
149 
150 bool Communicator_impl::is_primary_master()
151 {
152  return m_global_rank == 0;
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 int Communicator_impl::world_id()
165 {
166  return m_instance_id;
167 }
168 #endif
169 
170 //----------------------------------------------------------------
171 
172 // synchronize
173 
175 {
176  LOG;
177  return MPI_Barrier(m_comm);
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 
192 // data transfer: base cases
193 
194 int Communicator_impl::Base::broadcast(size_t size, void *data, int sender)
195 {
196  LOG;
197  return MPI_Bcast(data, size, MPI_BYTE, sender, m_comm);
198 }
199 
200 
201 int Communicator_impl::Base::exchange(size_t size, void *recv_buf, void *send_buf, int idir, int ipm, int itag)
202 {
203  LOG;
204 
205  MPI_Status status;
206  int p_send, p_recv;
207 
208  assert(ipm == 1 || ipm == -1);
209 
210  if (Layout::m_grid_dims[idir] == 1) { // no need to transfer
211  memcpy(recv_buf, send_buf, size);
212  return EXIT_SUCCESS;
213  }
214 
215  if (ipm == 1) { // downward shift
216  p_send = Layout::m_ipe_dn[idir];
217  p_recv = Layout::m_ipe_up[idir];
218  } else { // upward shift
219  p_send = Layout::m_ipe_up[idir];
220  p_recv = Layout::m_ipe_dn[idir];
221  }
222 
223  int tag_send = Layout::tag(self(), idir, -ipm);
224  int tag_recv = Layout::tag(p_recv, idir, -ipm);
225 
226  return MPI_Sendrecv(
227  send_buf, size, MPI_BYTE, p_send, tag_send,
228  recv_buf, size, MPI_BYTE, p_recv, tag_recv,
229  m_comm, &status);
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 int Communicator_impl::Base::reduce(int count, void *recv_buf, void *send_buf, MPI_Datatype type, MPI_Op op, int pattern)
256 {
257  LOG;
258  return MPI_Allreduce((void *)send_buf, (void *)recv_buf, count, type, op, Layout::m_sub_comm[pattern]);
259 }
260 
261 
262 //----------------------------------------------------------------
263 // data transfer for specific datatypes
264 
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 
301 // info
302 
304 {
305  return MPI_Wtime();
306 }
307 
308 
309 // debug
310 
312 {
313 #ifdef DEBUG
314 #ifdef ENABLE_MULTI_INSTANCE
315  printf("global_rank=%2d/%2d: ngrid=%d, grid_id=%d: grid_rank=%2d/%2d\n",
316  m_global_rank, m_global_size,
317  m_n_instance, m_instance_id,
319 
320 #else
321  printf("grid_rank=%2d/%2d\n",
323 #endif
324 #endif
325 
326 
327  return EXIT_SUCCESS;
328 }