QDP++
qdp_parscalar_layout.cc
Go to the documentation of this file.
1
15
16#include "qdp_diagnostics.h"
17
18#include "qdp.h"
19#include "qdp_util.h"
20#include "qdp_allocator.h"
21#include "qmp.h"
22
23
24namespace QDP
25{
26
27 //----------------------------------Only defined here
28 template<class T>
29 std::ostream& operator<<(std::ostream& s, const multi1d<T>& s1)
30 {
31 for(int i=0; i < s1.size(); ++i)
32 s << " " << s1[i];
33
34 return s;
35 }
36
37 // Only relevant in case of pool allocator.
38 float pool_size_in_gb = 8.0;
39
40
41 //-----------------------------------------------------------------------------
42 namespace Layout
43 {
44
45 //-----------------------------------------------------
47
83
84
85 //-----------------------------------------------------
86 // Functions
87
90
92 void setLattSize(const multi1d<int>& nrows) {_layout.nrow = nrows;}
93
95
96 void setSMPFlag(bool flag) {}
97
99
100 void setNumProc(int N) {}
101
103 const multi1d<int>& lattSize() {return _layout.nrow;}
104
106 int vol() {return _layout.vol;}
107
109 int sitesOnNode() {return _layout.subgrid_vol;}
110
112 bool primaryNode() {return (_layout.node_rank == 0) ? true : false;}
113
115 const multi1d<int>& subgridLattSize() {return _layout.subgrid_nrow;}
116
118 int nodeNumber() {return _layout.node_rank;}
119
121 int numNodes() {return _layout.num_nodes;}
122
124 const multi1d<int>& nodeCoord() {return _layout.logical_coord;}
125
127 const multi1d<int>& logicalSize() {return _layout.logical_size;}
128
130
131 int getNodeNumberFrom(const multi1d<int>& node_coord)
132 {
133 return QMP_get_node_number_from(node_coord.slice());
134 }
135
137
139 {
140 multi1d<int> node_coord(Nd);
141 const int* node_crd = QMP_get_logical_coordinates_from(node); // QMP mallocs here
142
143 for(int i=0; i < Nd; ++i)
144 node_coord[i] = node_crd[i];
145
146 // Hackery as free cannot take a const void*, so grab
147 // node_crd with a non const pointer
148 int* non_const_node_crd = const_cast<int*>(node_crd);
149 free(non_const_node_crd); // free up QMP's memory
150 return node_coord;
151 }
152
155
157 void init()
158 {
159 _layout.num_nodes = QMP_get_number_of_nodes();
160 _layout.node_rank = QMP_get_node_number();
161
162 // Default should be current behaviour (as of 7/4/12)
163 // No iogrid is defined -> each node is its own I/O node
164 _layout.iogrid_defined = false;
165 _layout.num_iogrid = _layout.num_nodes;
166 }
167
168
169
171 int linearSiteIndex(int site)
172 {
173 multi1d<int> coord = crtesn(site, lattSize());
174
175 return linearSiteIndex(coord);
176 }
177
178
179
181
183 {
184 return _layout.iogrid_defined;
185 }
186
189 {
190
191
192 return _layout.num_iogrid;
193
194 }
195
197 void setIONodeGrid(const multi1d<int>& io_grid)
198 {
199 _layout.iogrid.resize(Nd);
200 for(int mu=0; mu < Nd; mu++) {
201 _layout.iogrid[mu] = io_grid[mu];
202 }
203 _layout.num_iogrid = io_grid[0];
204 for(int mu=1; mu < Nd; mu++) {
205 _layout.num_iogrid *= io_grid[mu];
206 }
207 _layout.iogrid_defined = true;
208 }
209
212 {
213 return _layout.iogrid;
214 }
215
218 {
219#if QDP_DEBUG >= 2
220 QDP_info("Create default subsets");
221#endif
222 // Default set and subsets
224
225 // Default maps
227
228 // Initialize RNG
230
231 // Set default profile level
233 }
234
235
237 void create()
238 {
239 if ( ! QDP_isInitialized() )
240 QDP_error_exit("QDP is not initialized");
241
242 if (_layout.nrow.size() != Nd)
243 QDP_error_exit("dimension of lattice size not the same as the default");
244
245 _layout.vol=1;
246 for(int i=0; i < Nd; ++i)
247 _layout.vol *= _layout.nrow[i];
248
249#if QDP_DEBUG >= 2
250 QDP_info("vol=%d",_layout.vol);
251#endif
252
253#if QDP_DEBUG >= 2
254 QDP_info("Initialize layout");
255#endif
256
257 // Simple check - we insist here that the total volume is divisible
258 // by the number of processors. Will also insist that the problem
259 // size is regular on each node
260 if (_layout.vol % numNodes() != 0)
261 QDP_error_exit("Layout::create - problem size not divisible by number of processors");
262
263
264 // Return the smallest lattice size per node allowed
266
267 // Another sanity check - if the specified lattice size is not a multiple
268 // of the minimal size, then barf
269 for(int i=0; i < Nd; ++i)
270 if (_layout.nrow[i] % min_dim[i] != 0)
271 QDP_error_exit("Layout::create - Error: problem size not multiple of smallest size allowed for this type of layout");
272
273
274 // Now, layout the machine. Note, if the logical_machine size was set previously
275 // it will be used
276 multi1d<int> nrow(Nd);
277 for(int i=0; i < Nd; ++i)
278 nrow[i] = _layout.nrow[i] / min_dim[i];
279
280 int* nrow_slice=const_cast<int*>(nrow.slice());
281 QMP_layout_grid(nrow_slice, Nd);
282
283
284 // Pull out useful stuff
285 const int* phys_size = QMP_get_logical_dimensions();
286 const int* phys_coord = QMP_get_logical_coordinates();
287
288 _layout.subgrid_nrow.resize(Nd);
289 _layout.logical_coord.resize(Nd);
290 _layout.logical_size.resize(Nd);
291
292 _layout.subgrid_vol = 1;
293
294 for(int i=0; i < Nd; ++i)
295 {
296 _layout.logical_coord[i] = phys_coord[i];
297 _layout.logical_size[i] = phys_size[i];
298 _layout.subgrid_nrow[i] = _layout.nrow[i] / _layout.logical_size[i];
299
300 _layout.subgrid_vol *= _layout.subgrid_nrow[i];
301 }
302
303 // Diagnostics
304 QDPIO::cout << "Lattice initialized:\n";
305 QDPIO::cout << " problem size =";
306 for(int i=0; i < Nd; ++i)
307 QDPIO::cout << " " << _layout.nrow[i];
308 QDPIO::cout << std::endl;
309
310 QDPIO::cout << " layout size =";
311 for(int i=0; i < Nd; ++i)
312 QDPIO::cout << " " << nrow[i];
313 QDPIO::cout << std::endl;
314
315 QDPIO::cout << " logical machine size =";
316 for(int i=0; i < Nd; ++i)
317 QDPIO::cout << " " << _layout.logical_size[i];
318 QDPIO::cout << std::endl;
319
320 QDPIO::cout << " subgrid size =";
321 for(int i=0; i < Nd; ++i)
322 QDPIO::cout << " " << _layout.subgrid_nrow[i];
323 QDPIO::cout << std::endl;
324
325 QDPIO::cout << " total number of nodes = " << Layout::numNodes() << std::endl;
326 QDPIO::cout << " total volume = " << _layout.vol << std::endl;
327 QDPIO::cout << " subgrid volume = " << _layout.subgrid_vol << std::endl;
328 if ( _layout.iogrid_defined ) {
329 QDPIO::cout << " Number of IO nodes = " << _layout.num_iogrid << std::endl;
330 QDPIO::cout << " IO grid size =";
331 for(int i=0; i < Nd; i++)
332 QDPIO::cout << " " << _layout.iogrid[i];
333 QDPIO::cout << std::endl;
334 }
335
336 // Sanity check - check the QMP node number functions
337 for(int node=0; node < Layout::numNodes(); ++node)
338 {
340 int node2 = Layout::getNodeNumberFrom(coord);
341
342 if (node != node2)
343 QDP_error_exit("Layout::create - Layout problems, the QMP logical to physical node map functions do not work correctly with this lattice size");
344 }
345
346 // Sanity check - check the layout functions make sense
347#if QDP_DEBUG >= 2
348 // BJ: Put this into a debug loop as it can take a serious amount of time for a really
349 // large lattice
350 for(int site=0; site < vol(); ++site)
351 {
352 multi1d<int> coord1 = crtesn(site, lattSize());
353
354 int linear = linearSiteIndex(coord1);
355 int node = nodeNumber(coord1);
356
357 multi1d<int> coord2 = siteCoords(node,linear);
358 int j = local_site(coord2, lattSize());
359
360#if QDP_DEBUG >= 3
361 QDP_info("site= %d coord= %d %d %d %d linear= %d node=%d crd=%d %d %d %d j= %d",
362 site,coord1[0],coord1[1],coord1[2],coord1[3],
363 linear,node,
364 coord2[0],coord2[1],coord2[2],coord2[3],
365 j);
366#endif
367 if (site != j)
368 QDP_error_exit("Layout::create - Layout problems, the layout functions do not work correctly with this lattice size");
369 }
370#endif
371
372
373 size_t pool_size_in_MB = static_cast<size_t>(floor(pool_size_in_gb*1024.0));
374
376
377 // Initialize various defaults
378 initDefaults();
379
380
381 QDPIO::cout << "Finished lattice layout" << std::endl;
382
383#if QDP_DEBUG >= 2
384 QDP_info("Layout successfully initialized");
385#endif
386 }
387 }
388
389
390 //-----------------------------------------------------------------------------
391#if QDP_USE_LEXICO_LAYOUT == 1
392
393QDPXX_MESSAGE("Using a lexicographic layout")
394
395 namespace Layout
396 {
398
399 int linearSiteIndex(const multi1d<int>& coord)
400 {
401 multi1d<int> tmp_coord(Nd);
402
403 for(int i=0; i < coord.size(); ++i)
404 tmp_coord[i] = coord[i] % Layout::subgridLattSize()[i];
405
406 return local_site(tmp_coord, Layout::subgridLattSize());
407 }
408
409
411
412 int nodeNumber(const multi1d<int>& coord)
413 {
414 multi1d<int> tmp_coord(Nd);
415
416 for(int i=0; i < coord.size(); ++i)
417 tmp_coord[i] = coord[i] / Layout::subgridLattSize()[i];
418
419 return Layout::getNodeNumberFrom(tmp_coord);
420 }
421
422
424
425 multi1d<int> siteCoords(int node, int linear)
426 {
427 multi1d<int> coord = getLogicalCoordFrom(node);
428
429 // Get the base (origins) of the absolute lattice coord
430 coord *= Layout::subgridLattSize();
431
432 // Find the coordinate within a node and accumulate
433 // This is a lexicographic ordering
434 coord += crtesn(linear, Layout::subgridLattSize());
435
436 return coord;
437 }
438
439
441
443 {
444 multi1d<int> dim(Nd);
445 dim = 1;
446
447 return dim;
448 }
449 }
450
451 //-----------------------------------------------------------------------------
452
453#elif QDP_USE_CB2_LAYOUT == 1
454
455QDPXX_MESSAGE("Using a 2 checkerboard (red/black) layout")
456
457 namespace Layout
458 {
460
461 int linearSiteIndex(const multi1d<int>& coord)
462 {
463 int subgrid_vol_cb = Layout::sitesOnNode() >> 1;
464 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
465 subgrid_cb_nrow[0] >>= 1;
466
467 int cb = 0;
468 for(int m=0; m < Nd; ++m)
469 cb += coord[m];
470 cb &= 1;
471
472 multi1d<int> subgrid_cb_coord(Nd);
473 subgrid_cb_coord[0] = (coord[0] >> 1) % subgrid_cb_nrow[0];
474 for(int i=1; i < Nd; ++i)
475 subgrid_cb_coord[i] = coord[i] % subgrid_cb_nrow[i];
476
477 return local_site(subgrid_cb_coord, subgrid_cb_nrow) + cb*subgrid_vol_cb;
478 }
479
480
482
487 int nodeNumber(const multi1d<int>& coord)
488 {
489 multi1d<int> tmp_coord(Nd);
490
491 for(int i=0; i < coord.size(); ++i)
492 tmp_coord[i] = coord[i] / Layout::subgridLattSize()[i];
493
494 return Layout::getNodeNumberFrom(tmp_coord);
495 }
496
497
499
503 multi1d<int> siteCoords(int node, int linearsite) // ignore node
504 {
505 int subgrid_vol_cb = Layout::sitesOnNode() >> 1;
506 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
507 subgrid_cb_nrow[0] >>= 1;
508
509 // Get the base (origins) of the absolute lattice coord
510 multi1d<int> coord = getLogicalCoordFrom(node);
511 coord *= Layout::subgridLattSize();
512
513 int cb = linearsite / subgrid_vol_cb;
514 multi1d<int> tmp_coord = crtesn(linearsite % subgrid_vol_cb, subgrid_cb_nrow);
515
516 // Add on position within the node
517 // NOTE: the cb for the x-coord is not yet determined
518 coord[0] += 2*tmp_coord[0];
519 for(int m=1; m < Nd; ++m)
520 coord[m] += tmp_coord[m];
521
522 // Determine cb including global node cb
523 int cbb = cb;
524 for(int m=1; m < Nd; ++m)
525 cbb += coord[m];
526 coord[0] += (cbb & 1);
527
528 return coord;
529 }
530
531
533
535 {
536 multi1d<int> dim(Nd);
537 dim = 1;
538 dim[0] = 2; // must have multiple length 2 for cb
539
540 return dim;
541 }
542 }
543
544 //-----------------------------------------------------------------------------
545
546#elif QDP_USE_CB3D_LAYOUT == 1
547
548QDPXX_MESSAGE("Using a 3D checkerboard (red/black) layout")
549
550 namespace Layout
551 {
553
554 int linearSiteIndex(const multi1d<int>& coord)
555 {
556 int subgrid_vol_cb = Layout::sitesOnNode() / 2;
557 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
558 subgrid_cb_nrow[0] /= 2;
559
560 int cb = 0;
561 for(int m=0; m < Nd-1; ++m) { // Nd-1 checkerboard
562 cb += coord[m];
563 }
564 cb &= 1;
565
566 multi1d<int> subgrid_cb_coord(Nd);
567 subgrid_cb_coord[0] = (coord[0] / 2) % subgrid_cb_nrow[0];
568 for(int i=1; i < Nd; ++i)
569 subgrid_cb_coord[i] = coord[i] % subgrid_cb_nrow[i];
570
571 return local_site(subgrid_cb_coord, subgrid_cb_nrow) + cb*subgrid_vol_cb;
572 }
573
574
576
581 int nodeNumber(const multi1d<int>& coord)
582 {
583 multi1d<int> tmp_coord(Nd);
584
585 for(int i=0; i < coord.size(); ++i)
586 tmp_coord[i] = coord[i] / Layout::subgridLattSize()[i];
587
588 return Layout::getNodeNumberFrom(tmp_coord);
589 }
590
591
593
597 multi1d<int> siteCoords(int node, int linearsite) // ignore node
598 {
599 int subgrid_vol_cb = Layout::sitesOnNode() / 2;
600 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
601 subgrid_cb_nrow[0] /= 2;
602
603
604 // Get the base (origins) of the absolute lattice coord
605 multi1d<int> coord = getLogicalCoordFrom(node);
606 coord *= Layout::subgridLattSize();
607
608 int cb = linearsite / subgrid_vol_cb;
609 multi1d<int> tmp_coord = crtesn(linearsite % subgrid_vol_cb, subgrid_cb_nrow);
610
611
612
613 // Add on position within the node
614 // NOTE: the cb for the x-coord is not yet determined
615 coord[0] += 2*tmp_coord[0];
616 for(int m=1; m < Nd; ++m)
617 coord[m] += tmp_coord[m];
618
619
620
621 // Determine cb including global node cb
622 int cbb = cb;
623 for(int m=1; m < Nd-1; ++m)
624 cbb += coord[m];
625
626
627 coord[0] += (cbb & 1);
628
629 return coord;
630 }
631
632
634
636 {
637 multi1d<int> dim(Nd);
638 multi1d<int> lsize=Layout::lattSize(); // Full lattice size;
639 dim = 1;
640 dim[0] = 2; // must have multiple length 2 for cb
641
642 return dim;
643 }
644 }
645
646
647 //-----------------------------------------------------------------------------
648
649#elif QDP_USE_CB32_LAYOUT == 1
650
651QDPXX_MESSAGE("Using a 32 checkerboard layout")
652
653#error "THIS BIT STILL UNDER CONSTRUCTION"
654
655 namespace Layout
656 {
658
659 int linearSiteIndex(const multi1d<int>& coord)
660 {
661 int subgrid_vol_cb = Layout::sitesOnNode() >> (Nd+1);
662 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
663 subgrid_cb_nrow[0] >>= 2;
664 for(int i=1; i < Nd; ++i)
665 subgrid_cb_nrow[i] >>= 1;
666
667 int subl = coord[Nd-1] & 1;
668 for(int m=Nd-2; m >= 0; --m)
669 subl = (subl << 1) + (coord[m] & 1);
670
671 int cb = 0;
672 for(int m=0; m < Nd; ++m)
673 cb += coord[m] >> 1;
674
675 subl += (cb & 1) << Nd; // Final color or checkerboard
676
677 // Construct the checkerboard lattice coord
678 multi1d<int> subgrid_cb_coord(Nd);
679
680 subgrid_cb_coord[0] = (coord[0] >> 2) % subgrid_cb_nrow[0];
681 for(int i=1; i < Nd; ++i)
682 subgrid_cb_coord[i] = (coord[i] >> 1) % subgrid_cb_nrow[i];
683
684 return local_site(subgrid_cb_coord, subgrid_cb_nrow) + subl*subgrid_vol_cb;
685 }
686
687
689
694 int nodeNumber(const multi1d<int>& coord)
695 {
696 multi1d<int> tmp_coord(Nd);
697
698 for(int i=0; i < coord.size(); ++i)
699 tmp_coord[i] = coord[i] / Layout::subgridLattSize()[i];
700
701 return Layout::getNodeNumberFrom(tmp_coord);
702 }
703
704
706
710 multi1d<int> siteCoords(int node, int linearsite) // ignore node
711 {
712 int subgrid_vol_cb = Layout::sitesOnNode() >> (Nd+1);
713 multi1d<int> subgrid_cb_nrow = Layout::subgridLattSize();
714 subgrid_cb_nrow[0] >>= 2;
715 for(int i=1; i < Nd; ++i)
716 subgrid_cb_nrow[i] >>= 1;
717
718 // Get the base (origins) of the absolute lattice coord
719 multi1d<int> coord = Layout::getLogicalCoordFrom(node);
720 coord *= Layout::subgridLattSize();
721
722 int subl = linearsite / subgrid_vol_cb;
723 multi1d<int> tmp_coord = crtesn(linearsite % subgrid_vol_cb, subgrid_cb_nrow);
724
725 // Add on position within the node
726 // NOTE: the cb for the x-coord is not yet determined
727 coord[0] += tmp_coord[0] << 2;
728 for(int m=1; m < Nd; ++m)
729 coord[m] += tmp_coord[m] << 1;
730
731 int cb = 0;
732 for(int m=1; m<Nd; ++m)
733 cb += coord[m];
734 cb &= 1;
735
736 subl ^= (cb << Nd);
737 for(int m=0; m<Nd; ++m)
738 coord[m] ^= (subl & (1 << m)) >> m;
739 coord[0] ^= (subl & (1 << Nd)) >> (Nd-1); // this gets the hypercube cb
740
741 return coord;
742 }
743
744
746
747 multi1d<int> minimalLayoutMapping()
748 {
749 multi1d<int> dim(Nd);
750
751 dim[0] = 4; // must have multiple length 2 for cb and hypercube
752 for(int m=1; m < Nd; ++m)
753 dim[m] = 2; // must have multiple length 2 for hypercube
754
755 return dim;
756 }
757 }
758
759#else
760
761#error "no appropriate layout defined"
762
763#endif
764
765 //-----------------------------------------------------------------------------
766
767
768} // namespace QDP;
Container for a multi-dimensional 1D array.
Definition qdp_multi.h:25
const T * slice() const
Return ref to a column slice.
Definition qdp_multi.h:225
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 setIONodeGrid(const multi1d< int > &io_grid)
Set the I/O Node grid – satisfy interface.
void create()
Main lattice creation routine.
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.
bool isIOGridDefined(void) QDP_CONST
check if I/O grid is defined
const multi1d< int > & subgridLattSize()
Subgrid (grid on each node) lattice size.
void setNumProc(int N)
Set number of processors in a multi-threaded implementation.
int numIONodeGrid(void) QDP_CONST
number of I/O nodes
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.
const multi1d< int > & getIONodeGrid() QDP_CONST
Get the I/O Node grid.
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.
MakeReturn< UnaryNode< FnFloor, typenameCreateLeaf< QDPExpr< T1, C1 > >::Leaf_t >, typenameUnaryReturn< C1, FnFloor >::Type_t >::Expression_t floor(const QDPExpr< T1, C1 > &l)
Definition qdp.h:5388
int setProfileLevel(int n)
multi1d< int > crtesn(int ipos, const multi1d< int > &latt_size)
Decompose a lexicographic site into coordinates.
float pool_size_in_gb
int QDP_info(const char *format,...)
Simple information display routine.
Definition qdp_util.cc:43
Primary include file for QDP.
#define QDP_CONST
Definition qdp.h:63
Catch-alls for all memory allocators.
#define QDPXX_MESSAGE(s)
Local data specific to all architectures.
int subgrid_vol
Subgrid lattice volume.
multi1d< int > logical_size
Logical system size.
int vol
Total lattice volume.
int num_nodes
Total number of nodes.
multi1d< int > iogrid
IO Grid size.
multi1d< int > nrow
Lattice size.
multi1d< int > logical_coord
Logical node coordinates.
multi1d< int > subgrid_nrow
Subgrid lattice size.