QUDA  v0.7.0
A library for QCD on GPUs
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
comm_common.cpp
Go to the documentation of this file.
1 #include <unistd.h> // for gethostname()
2 
3 #include <quda_internal.h>
4 #include <comm_quda.h>
5 
6 
7 struct Topology_s {
8  int ndim;
10  int *ranks;
12  int my_rank;
14  // It might be worth adding communicators to allow for efficient reductions:
15  // #if defined(MPI_COMMS)
16  // MPI_Comm comm;
17  // #elif defined(QMP_COMMS)
18  // QMP_communicator_t comm; // currently only supported by qmp-2.4.0-alpha
19  // #endif
20 };
21 
22 
31 static inline int index(int ndim, const int *dims, const int *x)
32 {
33  int idx = x[0];
34  for (int i = 1; i < ndim; i++) {
35  idx = dims[i]*idx + x[i];
36  }
37  return idx;
38 }
39 
40 
41 static inline bool advance_coords(int ndim, const int *dims, int *x)
42 {
43  bool valid = false;
44  for (int i = ndim-1; i >= 0; i--) {
45  if (x[i] < dims[i]-1) {
46  x[i]++;
47  valid = true;
48  break;
49  } else {
50  x[i] = 0;
51  }
52  }
53  return valid;
54 }
55 
56 
57 char *comm_hostname(void)
58 {
59  static bool cached = false;
60  static char hostname[128];
61 
62  if (!cached) {
63  gethostname(hostname, 128);
64  hostname[127] = '\0';
65  cached = true;
66  }
67 
68  return hostname;
69 }
70 
71 
72 static unsigned long int rand_seed = 137;
73 
81 double comm_drand(void)
82 {
83  const double twoneg48 = 0.35527136788005009e-14;
84  const unsigned long int m = 25214903917, a = 11, mask = 281474976710655;
85  rand_seed = (m * rand_seed + a) & mask;
86  return (twoneg48 * rand_seed);
87 }
88 
89 
90 // QudaCommsMap is declared in quda.h:
91 // typedef int (*QudaCommsMap)(const int *coords, void *fdata);
92 
93 Topology *comm_create_topology(int ndim, const int *dims, QudaCommsMap rank_from_coords, void *map_data)
94 {
95  if (ndim > QUDA_MAX_DIM) {
96  errorQuda("ndim exceeds QUDA_MAX_DIM");
97  }
98 
99  Topology *topo = (Topology *) safe_malloc(sizeof(Topology));
100 
101  topo->ndim = ndim;
102 
103  int nodes = 1;
104  for (int i=0; i<ndim; i++) {
105  topo->dims[i] = dims[i];
106  nodes *= dims[i];
107  }
108 
109  topo->ranks = (int *) safe_malloc(nodes*sizeof(int));
110  topo->coords = (int (*)[QUDA_MAX_DIM]) safe_malloc(nodes*sizeof(int[QUDA_MAX_DIM]));
111 
112  int x[QUDA_MAX_DIM];
113  for (int i = 0; i < QUDA_MAX_DIM; i++) x[i] = 0;
114 
115  do {
116  int rank = rank_from_coords(x, map_data);
117  topo->ranks[index(ndim, dims, x)] = rank;
118  for (int i=0; i<ndim; i++) {
119  topo->coords[rank][i] = x[i];
120  }
121  } while (advance_coords(ndim, dims, x));
122 
123  int my_rank = comm_rank();
124  topo->my_rank = my_rank;
125  for (int i = 0; i < ndim; i++) {
126  topo->my_coords[i] = topo->coords[my_rank][i];
127  }
128 
129  // initialize the random number generator with a rank-dependent seed
130  rand_seed = 17*my_rank + 137;
131 
132  return topo;
133 }
134 
135 
137 {
138  host_free(topo->ranks);
139  host_free(topo->coords);
140  host_free(topo);
141 }
142 
143 
144 int comm_ndim(const Topology *topo)
145 {
146  return topo->ndim;
147 }
148 
149 
150 const int *comm_dims(const Topology *topo)
151 {
152  return topo->dims;
153 }
154 
155 
156 const int *comm_coords(const Topology *topo)
157 {
158  return topo->my_coords;
159 }
160 
161 
162 const int *comm_coords_from_rank(const Topology *topo, int rank)
163 {
164  return topo->coords[rank];
165 }
166 
167 
168 int comm_rank_from_coords(const Topology *topo, const int *coords)
169 {
170  return topo->ranks[index(topo->ndim, topo->dims, coords)];
171 }
172 
173 
174 static inline int mod(int a, int b)
175 {
176  return ((a % b) + b) % b;
177 }
178 
179 int comm_rank_displaced(const Topology *topo, const int displacement[])
180 {
181  int coords[QUDA_MAX_DIM];
182 
183  for (int i = 0; i < QUDA_MAX_DIM; i++) {
184  coords[i] = (i < topo->ndim) ?
185  mod(comm_coords(topo)[i] + displacement[i], comm_dims(topo)[i]) : 0;
186  }
187 
188  return comm_rank_from_coords(topo, coords);
189 }
190 
191 
192 // FIXME: The following routines rely on a "default" topology.
193 // They should probably be reworked or eliminated eventually.
194 
196 
198 {
199  default_topo = topo;
200 }
201 
202 
204 {
205  if (!default_topo) {
206  errorQuda("Default topology has not been declared");
207  }
208  return default_topo;
209 }
210 
211 
212 int comm_dim(int dim)
213 {
215  return comm_dims(topo)[dim];
216 }
217 
218 
219 int comm_coord(int dim)
220 {
222  return comm_coords(topo)[dim];
223 }
224 
225 
229 MsgHandle *comm_declare_send_relative(void *buffer, int dim, int dir, size_t nbytes)
230 {
231  int disp[QUDA_MAX_DIM] = {0};
232  disp[dim] = dir;
233 
234  return comm_declare_send_displaced(buffer, disp, nbytes);
235 }
236 
237 
241 MsgHandle *comm_declare_receive_relative(void *buffer, int dim, int dir, size_t nbytes)
242 {
243  int disp[QUDA_MAX_DIM] = {0};
244  disp[dim] = dir;
245 
246  return comm_declare_receive_displaced(buffer, disp, nbytes);
247 }
248 
252 MsgHandle *comm_declare_strided_send_relative(void *buffer, int dim, int dir,
253  size_t blksize, int nblocks, size_t stride)
254 {
255  int disp[QUDA_MAX_DIM] = {0};
256  disp[dim] = dir;
257 
258  return comm_declare_strided_send_displaced(buffer, disp, blksize, nblocks, stride);
259 }
260 
261 
266  size_t blksize, int nblocks, size_t stride)
267 {
268  int disp[QUDA_MAX_DIM] = {0};
269  disp[dim] = dir;
270 
271  return comm_declare_strided_receive_displaced(buffer, disp, blksize, nblocks, stride);
272 }
273 
274 void comm_finalize(void)
275 {
277  comm_destroy_topology(topo);
279 }
280 
281 
282 static int manual_set_partition[QUDA_MAX_DIM] = {0};
283 
285 {
286  manual_set_partition[dim] = 1;
287 }
288 
289 
291 {
292  return (manual_set_partition[dim] || (comm_dim(dim) > 1));
293 }
double comm_drand(void)
Definition: comm_common.cpp:81
int comm_rank(void)
Definition: comm_mpi.cpp:80
const int * comm_dims(const Topology *topo)
MsgHandle * comm_declare_receive_displaced(void *buffer, const int displacement[], size_t nbytes)
Definition: comm_mpi.cpp:117
int comm_dim_partitioned(int dim)
void comm_set_default_topology(Topology *topo)
MsgHandle * comm_declare_strided_receive_displaced(void *buffer, const int displacement[], size_t blksize, int nblocks, size_t stride)
Definition: comm_mpi.cpp:155
#define errorQuda(...)
Definition: util_quda.h:73
#define host_free(ptr)
Definition: malloc_quda.h:29
char * comm_hostname(void)
Definition: comm_common.cpp:57
int comm_ndim(const Topology *topo)
void comm_destroy_topology(Topology *topo)
int comm_rank_from_coords(const Topology *topo, const int *coords)
void comm_dim_partitioned_set(int dim)
MsgHandle * comm_declare_strided_send_displaced(void *buffer, const int displacement[], size_t blksize, int nblocks, size_t stride)
Definition: comm_mpi.cpp:133
const int * comm_coords_from_rank(const Topology *topo, int rank)
MsgHandle * comm_declare_send_displaced(void *buffer, const int displacement[], size_t nbytes)
Definition: comm_mpi.cpp:101
int my_coords[QUDA_MAX_DIM]
Definition: comm_common.cpp:13
Topology * default_topo
int dims[QUDA_MAX_DIM]
Definition: comm_common.cpp:9
int(* coords)[QUDA_MAX_DIM]
Definition: comm_common.cpp:11
MsgHandle * comm_declare_strided_send_relative(void *buffer, int dim, int dir, size_t blksize, int nblocks, size_t stride)
int comm_dim(int dim)
#define safe_malloc(size)
Definition: malloc_quda.h:25
int x[4]
MsgHandle * comm_declare_strided_receive_relative(void *buffer, int dim, int dir, size_t blksize, int nblocks, size_t stride)
int comm_coord(int dim)
int comm_rank_displaced(const Topology *topo, const int displacement[])
const int * comm_coords(const Topology *topo)
MsgHandle * comm_declare_send_relative(void *buffer, int dim, int dir, size_t nbytes)
Topology * comm_create_topology(int ndim, const int *dims, QudaCommsMap rank_from_coords, void *map_data)
Definition: comm_common.cpp:93
#define QUDA_MAX_DIM
Maximum number of dimensions supported by QUDA. In practice, no routines make use of more than 5...
int(* QudaCommsMap)(const int *coords, void *fdata)
Definition: comm_quda.h:12
void comm_finalize(void)
Topology * comm_default_topology(void)
MsgHandle * comm_declare_receive_relative(void *buffer, int dim, int dir, size_t nbytes)