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