QDP++
qdp_parscalarvec_layout.cc
Go to the documentation of this file.
1
14
15#include "qdp_diagnostics.h"
16
17#include "qdp.h"
18#include "qdp_util.h"
19
20#include "qmp.h"
21
22namespace QDP
23{
24
25 //-----------------------------------------------------------------------------
26 // IO routine solely for debugging. Only defined here
27 template<class T>
28 ostream& operator<<(ostream& s, const multi1d<T>& s1)
29 {
30 for(int i=0; i < s1.size(); ++i)
31 s << " " << s1[i];
32
33 return s;
34 }
35
36
37 //-----------------------------------------------------------------------------
38 namespace Layout
39 {
40 //-----------------------------------------------------
42
47 struct LocalLayout_t
48 {
50 int vol;
51
53 multi1d<int> nrow;
54
56 int subgrid_vol;
57
60
63
66
69
71 int node_rank;
72
74 int num_nodes;
75 } _layout;
76
77
78 //-----------------------------------------------------
79 // Functions
80
82 void destroy() {RNG::finalizeRNG();}
83
85 void setLattSize(const multi1d<int>& nrows) {_layout.nrow = nrows;}
86
88
89 void setSMPFlag(bool flag) {}
90
92
93 void setNumProc(int N) {}
94
96 const multi1d<int>& lattSize() {return _layout.nrow;}
97
99 int vol() {return _layout.vol;}
100
102 int sitesOnNode() {return _layout.subgrid_vol;}
103
105 int outerSitesOnNode() {return _layout.olattice_vol;}
106
108 bool primaryNode() {return (_layout.node_rank == 0) ? true : false;}
109
111 const multi1d<int>& subgridLattSize() {return _layout.subgrid_nrow;}
112
114 int nodeNumber() {return _layout.node_rank;}
115
117 int numNodes() {return _layout.num_nodes;}
118
120 const multi1d<int>& nodeCoord() {return _layout.logical_coord;}
121
123 const multi1d<int>& logicalSize() {return _layout.logical_size;}
124
126
127 int getNodeNumberFrom(const multi1d<int>& node_coord)
128 {
129 return QMP_get_node_number_from(node_coord.slice());
130 }
131
133
134 multi1d<int> getLogicalCoordFrom(int node)
135 {
136 multi1d<int> node_coord(Nd);
137 const int* node_crd = QMP_get_logical_coordinates_from(node); // QMP mallocs here
138
139 for(int i=0; i < Nd; ++i)
140 node_coord[i] = node_crd[i];
141
142 // Hackery as free cannot take a const void*, so grab
143 // node_crd with a non const pointer
144 int* non_const_node_crd = const_cast<int*>(node_crd);
145 free(non_const_node_crd); // free up QMP's memory
146 return node_coord;
147 }
148
150 multi1d<int> minimalLayoutMapping();
151
153 void init()
154 {
155 _layout.num_nodes = QMP_get_number_of_nodes();
156 _layout.node_rank = QMP_get_node_number();
157 }
158
159
160
162 int linearSiteIndex(int site)
163 {
164 multi1d<int> coord = crtesn(site, lattSize());
165
166 return linearSiteIndex(coord);
167 }
168
169
171 void initDefaults()
172 {
173#if QDP_DEBUG >= 2
174 QDP_info("Create default subsets");
175#endif
176 // Default set and subsets
178
179 // Default maps
181
182 // Initialize RNG
184
185 // Set default profile level
187 }
188
189
191 void create()
192 {
193 if ( ! QDP_isInitialized() )
194 QDP_error_exit("QDP is not initialized");
195
196 if (_layout.nrow.size() != Nd)
197 QDP_error_exit("dimension of lattice size not the same as the default");
198
199 _layout.vol=1;
200 for(int i=0; i < Nd; ++i)
201 _layout.vol *= _layout.nrow[i];
202
203#if QDP_DEBUG >= 2
204 QDP_info("vol=%d",_layout.vol);
205#endif
206
207#if QDP_DEBUG >= 2
208 QDP_info("Initialize layout");
209#endif
210
211 // This implementation requires there be a multiple of INNER_LEN sites
212 if (_layout.vol % INNER_LEN != 0)
213 QDP_error_exit("Layout::create() - this scalarvec implementation requires there be a multiple of %d sites", INNER_LEN);
214
215
216 // Simple check - we insist here that the total volume is divisible
217 // by the number of processors. Will also insist that the problem
218 // size is regular on each node
219 if (_layout.vol % numNodes() != 0)
220 QDP_error_exit("Layout::create - problem size not divisible by number of processors");
221
222
223 // Return the smallest lattice size per node allowed
224 multi1d<int> min_dim = minimalLayoutMapping();
225
226 // Another sanity check - if the specified lattice size is not a multiple
227 // of the minimal size, then barf
228 for(int i=0; i < Nd; ++i)
229 if (_layout.nrow[i] % min_dim[i] != 0)
230 QDP_error_exit("Layout::create - Error: problem size not multiple of smallest size allowed for this type of layout");
231
232
233 // Now, layout the machine. Note, if the logical_machine size was set previously
234 // it will be used
235 multi1d<int> nrow(Nd);
236 for(int i=0; i < Nd; ++i)
237 nrow[i] = _layout.nrow[i] / min_dim[i];
238
239 int* nrow_slice=const_cast<int*>(nrow.slice());
240 QMP_layout_grid(nrow_slice, Nd);
241
242
243 // Pull out useful stuff
244 const int* phys_size = QMP_get_logical_dimensions();
245 const int* phys_coord = QMP_get_logical_coordinates();
246
247 _layout.subgrid_nrow.resize(Nd);
248 _layout.logical_coord.resize(Nd);
249 _layout.logical_size.resize(Nd);
250
251 _layout.subgrid_vol = 1;
252
253 for(int i=0; i < Nd; ++i)
254 {
255 _layout.logical_coord[i] = phys_coord[i];
256 _layout.logical_size[i] = phys_size[i];
257 _layout.subgrid_nrow[i] = _layout.nrow[i] / _layout.logical_size[i];
258
259 _layout.subgrid_vol *= _layout.subgrid_nrow[i];
260 }
261
262 _layout.olattice_vol = _layout.subgrid_vol >> INNER_LOG; // outer-subgrid volume
263
264
265 // Diagnostics
266 QDPIO::cout << "Lattice initialized:\n";
267 QDPIO::cout << " problem size =";
268 for(int i=0; i < Nd; ++i)
269 QDPIO::cout << " " << _layout.nrow[i];
270 QDPIO::cout << std::endl;
271
272 QDPIO::cout << " logical machine size =";
273 for(int i=0; i < Nd; ++i)
274 QDPIO::cout << " " << _layout.logical_size[i];
275 QDPIO::cout << std::endl;
276
277 QDPIO::cout << " logical node coord =";
278 for(int i=0; i < Nd; ++i)
279 QDPIO::cout << " " << _layout.logical_coord[i];
280 QDPIO::cout << std::endl;
281
282 QDPIO::cout << " subgrid size =";
283 for(int i=0; i < Nd; ++i)
284 QDPIO::cout << " " << _layout.subgrid_nrow[i];
285 QDPIO::cout << std::endl;
286
287 QDPIO::cout << " total volume = " << _layout.vol << std::endl;
288 QDPIO::cout << " subgrid volume = " << _layout.subgrid_vol << std::endl;
289
290 // This implementation requires there be a multiple of INNER_LEN sites
291 // on a node
292 if (_layout.subgrid_vol % INNER_LEN != 0)
293 QDP_error_exit("Layout::create() - this parscalarvec implementation requires there be a multiple of %d sites", INNER_LEN);
294
295
296 // Sanity check - check the QMP node number functions
297 for(int node=0; node < Layout::numNodes(); ++node)
298 {
299 multi1d<int> coord = Layout::getLogicalCoordFrom(node);
300 int node2 = Layout::getNodeNumberFrom(coord);
301
302 if (node != node2)
303 QDP_error_exit("Layout::create - Layout problems, the QMP logical to physical node map functions do not work correctly with this lattice size");
304 }
305
306 // Sanity check - check the layout functions make sense
307 for(int site=0; site < vol(); ++site)
308 {
309 multi1d<int> coord1 = crtesn(site, lattSize());
310
311 int linear = linearSiteIndex(coord1);
312 int node = nodeNumber(coord1);
313
314 multi1d<int> coord2 = siteCoords(node,linear);
315 int j = local_site(coord2, lattSize());
316
317#if QDP_DEBUG >= 2
318 QDP_info("site= %d coord= %d %d %d %d linear= %d node=%d crd=%d %d %d %d j= %d",
319 site,coord1[0],coord1[1],coord1[2],coord1[3],
320 linear,node,
321 coord2[0],coord2[1],coord2[2],coord2[3],
322 j);
323#endif
324 if (site != j)
325 QDP_error_exit("Layout::create - Layout problems, the layout functions do not work correctly with this lattice size");
326 }
327
328 // Initialize various defaults
329 initDefaults();
330
331 QDPIO::cout << "Finished lattice layout" << std::endl;
332 }
333 }
334
335
336 //-----------------------------------------------------------------------------
337#if QDP_USE_LEXICO_LAYOUT == 1
338
339QDPXX_MESSAGE("Using a lexicographic layout")
340
341 namespace Layout
342 {
344
345 int linearSiteIndex(const multi1d<int>& coord)
346 {
347 multi1d<int> tmp_coord(Nd);
348
349 for(int i=0; i < coord.size(); ++i)
350 tmp_coord[i] = coord[i] % Layout::subgridLattSize()[i];
351
352 return local_site(tmp_coord, Layout::subgridLattSize());
353 }
354
355
357
358 int nodeNumber(const multi1d<int>& coord)
359 {
360 multi1d<int> tmp_coord(Nd);
361
362 for(int i=0; i < coord.size(); ++i)
363 tmp_coord[i] = coord[i] / Layout::subgridLattSize()[i];
364
365 return Layout::getNodeNumberFrom(tmp_coord);
366 }
367
368
370
371 multi1d<int> siteCoords(int node, int linear)
372 {
373 multi1d<int> coord = getLogicalCoordFrom(node);
374
375 // Get the base (origins) of the absolute lattice coord
376 coord *= Layout::subgridLattSize();
377
378 // Find the coordinate within a node and accumulate
379 // This is a lexicographic ordering
380 coord += crtesn(linear, Layout::subgridLattSize());
381
382 return coord;
383 }
384
385
387
389 {
390 multi1d<int> dim(Nd);
391 dim = 1;
392
393 return dim;
394 }
395 }
396
397 //-----------------------------------------------------------------------------
398
399#elif QDP_USE_CB2_LAYOUT == 1
400
401QDPXX_MESSAGE("Using a 2 checkerboard (red/black) layout")
402
403 namespace Layout
404 {
406
407 int linearSiteIndex(const multi1d<int>& coord)
408 {
409 int subgrid_vol_cb = Layout::sitesOnNode() >> 1;
410 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
411 subgrid_cb_nrow[0] >>= 1;
412
413 int cb = 0;
414 for(int m=0; m < Nd; ++m)
415 cb += coord[m];
416 cb &= 1;
417
418 multi1d<int> subgrid_cb_coord(Nd);
419 subgrid_cb_coord[0] = (coord[0] >> 1) % subgrid_cb_nrow[0];
420 for(int i=1; i < Nd; ++i)
421 subgrid_cb_coord[i] = coord[i] % subgrid_cb_nrow[i];
422
423 return local_site(subgrid_cb_coord, subgrid_cb_nrow) + cb*subgrid_vol_cb;
424 }
425
426
428
433 int nodeNumber(const multi1d<int>& coord)
434 {
435 multi1d<int> tmp_coord(Nd);
436
437 for(int i=0; i < coord.size(); ++i)
438 tmp_coord[i] = coord[i] / Layout::subgridLattSize()[i];
439
440 return Layout::getNodeNumberFrom(tmp_coord);
441 }
442
443
445
449 multi1d<int> siteCoords(int node, int linearsite) // ignore node
450 {
451 int subgrid_vol_cb = Layout::sitesOnNode() >> 1;
452 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
453 subgrid_cb_nrow[0] >>= 1;
454
455 // Get the base (origins) of the absolute lattice coord
456 multi1d<int> coord = getLogicalCoordFrom(node);
457 coord *= Layout::subgridLattSize();
458
459 int cb = linearsite / subgrid_vol_cb;
460 multi1d<int> tmp_coord = crtesn(linearsite % subgrid_vol_cb, subgrid_cb_nrow);
461
462 // Add on position within the node
463 // NOTE: the cb for the x-coord is not yet determined
464 coord[0] += 2*tmp_coord[0];
465 for(int m=1; m < Nd; ++m)
466 coord[m] += tmp_coord[m];
467
468 // Determine cb including global node cb
469 int cbb = cb;
470 for(int m=1; m < Nd; ++m)
471 cbb += coord[m];
472 coord[0] += (cbb & 1);
473
474 return coord;
475 }
476
477
479
481 {
482 multi1d<int> dim(Nd);
483 dim = 1;
484 dim[0] = 2; // must have multiple length 2 for cb
485
486 return dim;
487 }
488 }
489
490
491 //-----------------------------------------------------------------------------
492
493#elif QDP_USE_CB32_LAYOUT == 1
494
495QDPXX_MESSAGE("Using a 32 checkerboard layout")
496
497#error "THIS BIT STILL UNDER CONSTRUCTION"
498
499 namespace Layout
500 {
502
503 int linearSiteIndex(const multi1d<int>& coord)
504 {
505 int subgrid_vol_cb = Layout::sitesOnNode() >> (Nd+1);
506 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
507 subgrid_cb_nrow[0] >>= 2;
508 for(int i=1; i < Nd; ++i)
509 subgrid_cb_nrow[i] >>= 1;
510
511 int subl = coord[Nd-1] & 1;
512 for(int m=Nd-2; m >= 0; --m)
513 subl = (subl << 1) + (coord[m] & 1);
514
515 int cb = 0;
516 for(int m=0; m < Nd; ++m)
517 cb += coord[m] >> 1;
518
519 subl += (cb & 1) << Nd; // Final color or checkerboard
520
521 // Construct the checkerboard lattice coord
522 multi1d<int> subgrid_cb_coord(Nd);
523
524 subgrid_cb_coord[0] = (coord[0] >> 2) % subgrid_cb_nrow[0];
525 for(int i=1; i < Nd; ++i)
526 subgrid_cb_coord[i] = (coord[i] >> 1) % subgrid_cb_nrow[i];
527
528 return local_site(subgrid_cb_coord, subgrid_cb_nrow) + subl*subgrid_vol_cb;
529 }
530
531
533
538 int nodeNumber(const multi1d<int>& coord)
539 {
540 multi1d<int> tmp_coord(Nd);
541
542 for(int i=0; i < coord.size(); ++i)
543 tmp_coord[i] = coord[i] / Layout::subgridLattSize()[i];
544
545 return Layout::getNodeNumberFrom(tmp_coord);
546 }
547
548
550
554 multi1d<int> siteCoords(int node, int linearsite) // ignore node
555 {
556 int subgrid_vol_cb = Layout::sitesOnNode() >> (Nd+1);
557 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
558 subgrid_cb_nrow[0] >>= 2;
559 for(int i=1; i < Nd; ++i)
560 subgrid_cb_nrow[i] >>= 1;
561
562 // Get the base (origins) of the absolute lattice coord
563 multi1d<int> coord = Layout::getLogicalCoordFrom(node);
564 coord *= Layout::subgridLattSize();
565
566 int subl = linearsite / subgrid_vol_cb;
567 multi1d<int> tmp_coord = crtesn(linearsite % subgrid_vol_cb, subgrid_cb_nrow);
568
569 // Add on position within the node
570 // NOTE: the cb for the x-coord is not yet determined
571 coord[0] += tmp_coord[0] << 2;
572 for(int m=1; m < Nd; ++m)
573 coord[m] += tmp_coord[m] << 1;
574
575 int cb = 0;
576 for(int m=1; m<Nd; ++m)
577 cb += coord[m];
578 cb &= 1;
579
580 subl ^= (cb << Nd);
581 for(int m=0; m<Nd; ++m)
582 coord[m] ^= (subl & (1 << m)) >> m;
583 coord[0] ^= (subl & (1 << Nd)) >> (Nd-1); // this gets the hypercube cb
584
585 return coord;
586 }
587
588
590
591 multi1d<int> minimalLayoutMapping()
592 {
593 multi1d<int> dim(Nd);
594
595 dim[0] = 4; // must have multiple length 2 for cb and hypercube
596 for(int m=1; m < Nd; ++m)
597 dim[m] = 2; // must have multiple length 2 for hypercube
598
599 return dim;
600 }
601 }
602
603#else
604
605#error "no appropriate layout defined"
606
607#endif
608
609 //-----------------------------------------------------------------------------
610
611
612} // namespace QDP;
Container for a multi-dimensional 1D array.
Definition qdp_multi.h:25
int size() const
Size of array.
Definition qdp_multi.h:60
#define INNER_LEN
#define INNER_LOG
TextWriter & operator<<(TextWriter &txt, const std::string &output)
Definition qdp_io.cc:283
const int Nd
Definition qdp_params.h:24
Layout namespace holding info on problem size and machine info.
Definition qdp_layout.cc:16
int nodeNumber()
Returns the node number of this node.
struct QDP::Layout::LocalLayout_t _layout
const multi1d< int > & logicalSize()
Returns the logical size of this machine.
void setLattSize(const multi1d< int > &nrows)
Set virtual grid (problem grid) lattice size.
int linearSiteIndex(int site)
The linearized site index for the corresponding lexicographic site.
int sitesOnNode()
Subgrid lattice volume.
multi1d< int > siteCoords(int node, int index) QDP_CONST
Reconstruct the lattice coordinate from the node and site number.
void create()
Main lattice creation routine.
int outerSitesOnNode()
Subgrid lattice volume.
void initDefaults()
Initializer for all the layout defaults.
int getNodeNumberFrom(const multi1d< int > &node_coord)
Returns the node number given some logical node coordinate.
void init()
Initializer for layout.
int numNodes()
Returns the number of nodes.
const multi1d< int > & lattSize()
Virtual grid (problem grid) lattice size.
const multi1d< int > & subgridLattSize()
Subgrid (grid on each node) lattice size.
void setNumProc(int N)
Set number of processors in a multi-threaded implementation.
multi1d< int > getLogicalCoordFrom(int node)
Returns the logical node coordinates given some node number.
void setSMPFlag(bool flag)
Set SMP flag – true if using smp/multiprocessor mode on a node.
int vol()
Total lattice volume.
multi1d< int > minimalLayoutMapping()
Return the smallest lattice size per node allowed.
bool primaryNode()
Returns whether this is the primary node.
void destroy()
Main destruction routine.
const multi1d< int > & nodeCoord()
Returns the logical node coordinates for this node.
StandardOutputStream cout
Definition qdp_stdio.cc:21
void initDefaultRNG()
Initialize the random number generator with a default seed.
Definition qdp_random.cc:44
void finalizeRNG()
Yet another random number generator.
int getProgramProfileLevel()
bool QDP_isInitialized()
Is the machine initialized?
void QDP_error_exit(const char *format,...)
Simple error display and abort routine.
Definition qdp_util.cc:93
int local_site(const multi1d< int > &coord, const multi1d< int > &latt_size)
Calculates the lexicographic site index from the coordinate of a site.
void initDefaultMaps()
Initializer for maps.
Definition qdp_map.cc:42
void initDefaultSets()
Initializer for sets.
int setProfileLevel(int n)
multi1d< int > crtesn(int ipos, const multi1d< int > &latt_size)
Decompose a lexicographic site into coordinates.
int QDP_info(const char *format,...)
Simple information display routine.
Definition qdp_util.cc:43
Primary include file for QDP.
#define QDPXX_MESSAGE(s)
int subgrid_vol
Subgrid lattice volume.
int olattice_vol
Outer-subgrid lattice volume.
multi1d< int > logical_size
Logical system size.
int vol
Total lattice volume.
int num_nodes
Total number of nodes.
multi1d< int > nrow
Lattice size.
multi1d< int > logical_coord
Logical node coordinates.
multi1d< int > subgrid_nrow
Subgrid lattice size.