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