QUDA  v1.1.0
A library for QCD on GPUs
layout_hyper.cpp
Go to the documentation of this file.
1 /*
2  setup_layout() sets up layout
3  node_number() returns the node number on which a site lives
4  node_index() returns the index of the site on the node
5  get_coords() gives lattice coords from node & index
6 */
7 
8 // for int max
9 #include <limits>
10 
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <qmp.h>
14 #include <layout_hyper.h>
15 #include <util_quda.h>
16 
17 /* The following globals are required:
18  QMP_get_logical_topology()
19  QMP_logical_topology_is_declared()
20  this_node
21  QMP_abort()
22 */
23 
24 static int *squaresize = nullptr; /* dimensions of hypercubes */
25 static int *nsquares = nullptr; /* number of hypercubes in each direction */
26 static int ndim;
27 static size_t *size1[2] = {nullptr, nullptr}, *size2 = nullptr;
28 static size_t sites_on_node;
29 static int *mcoord = nullptr;
30 static bool single_parity = false;
31 
32 int quda_setup_layout(int len[], int nd, int numnodes, int single_parity_)
33 {
34  ndim = nd;
35  single_parity = single_parity_;
36 
37  if (squaresize) free(squaresize);
38  squaresize = (int *)malloc(ndim * sizeof(int));
39 
40  if (nsquares) free(nsquares);
41  nsquares = (int *)malloc(ndim * sizeof(int));
42 
43  if (mcoord) free(mcoord);
44  mcoord = (int *)malloc(ndim * sizeof(int));
45 
46  /* setup QMP logical topology */
47  if (!QMP_logical_topology_is_declared()) {
48  if (QMP_declare_logical_topology(nsquares, ndim) != 0) return 1;
49  }
50 
51  // use the predetermined geometry
52  for (int i = 0; i < ndim; i++) {
53  nsquares[i] = QMP_get_logical_dimensions()[i];
54  squaresize[i] = len[i] / nsquares[i];
55  }
56 
57  sites_on_node = 1;
58  for (int i = 0; i < ndim; ++i) { sites_on_node *= squaresize[i]; }
59 
60  if (size1[0]) free(size1[0]);
61  size1[0] = (size_t *)malloc(2 * (ndim + 1) * sizeof(size_t));
62  size1[1] = size1[0] + ndim + 1;
63 
64  if (size2) free(size2);
65  size2 = (size_t *)malloc((ndim + 1) * sizeof(size_t));
66 
67  size1[0][0] = 1;
68  size1[1][0] = 0;
69  size2[0] = 1;
70  for (int i = 1; i <= ndim; i++) {
71  size1[0][i] = size2[i - 1] * (squaresize[i - 1] / 2) + size1[0][i - 1] * (squaresize[i - 1] % 2);
72  size1[1][i] = size2[i - 1] * (squaresize[i - 1] / 2) + size1[1][i - 1] * (squaresize[i - 1] % 2);
73  size2[i] = size1[0][i] + size1[1][i];
74  // printf("%s %i\t%i\t%i\n", __func__, size1[0][i], size1[1][i], size2[i]);
75  }
76  return 0;
77 }
78 
79 int quda_node_number(const int x[])
80 {
81  for (int i = 0; i < ndim; i++) { mcoord[i] = x[i] / squaresize[i]; }
82  return QMP_get_node_number_from(mcoord);
83 }
84 
85 #ifdef QIO_HAS_EXTENDED_LAYOUT
86 int quda_node_number_ext(const int x[], void *arg)
87 {
88  (void)arg;
89  return quda_node_number(x);
90 }
91 #endif // QIO_HAS_EXTENDED_LAYOUT
92 
93 size_t quda_node_index_helper(const int x[])
94 {
95  size_t r = 0, p = 0;
96 
97  for (int i = ndim - 1; i >= 0; --i) {
98  r = r * squaresize[i] + (x[i] % squaresize[i]);
99  p += x[i];
100  }
101 
102  if (!single_parity) {
103  if (p % 2 == 0) { /* even site */
104  r /= 2;
105  } else {
106  r = (r + sites_on_node) / 2;
107  }
108  }
109 
110  return r;
111 }
112 
113 #ifdef QIO_HAS_EXTENDED_LAYOUT
114 QIO_Index quda_node_index_ext(const int x[], void *arg)
115 {
116  (void)arg;
117  return static_cast<QIO_Index>(quda_node_index_helper(x));
118 }
119 #else
120 int quda_node_index(const int x[])
121 {
122  size_t node_idx = quda_node_index_helper(x);
123 
124  if (node_idx > static_cast<size_t>(std::numeric_limits<int>::max()) || node_idx < 0)
125  errorQuda("Invalid node_idx %lu", node_idx);
126 
127  return static_cast<int>(node_idx);
128 }
129 #endif // QIO_HAS_EXTENDED_LAYOUT
130 
131 void quda_get_coords_helper(int x[], int node, size_t index)
132 {
133  size_t si = index;
134  int *m = QMP_get_logical_coordinates_from(node);
135 
136  size_t s = 0;
137  for (int i = 0; i < ndim; ++i) {
138  x[i] = m[i] * squaresize[i];
139  s += x[i];
140  }
141 
142  if (!single_parity) {
143  s &= 1;
144 
145  if (index >= size1[s][ndim]) {
146  index -= size1[s][ndim];
147  s ^= 1;
148  }
149 
150  for (int i = ndim - 1; i > 0; i--) {
151  x[i] += 2 * (index / size2[i]);
152  index %= size2[i];
153  if (index >= size1[s][i]) {
154  index -= size1[s][i];
155  s ^= 1;
156  x[i]++;
157  }
158  }
159  x[0] += 2 * index + s;
160  } else {
161  // ((t*Z + z) * Y + y) * X + x
162  for (int i = ndim - 1; i > 0; i--) {
163  x[i] += index / size2[i];
164  index %= size2[i];
165  }
166  x[0] += index;
167  }
168 
169  free(m);
170 
171  /* Check the result */
172 #ifdef QIO_HAS_EXTENDED_LAYOUT
173  size_t node_index = quda_node_index_ext(x, NULL);
174 #else
175  size_t node_index = static_cast<size_t>(quda_node_index(x));
176 #endif
177  if (node_index != si) {
178  if (quda_this_node == 0) {
179  fprintf(stderr, "get_coords: error in layout!\n");
180  for (int i = 0; i < ndim; i++) {
181  fprintf(stderr, "%lu\t%lu\t%lu\n", (size_t)size1[0][i], (size_t)size1[1][i], (size_t)size2[i]);
182  }
183  fprintf(stderr, "%i\tindex=%lu\tx=(", node, (size_t)si);
184  for (int i = 0; i < ndim; i++) fprintf(stderr, i < ndim - 1 ? "%i, " : "%i)\n", x[i]);
185  }
186  QMP_abort(1);
187  exit(1);
188  }
189 }
190 
191 #ifdef QIO_HAS_EXTENDED_LAYOUT
192 void quda_get_coords_ext(int x[], int node, QIO_Index index, void *arg)
193 {
194  (void)arg;
195 
196  if (index > static_cast<QIO_Index>(std::numeric_limits<int>::max()) || index < 0)
197  errorQuda("Invalid index %lu", index);
198  quda_get_coords_helper(x, node, static_cast<size_t>(index));
199 }
200 #else
201 void quda_get_coords(int x[], int node, int index) { quda_get_coords_helper(x, node, static_cast<size_t>(index)); }
202 #endif // QIO_HAS_EXTENDED_LAYOUT
203 
204 /* The number of sites on the specified node */
205 #ifdef QIO_HAS_EXTENDED_LAYOUT
206 QIO_Index quda_num_sites_ext(int node, void *arg)
207 {
208  (void)arg;
209  return sites_on_node;
210 }
211 #else
212 int quda_num_sites(int node)
213 {
214  if (sites_on_node > static_cast<size_t>(std::numeric_limits<int>::max()) || sites_on_node < 0)
215  errorQuda("Invalid sites_on_node %lu", sites_on_node);
216 
217  return static_cast<int>(sites_on_node);
218 }
219 #endif // QIO_HAS_EXTENDED_LAYOUT
void quda_get_coords(int x[], int node, int index)
int quda_node_index(const int x[])
int quda_num_sites(int node)
void quda_get_coords_helper(int x[], int node, size_t index)
size_t quda_node_index_helper(const int x[])
int quda_setup_layout(int len[], int nd, int numnodes, int single_parity_)
int quda_node_number(const int x[])
int quda_this_node
Definition: qio_field.cpp:12
__host__ __device__ ValueType arg(const complex< ValueType > &z)
Returns the phase angle of z.
#define errorQuda(...)
Definition: util_quda.h:120