Bridge++  Ver. 1.3.x
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 
20 #include "commonParameters.h"
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 
130  // find logical layout
131  int retv = pe_logical_layout(m_ndim, m_dims, m_grid_size, m_grid_dims);
132 
133  if (retv != EXIT_SUCCESS) {
134  fprintf(stderr, "layout failed.\n");
135  exit(EXIT_FAILURE);
136  }
137 
138  // physical to logical map
139  physical_map_setup();
140 
141  // find logical coordinate of my rank
142  m_grid_coord = new int [m_ndim];
143  grid_coord(m_grid_coord, m_grid_rank);
144 
145  // find neighbour rank
146  m_ipe_up = new int [m_ndim];
147  m_ipe_dn = new int [m_ndim];
148 
149  int *coord = new int [m_ndim];
150  for (int i = 0; i < m_ndim; ++i) {
151  for (int j = 0; j < m_ndim; ++j) {
152  coord[j] = m_grid_coord[j];
153  }
154 
155  // upward
156  coord[i] = (m_grid_coord[i] + 1) % m_grid_dims[i];
157  grid_rank(&m_ipe_up[i], coord);
158 
159  // downward
160  coord[i] = (m_grid_coord[i] - 1 + m_grid_dims[i]) % m_grid_dims[i];
161  grid_rank(&m_ipe_dn[i], coord);
162  }
163  delete [] coord;
164 
165 
166 #ifdef DEBUG
167  printf("rank %d: up=(%d,%d,%d,%d), dn=(%d,%d,%d,%d)\n",
169  m_ipe_up[0], m_ipe_up[1], m_ipe_up[2], m_ipe_up[3],
170  m_ipe_dn[0], m_ipe_dn[1], m_ipe_dn[2], m_ipe_dn[3]);
171 #endif
172 
173 
174  // subgrid of reduced dimension.
175  // subgrid_setup();
176 
177  return EXIT_SUCCESS;
178 }
179 
180 
181 //====================================================================
183 {
184  // subgrid_delete();
185 
186  physical_map_delete();
187 
188  delete [] m_dims;
189  delete [] m_grid_dims;
190  delete [] m_grid_coord;
191  delete [] m_ipe_up;
192  delete [] m_ipe_dn;
193 
194  return EXIT_SUCCESS;
195 }
196 
197 
198 //====================================================================
199 // subgrid for communication in reduced dimensional subsets
200 // -- discarded [H.Matsufuru].
201 
202 namespace { // anonymous namespace
203 // layout
204  static const int prime_table[] =
205  {
206  2, 3, 5, 7, 11, 13, 17, 19,
207  23, 29, 31, 37, 41, 43, 47, 53,
208  59, 61, 67, 71, 73, 79, 83, 89,
209  97, 101, 103, 107, 109, 113, 127, 131,
210  137, 139, 149, 151, 157, 163, 167, 173,
211  179, 181, 191, 193, 197, 199, 211, 223,
212  227, 229, 233, 239, 241, 251, 257, 263,
213  269, 271, 277, 281, 283, 293, 307, 311,
214  };
215 
216  static const int nprime = sizeof(prime_table) / sizeof(int);
217 
218 //* find logical layout
219 //* divide dims_mu into npe_mu x local_mu where prod npe_mu = nproc.
220 //* npe_mu != 0 is kept intact.
221  static int pe_logical_layout(const int ndim, const int *dims, int nproc, int *npe)
222  {
223  int retv = EXIT_SUCCESS;
224 
225  int nfreedim = 0;
226  int nfreeproc = nproc;
227 
228  for (int i = 0; i < ndim; ++i) {
229  if (npe[i] == 0) {
230  ++nfreedim;
231  } else {
232  if (npe[i] < 0) {
233  fprintf(stderr, "illegal value: npe[%d]=%d.\n", i, npe[i]);
234  return EXIT_FAILURE;
235  } else if (nproc % npe[i] != 0) {
236  fprintf(stderr, "illegal value: npe[%d]=%d does not divide NPE=%d.\n", i, npe[i], nproc);
237  return EXIT_FAILURE;
238  } else if (nfreeproc % npe[i] != 0) {
239  fprintf(stderr, "illegal value: NPE=%d is not divisable by %d.\n", nproc, nproc / nfreeproc * npe[i]);
240  return EXIT_FAILURE;
241  } else if (dims[i] % npe[i] != 0) {
242  fprintf(stderr, "illegal value: npe[%d]=%d does not divide L=%d.\n", i, npe[i], dims[i]);
243  return EXIT_FAILURE;
244  } else {
245  nfreeproc /= npe[i];
246  }
247  }
248  }
249 
250  if (nfreeproc < 1) {
251  fprintf(stderr, "impossible layout.\n");
252  return EXIT_FAILURE;
253  } else if (nfreeproc == 1) {
254  for (int i = 0; i < ndim; ++i) {
255  if (npe[i] == 0) npe[i] = 1;
256  }
257  return EXIT_SUCCESS; // complete.
258  } else {
259  if (nfreedim == 0) {
260  fprintf(stderr, "impossible layout. no room to divide.\n");
261  return EXIT_FAILURE;
262  }
263  }
264 
265  // divide nfreeproc to nfreedim npe's.
266  int np = nfreeproc;
267 
268  int *subdims = new int [ndim];
269  int nf = 0;
270  for (int i = 0; i < ndim; ++i) {
271  if (npe[i] == 0) subdims[nf++] = dims[i]; }
272 
273  int *count = new int [nprime];
274  for (int i = 0; i < nprime; ++i) {
275  count[i] = 0;
276  }
277 
278  for (int i = 0; i < nprime; ++i) {
279  int p = prime_table[i];
280  while (np > 1 && np % p == 0)
281  {
282  ++count[i];
283  np /= p;
284  }
285  if (np == 1) break;
286  }
287 
288 // printf("%d = (", nfreeproc);
289 // for (int i=0; i<nprime; ++i) {
290 // printf("%d, ", count[i]);
291 // }
292 // printf(")\n");
293 
294  if (np > 1) {
295  fprintf(stderr, "insufficient prime table.\n");
296  retv = EXIT_FAILURE;
297  goto finalize;
298  }
299 
300 // printf("subdims=(");
301 // for (int i=0; i<nf; ++i) {
302 // printf("%d, ", subdims[i]);
303 // }
304 // printf(")\n");
305 
306  for (int i = nprime - 1; i >= 0; --i) {
307  if (count[i] == 0) continue;
308 
309  int p = prime_table[i];
310 
311  for (int j = 0; j < count[i]; ++j) {
312  int maxsubdim = 0;
313  int maxk = -1;
314  for (int k = 0; k < nf; ++k) {
315  if ((subdims[k] >= maxsubdim) && (subdims[k] % p == 0)) {
316  maxsubdim = subdims[k];
317  maxk = k;
318  }
319  }
320 // printf("prime=%d, maxk=%d, maxsubdim=%d\n", p, maxk, maxsubdim);
321 
322  if (maxk == -1) {
323  fprintf(stderr, "not divisable. %d\n", p);
324  retv = EXIT_FAILURE;
325  goto finalize;
326  }
327 
328  subdims[maxk] /= p;
329  }
330  }
331 
332 /*
333  printf("subdims=(");
334  for (int i=0; i<nf; ++i) {
335  printf("%d, ", subdims[i]);
336  }
337  printf(")\n");
338 */
339  // store
340  for (int i = 0, k = 0; i < ndim; ++i) {
341  if (npe[i] == 0) {
342  npe[i] = dims[i] / subdims[k];
343  ++k;
344  }
345  }
346 
347 finalize:
348  delete [] subdims;
349  delete [] count;
350 
351  return retv;
352  }
353 
354 
355 //* find n primes.
356  static int find_primes(const int n, int *p)
357  {
358  if (n < 1) return EXIT_FAILURE;
359 
360  int i = 0;
361  int k = 2;
362 
363  p[i++] = k++;
364 
365  while (1)
366  {
367  int j;
368  for (j = 0; j < i; ++j) {
369  if (k % p[j] == 0) break;
370  }
371 
372  if (j >= i) { // not divisable by p[0]..p[i-1]. found new prime.
373  p[i++] = k;
374  if (i >= n) return EXIT_FAILURE;
375  }
376 
377  ++k;
378  }
379 
380  return EXIT_SUCCESS;
381  }
382 } // anonymous namespace
383 
384 //====================================================================
385 //============================================================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:182
static int * m_ipe_dn
rank of downward neighbour in directions.
Definition: layout.h:42