Bridge++  Ver. 2.0.2
layout.cpp
Go to the documentation of this file.
1 
14 #include "layout.h"
15 
16 // prototype declaration
17 namespace {
18  static int pe_logical_layout(const int ndim, const int *dims, int nproc, int *npe);
19  static int find_primes(const int n, int *p);
20 }
21 
22 // static members
24 int *Communicator_impl::Layout::m_dims = 0; //< lattice extent
25 
26 // logical layout
29 
32 
33 // physical mapping
35 int *Communicator_impl::Layout::m_physical_to_logical = 0; //< map between physical and logical grid
36 
37 // subdimensional-slices
39 
40 
41 //====================================================================
42 // communicator_impl methods
43 int Communicator_impl::Layout::ipe(const int idir)
44 {
45  return m_grid_coord[idir];
46 }
47 
48 
49 //====================================================================
50 int Communicator_impl::Layout::npe(const int idir)
51 {
52  return m_grid_dims[idir];
53 }
54 
55 
56 //====================================================================
58 {
59  for (int i = 0; i < m_ndim; ++i) {
60  dims[i] = m_grid_dims[i];
61  }
62  return EXIT_SUCCESS;
63 }
64 
65 
66 //====================================================================
67 // tag() : identify transfer channel by source rank and direction (incl fw/bw)
68 int Communicator_impl::Layout::tag(int rank, int idir, int ipm)
69 {
70  return 2 * m_ndim * rank + idir + ((ipm > 0) ? 0 : m_ndim);
71 }
72 
73 
74 //====================================================================
76 
94 {
95  // fetch parameter values from CommonParameters
96 
97  m_ndim = CommonParameters::Ndim();
98 
99  // lattice size
100  m_dims = new int [m_ndim];
101 
102  m_dims[0] = CommonParameters::Lx();
103  m_dims[1] = CommonParameters::Ly();
104  m_dims[2] = CommonParameters::Lz();
105  m_dims[3] = CommonParameters::Lt();
106 
107  // suggested logical layout
108  m_grid_dims = new int [m_ndim];
109 
110  m_grid_dims[0] = CommonParameters::NPEx();
111  m_grid_dims[1] = CommonParameters::NPEy();
112  m_grid_dims[2] = CommonParameters::NPEz();
113  m_grid_dims[3] = CommonParameters::NPEt();
114 
115  // suggested local volume
116  int *local_dims = new int [m_ndim];
117 
118  local_dims[0] = CommonParameters::Nx();
119  local_dims[1] = CommonParameters::Ny();
120  local_dims[2] = CommonParameters::Nz();
121  local_dims[3] = CommonParameters::Nt();
122 
123  for (int i = 0; i < m_ndim; ++i) {
124  if (local_dims[i] != 0) { // there is a suggestion of local extent.
125  if (m_grid_dims[i] != 0) {
126  if (m_grid_dims[i] * local_dims[i] != m_dims[i]) {
127  fprintf(stderr, "layout mismatch.\n");
128  exit(EXIT_FAILURE);
129  } else {
130  // ok. m_grid_dims[i] is as specified.
131  }
132  } else { // use specified local size and find number of divisions.
133  if (m_dims[i] % local_dims[i] != 0) {
134  fprintf(stderr, "layout mismatch. lattice undivisable by local volume.\n");
135  exit(EXIT_FAILURE);
136  } else {
137  m_grid_dims[i] = m_dims[i] / local_dims[i];
138  }
139  }
140  }
141  }
142 
143  delete [] local_dims;
144 
145 
146  std::vector<int> lattice_size(m_dims, m_dims + 4);
147  std::vector<int> grid_size(m_grid_dims, m_grid_dims + 4);
148 
149  // continue setup
150  return layout_setup(lattice_size, grid_size);
151 }
152 
153 
155  const std::vector<int>& lattice_size,
156  std::vector<int>& grid_size)
157 {
158  m_ndim = lattice_size.size();
159 
160  // lattice size
161  m_dims = new int [m_ndim];
162 
163  for (int i = 0; i < m_ndim; ++i) {
164  m_dims[i] = lattice_size[i];
165  }
166 
167  // suggested logical layout
168  m_grid_dims = new int [m_ndim];
169 
170  for (int i = 0; i < m_ndim; ++i) {
171  m_grid_dims[i] = 0;
172  }
173 
174  for (int i = 0; i < grid_size.size(); ++i) {
175  m_grid_dims[i] = grid_size[i];
176  }
177 
178 
179  // find logical layout
180  int retv = pe_logical_layout(m_ndim, m_dims, m_grid_size, m_grid_dims);
181 
182  // note: Communicator_impl::m_grid_size = size of local communicator m_comm.
183 
184  if (retv != EXIT_SUCCESS) {
185  fprintf(stderr, "layout failed.\n");
186  exit(EXIT_FAILURE);
187  }
188 
189 
190  // store back to grid_size
191  grid_size.resize(m_ndim);
192  for (int i = 0; i < m_ndim; ++i) {
193  grid_size[i] = m_grid_dims[i];
194  }
195 
196 
197  // physical to logical map
198  physical_map_setup();
199 
200  // find logical coordinate of my rank
201  m_grid_coord = new int [m_ndim];
202  grid_coord(m_grid_coord, m_grid_rank);
203 
204  // find neighbour rank
205  m_ipe_up = new int [m_ndim];
206  m_ipe_dn = new int [m_ndim];
207 
208  int *coord = new int [m_ndim];
209  for (int i = 0; i < m_ndim; ++i) {
210  for (int j = 0; j < m_ndim; ++j) {
211  coord[j] = m_grid_coord[j];
212  }
213 
214  // upward
215  coord[i] = (m_grid_coord[i] + 1) % m_grid_dims[i];
216  grid_rank(&m_ipe_up[i], coord);
217 
218  // downward
219  coord[i] = (m_grid_coord[i] - 1 + m_grid_dims[i]) % m_grid_dims[i];
220  grid_rank(&m_ipe_dn[i], coord);
221  }
222  delete [] coord;
223 
224 
225 #ifdef DEBUG
226  printf("rank %d: up=(%d,%d,%d,%d), dn=(%d,%d,%d,%d)\n",
228  m_ipe_up[0], m_ipe_up[1], m_ipe_up[2], m_ipe_up[3],
229  m_ipe_dn[0], m_ipe_dn[1], m_ipe_dn[2], m_ipe_dn[3]);
230 #endif
231 
232  // subgrid of reduced dimension.
233  subgrid_setup();
234 
235  return EXIT_SUCCESS;
236 }
237 
238 
239 //====================================================================
241 {
242  subgrid_delete();
243 
244  physical_map_delete();
245 
246  delete [] m_dims;
247  delete [] m_grid_dims;
248  delete [] m_grid_coord;
249  delete [] m_ipe_up;
250  delete [] m_ipe_dn;
251 
252  return EXIT_SUCCESS;
253 }
254 
255 
256 //====================================================================
257 // subgrid for communication in reduced dimensional subsets
259 {
260  // int Nmask = (1 << m_ndim);
261  int Nmask = 1;
262 
263  // temporary modified to avoid error on BG/Q. [23 May 2014 H.M.]
264 
265  m_sub_comm = new MPI_Comm [Nmask];
266 
267  for (int imask = 0; imask < Nmask; ++imask) {
268  //int coord[m_ndim];
269  int *coord = new int [m_ndim];
270  for (int i = 0; i < m_ndim; ++i) {
271  coord[i] = m_grid_coord[i];
272  }
273 
274  for (int i = 0; i < m_ndim; ++i) {
275  bool mask = ((imask >> i) & 1) == 1 ? true : false;
276  if (!mask) coord[i] = 0;
277  }
278 
279  int rank = 0;
280  grid_rank(&rank, coord);
281 
282 /*
283  printf("split %2d: rank %2d: (%d,%d,%d,%d) -> (%d,%d,%d,%d), %2d\n",
284  imask,
285  m_grid_rank,
286  m_grid_coord[0], m_grid_coord[1], m_grid_coord[2], m_grid_coord[3],
287  coord[0], coord[1], coord[2], coord[3],
288  rank);
289 */
290  MPI_Comm_split(m_comm, rank, 0 /* key */, &m_sub_comm[imask]);
291  delete [] coord;
292  }
293 
294  return EXIT_SUCCESS;
295 }
296 
297 
298 //====================================================================
300 {
301  delete [] m_sub_comm;
302 
303  return EXIT_SUCCESS;
304 }
305 
306 
307 //====================================================================
308 namespace { // anonymous namespace
309 // layout
310  static const int prime_table[] =
311  {
312  2, 3, 5, 7, 11, 13, 17, 19,
313  23, 29, 31, 37, 41, 43, 47, 53,
314  59, 61, 67, 71, 73, 79, 83, 89,
315  97, 101, 103, 107, 109, 113, 127, 131,
316  137, 139, 149, 151, 157, 163, 167, 173,
317  179, 181, 191, 193, 197, 199, 211, 223,
318  227, 229, 233, 239, 241, 251, 257, 263,
319  269, 271, 277, 281, 283, 293, 307, 311,
320  };
321 
322  static const int nprime = sizeof(prime_table) / sizeof(int);
323 
324 //* find logical layout
325 //* divide dims_mu into npe_mu x local_mu where prod npe_mu = nproc.
326 //* npe_mu != 0 is kept intact.
327  static int pe_logical_layout(const int ndim, const int *dims, int nproc, int *npe)
328  {
329  int retv = EXIT_SUCCESS;
330 
331  int nfreedim = 0;
332  int nfreeproc = nproc;
333 
334  for (int i = 0; i < ndim; ++i) {
335  if (npe[i] == 0) {
336  ++nfreedim;
337  } else {
338  if (npe[i] < 0) {
339  fprintf(stderr, "illegal value: npe[%d]=%d.\n", i, npe[i]);
340  return EXIT_FAILURE;
341  } else if (nproc % npe[i] != 0) {
342  fprintf(stderr, "illegal value: npe[%d]=%d does not divide NPE=%d.\n", i, npe[i], nproc);
343  return EXIT_FAILURE;
344  } else if (nfreeproc % npe[i] != 0) {
345  fprintf(stderr, "illegal value: NPE=%d is not divisable by %d.\n", nproc, nproc / nfreeproc * npe[i]);
346  return EXIT_FAILURE;
347  } else if (dims[i] % npe[i] != 0) {
348  fprintf(stderr, "illegal value: npe[%d]=%d does not divide L=%d.\n", i, npe[i], dims[i]);
349  return EXIT_FAILURE;
350  } else {
351  nfreeproc /= npe[i];
352  }
353  }
354  }
355 
356  if (nfreeproc < 1) {
357  fprintf(stderr, "impossible layout.\n");
358  return EXIT_FAILURE;
359  } else if (nfreeproc == 1) {
360  for (int i = 0; i < ndim; ++i) {
361  if (npe[i] == 0) npe[i] = 1;
362  }
363  return EXIT_SUCCESS; // complete.
364  } else {
365  if (nfreedim == 0) {
366  fprintf(stderr, "impossible layout. no room to divide.\n");
367  return EXIT_FAILURE;
368  }
369  }
370 
371  // divide nfreeproc to nfreedim npe's.
372  int np = nfreeproc;
373 
374  int *subdims = new int [ndim];
375  int nf = 0;
376  for (int i = 0; i < ndim; ++i) {
377  if (npe[i] == 0) subdims[nf++] = dims[i]; }
378 
379  int *count = new int [nprime];
380  for (int i = 0; i < nprime; ++i) {
381  count[i] = 0;
382  }
383 
384  for (int i = 0; i < nprime; ++i) {
385  int p = prime_table[i];
386  while (np > 1 && np % p == 0)
387  {
388  ++count[i];
389  np /= p;
390  }
391  if (np == 1) break;
392  }
393 
394 // printf("%d = (", nfreeproc);
395 // for (int i=0; i<nprime; ++i) {
396 // printf("%d, ", count[i]);
397 // }
398 // printf(")\n");
399 
400  if (np > 1) {
401  fprintf(stderr, "insufficient prime table.\n");
402  retv = EXIT_FAILURE;
403  goto finalize;
404  }
405 
406 // printf("subdims=(");
407 // for (int i=0; i<nf; ++i) {
408 // printf("%d, ", subdims[i]);
409 // }
410 // printf(")\n");
411 
412  for (int i = nprime - 1; i >= 0; --i) {
413  if (count[i] == 0) continue;
414 
415  int p = prime_table[i];
416 
417  for (int j = 0; j < count[i]; ++j) {
418  int maxsubdim = 0;
419  int maxk = -1;
420  for (int k = 0; k < nf; ++k) {
421  if ((subdims[k] >= maxsubdim) && (subdims[k] % p == 0)) {
422  maxsubdim = subdims[k];
423  maxk = k;
424  }
425  }
426 // printf("prime=%d, maxk=%d, maxsubdim=%d\n", p, maxk, maxsubdim);
427 
428  if (maxk == -1) {
429  fprintf(stderr, "not divisable. %d\n", p);
430  retv = EXIT_FAILURE;
431  goto finalize;
432  }
433 
434  subdims[maxk] /= p;
435  }
436  }
437 
438 /*
439  printf("subdims=(");
440  for (int i=0; i<nf; ++i) {
441  printf("%d, ", subdims[i]);
442  }
443  printf(")\n");
444 */
445  // store
446  for (int i = 0, k = 0; i < ndim; ++i) {
447  if (npe[i] == 0) {
448  npe[i] = dims[i] / subdims[k];
449  ++k;
450  }
451  }
452 
453 finalize:
454  delete [] subdims;
455  delete [] count;
456 
457  return retv;
458  }
459 
460 
461  //* find n primes.
462  static int find_primes(const int n, int *p)
463  {
464  if (n < 1) return EXIT_FAILURE;
465 
466  int i = 0;
467  int k = 2;
468 
469  p[i++] = k++;
470 
471  while (1)
472  {
473  int j;
474  for (j = 0; j < i; ++j) {
475  if (k % p[j] == 0) break;
476  }
477 
478  if (j >= i) { // not divisable by p[0]..p[i-1]. found new prime.
479  p[i++] = k;
480  if (i >= n) return EXIT_FAILURE;
481  }
482 
483  ++k;
484  }
485 
486  return EXIT_SUCCESS;
487  }
488 } // anonymous namespace
489 
490 //====================================================================
491 //============================================================END=====
CommonParameters::Ny
static int Ny()
Definition: commonParameters.h:106
Communicator_impl::Layout::m_ndim
static int m_ndim
number of dimensions.
Definition: layout.h:46
CommonParameters::Nz
static int Nz()
Definition: commonParameters.h:107
Communicator_impl::Layout::subgrid_delete
static int subgrid_delete()
Definition: layout.cpp:299
Communicator_impl::Layout::m_ipe_dn
static int * m_ipe_dn
rank of downward neighbour in directions.
Definition: layout.h:54
Communicator_impl::m_grid_size
static int m_grid_size
Definition: communicator_mpi.h:110
CommonParameters::Ndim
static int Ndim()
Definition: commonParameters.h:117
Communicator_impl::Layout::m_sub_comm
static MPI_Comm * m_sub_comm
subgrid
Definition: layout.h:64
Communicator_impl::Layout::tag
static int tag(int rank, int idir, int ipm)
generate tag for communication.
Definition: layout.cpp:68
Communicator::self
static int self()
rank within small world.
Definition: communicator.cpp:74
Communicator_impl::Layout::layout_setup
static int layout_setup()
initialise layout.
Definition: layout.cpp:93
CommonParameters::Ly
static int Ly()
Definition: commonParameters.h:92
Communicator_impl::Layout::m_grid_coord
static int * m_grid_coord
grid coordinate.
Definition: layout.h:51
Communicator_impl::Layout::ipe
static int ipe(const int idir)
grid coordinate along idir direction.
Definition: layout.cpp:43
Communicator_impl::Layout::layout_delete
static int layout_delete()
destroy layout and clean up.
Definition: layout.cpp:240
CommonParameters::Nx
static int Nx()
Definition: commonParameters.h:105
CommonParameters::Lt
static int Lt()
Definition: commonParameters.h:94
CommonParameters::Lx
static int Lx()
Definition: commonParameters.h:91
CommonParameters::Lz
static int Lz()
Definition: commonParameters.h:93
CommonParameters::Nt
static int Nt()
Definition: commonParameters.h:108
CommonParameters::NPEz
static int NPEz()
Definition: commonParameters.h:99
Communicator_impl::Layout::npe
static int npe(const int idir)
grid size in idir direction.
Definition: layout.cpp:50
Communicator_impl::m_comm
static MPI_Comm m_comm
Definition: communicator_mpi.h:112
Communicator_impl::Layout::m_grid_dims
static int * m_grid_dims
grid dimensions in directions.
Definition: layout.h:50
Communicator_impl::m_grid_rank
static int m_grid_rank
Definition: communicator_mpi.h:109
Communicator_impl::Layout::m_map_grid
static char m_map_grid[16]
Definition: layout.h:57
CommonParameters::NPEy
static int NPEy()
Definition: commonParameters.h:98
Communicator_impl::Layout::grid_dims
static int grid_dims(int *gdims)
find grid size.
Definition: layout.cpp:57
Communicator_impl::Layout::m_dims
static int * m_dims
lattice extent (Lx, Ly, Lz, Lt)
Definition: layout.h:47
Communicator_impl::finalize
static int finalize()
Definition: communicator_mpi.cpp:78
CommonParameters::NPEx
static int NPEx()
Definition: commonParameters.h:97
CommonParameters::NPEt
static int NPEt()
Definition: commonParameters.h:100
Communicator_impl::Layout::m_ipe_up
static int * m_ipe_up
rank of upward neighbour in directions.
Definition: layout.h:53
layout.h
Communicator_impl::Layout::m_physical_to_logical
static int * m_physical_to_logical
map between physical and logical grid
Definition: layout.h:58
Communicator_impl::Layout::subgrid_setup
static int subgrid_setup()
Definition: layout.cpp:258