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