QDP++
qdp_parscalarvec_specific.h
Go to the documentation of this file.
1// -*- C++ -*-
2
6
7#ifndef QDP_PARSCALARVEC_SPECIFIC_H
8#define QDP_PARSCALARVEC_SPECIFIC_H
9
10#include "qmp.h"
11
12namespace QDP {
13
14//-----------------------------------------------------------------------------
15// Layout stuff specific to a parscalarvec architecture
16namespace Layout
17{
20
23}
24
25
26//-----------------------------------------------------------------------------
27// Internal ops with ties to QMP
28namespace QDPInternal
29{
31 void route(void *send_buf, int srce_node, int dest_node, int count);
32
34 void wait(int dir);
35
37 void sendToWait(void *send_buf, int dest_node, int count);
38
40 void recvFromWait(void *recv_buf, int srce_node, int count);
41
43
44 template<class T>
45 void sendToPrimaryNode(T& dest, int srcnode)
46 {
47 if (srcnode != 0)
48 {
50 recvFromWait((void *)&dest, srcnode, sizeof(T));
51
52 if (Layout::nodeNumber() == srcnode)
53 sendToWait((void *)&dest, 0, sizeof(T));
54 }
55 }
56
58 inline void sumAnUnsigned(void* inout, void* in)
59 {
60 *(unsigned int*)inout += *(unsigned int*)in;
61 }
62
64 inline void globalSumArray(unsigned int *dest, int len)
65 {
66 for(int i=0; i < len; i++, dest++)
67 QMP_binary_reduction(dest, sizeof(unsigned int), sumAnUnsigned);
68 }
69
71 inline void globalSumArray(int *dest, int len)
72 {
73 for(unsigned int i=0; i < len; i++, dest++)
74 QMP_sum_int(dest);
75 }
76
78 inline void globalSumArray(float *dest, int len)
79 {
80 QMP_sum_float_array(dest, len);
81 }
82
84 inline void globalSumArray(double *dest, int len)
85 {
86 QMP_sum_double_array(dest, len);
87 }
88
90 template<class T>
91 inline void globalSum(T& dest)
92 {
93 // The implementation here is relying on the structure being packed
94 // tightly in memory - no padding
95 typedef typename WordType<T>::Type_t W; // find the machine word type
96 globalSumArray((W *)&dest, sizeof(T)/sizeof(W)); // call appropriate hook
97 }
98
100 template<class T>
101 inline void broadcast(T& dest)
102 {
103 QMP_broadcast((void *)&dest, sizeof(T));
104 }
105
107 void broadcast_str(std::string& dest);
108
110 inline void broadcast(void* dest, size_t nbytes)
111 {
112 QMP_broadcast(dest, nbytes);
113 }
114
116 template<>
117 inline void broadcast(std::string& dest)
118 {
119 broadcast_str(dest);
120 }
121
122}
123
124#define QDP_NOT_IMPLEMENTED
125
126//-----------------------------------------------------------------------------
128
132template<class T, class T1, class Op, class RHS>
133//inline
134void evaluate(OLattice<T>& dest, const Op& op, const QDPExpr<RHS,OScalar<T1> >& rhs,
135 const Subset& s)
136{
137// cerr << "In evaluateUnorderedSubet(olattice,oscalar)\n";
138
139#if defined(QDP_USE_PROFILING)
140 static QDPProfile_t prof(dest, op, rhs);
141 prof.time -= getClockTime();
142#endif
143
144#if ! defined(QDP_NOT_IMPLEMENTED)
145 const int *tab = s.siteTable().slice();
146 for(int j=0; j < s.numSiteTable(); ++j)
147 {
148 int i = tab[j];
149// fprintf(stderr,"eval(olattice,oscalar): site %d\n",i);
150// op(dest.elem(i), forEach(rhs, ElemLeaf(), OpCombine()));
151 op(dest.elem(i), forEach(rhs, EvalLeaf1(0), OpCombine()));
152 }
153#else
154 QDP_error("evaluateSubset not implemented");
155#endif
156
157#if defined(QDP_USE_PROFILING)
158 prof.time += getClockTime();
159 prof.count++;
160 prof.print();
161#endif
162}
163
164
166
170template<class T, class T1, class Op, class RHS>
171//inline
172void evaluate(OLattice<T>& dest, const Op& op, const QDPExpr<RHS,OLattice<T1> >& rhs,
173 const Subset& s)
174{
175// cerr << "In evaluateSubset(olattice,olattice)" << endl;
176
177#if defined(QDP_USE_PROFILING)
178 static QDPProfile_t prof(dest, op, rhs);
179 prof.time -= getClockTime();
180#endif
181
182#if ! defined(QDP_NOT_IMPLEMENTED)
183 // General form of loop structure
184 const int *tab = s.siteTable().slice();
185 for(int j=0; j < s.numSiteTable(); ++j)
186 {
187 int i = tab[j];
188// fprintf(stderr,"eval(olattice,olattice): site %d\n",i);
189 op(dest.elem(i), forEach(rhs, EvalLeaf1(i), OpCombine()));
190 }
191#else
192 QDP_error("evaluateSubset not implemented");
193#endif
194
195#if defined(QDP_USE_PROFILING)
196 prof.time += getClockTime();
197 prof.count++;
198 prof.print();
199#endif
200}
201
202
203
204
205//-----------------------------------------------------------------------------
207template<class T1, class T2>
208void
210{
211 OLattice<T2>& dest = d.field();
212 const Subset& s = d.subset();
213
214#if ! defined(QDP_NOT_IMPLEMENTED)
215 const int *tab = s.siteTable().slice();
216 for(int j=0; j < s.numSiteTable(); ++j)
217 {
218 int i = tab[j];
219 copymask(dest.elem(i), mask.elem(i), s1.elem(i));
220 }
221#else
222 QDP_error("copymask_Subset not implemented");
223#endif
224}
225
226
228template<class T1, class T2>
229void
230copymask(OLattice<T2>& dest, const OLattice<T1>& mask, const OLattice<T2>& s1)
231{
232 const int iend = Layout::outerSitesOnNode();
233 for(int i=0; i < iend; ++i)
234 copymask(dest.elem(i), mask.elem(i), s1.elem(i));
235}
236
237
238
239//-----------------------------------------------------------------------------
240// Random numbers
241namespace RNG
242{
243 extern Seed ran_seed;
244 extern Seed ran_mult;
245 extern Seed ran_mult_n;
247}
248
249
251
252template<class T>
253void
254random(OScalar<T>& d)
255{
256 Seed seed = RNG::ran_seed;
257 Seed skewed_seed = RNG::ran_seed * RNG::ran_mult;
258
259 fill_random(d.elem(), seed, skewed_seed, RNG::ran_mult);
260
261 RNG::ran_seed = seed; // The seed from any site is the same as the new global seed
262}
263
264
266template<class T>
267void
268random(OLattice<T>& d, const Subset& s)
269{
270 Seed seed;
271 Seed skewed_seed;
272
273#if ! defined(QDP_NOT_IMPLEMENTED)
274#error "random(unorderedsubset) broken"
275 const int *tab = s.siteTable().slice();
276 for(int j=0; j < s.numSiteTable(); ++j)
277 {
278 int i = tab[j];
279 seed = RNG::ran_seed;
280 skewed_seed.elem() = RNG::ran_seed.elem() * RNG::lattice_ran_mult->elem(i);
281 fill_random(d.elem(i), seed, skewed_seed, RNG::ran_mult_n);
282 }
283
284 RNG::ran_seed = seed; // The seed from any site is the same as the new global seed
285#else
286 QDP_error("random_Subset not implemented");
287#endif
288}
289
290
292template<class T, class S>
294{
295 OLattice<T>& d = const_cast<OSubLattice<T,S>&>(dd).field();
296 const S& s = dd.subset();
297
298 random(d,s);
299}
300
301
303template<class T>
304void random(OLattice<T>& d)
305{
306 random(d,all);
307}
308
309
311template<class T>
312void gaussian(OLattice<T>& d, const Subset& s)
313{
314 OLattice<T> r1, r2;
315
316 random(r1,s);
317 random(r2,s);
318
319#if ! defined(QDP_NOT_IMPLEMENTED)
320 const int *tab = s.siteTable().slice();
321 for(int j=0; j < s.numSiteTable(); ++j)
322 {
323 int i = tab[j];
324 fill_gaussian(d.elem(i), r1.elem(i), r2.elem(i));
325 }
326#else
327 QDP_error("gaussianSubset not implemented");
328#endif
329}
330
331
332
334template<class T, class S>
336{
337 OLattice<T>& d = const_cast<OSubLattice<T,S>&>(dd).field();
338 const S& s = dd.subset();
339
340 gaussian(d,s);
341}
342
343
345template<class T>
346void gaussian(OLattice<T>& d)
347{
348 gaussian(d,all);
349}
350
351
352
353//-----------------------------------------------------------------------------
354// Broadcast operations
356template<class T>
357void zero_rep(OLattice<T>& dest, const Subset& s)
358{
359#if ! defined(QDP_NOT_IMPLEMENTED)
360 const int *tab = s.siteTable().slice();
361 for(int j=0; j < s.numSiteTable(); ++j)
362 {
363 int i = tab[j];
364 zero_rep(dest.elem(i));
365 }
366#else
367 QDP_error("zero_rep_Subset not implemented");
368#endif
369}
370
371
372
374template<class T, class S>
376{
377 OLattice<T>& d = dd.field();
378 const S& s = dd.subset();
379
380 zero_rep(d,s);
381}
382
383
385template<class T>
386void zero_rep(OLattice<T>& dest)
387{
388 const int iend = Layout::outerSitesOnNode();
389 for(int i=0; i < iend; ++i)
390 zero_rep(dest.elem(i));
391}
392
393
394
395//-----------------------------------------------
396// Global sums
398
402template<class RHS, class T>
403typename UnaryReturn<OScalar<T>, FnSum>::Type_t
404sum(const QDPExpr<RHS,OScalar<T> >& s1, const Subset& s)
405{
406 typename UnaryReturn<OScalar<T>, FnSum>::Type_t d;
407
408#if defined(QDP_USE_PROFILING)
409 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
410 prof.time -= getClockTime();
411#endif
412
413 evaluate(d,OpAssign(),s1,all);
414
415#if defined(QDP_USE_PROFILING)
416 prof.time += getClockTime();
417 prof.count++;
418 prof.print();
419#endif
420
421 return d;
422}
423
424
426
430template<class RHS, class T>
431typename UnaryReturn<OScalar<T>, FnSum>::Type_t
432sum(const QDPExpr<RHS,OScalar<T> >& s1)
433{
434 typename UnaryReturn<OScalar<T>, FnSum>::Type_t d;
435
436#if defined(QDP_USE_PROFILING)
437 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
438 prof.time -= getClockTime();
439#endif
440
441 evaluate(d,OpAssign(),s1,all); // since OScalar, no global sum needed
442
443#if defined(QDP_USE_PROFILING)
444 prof.time += getClockTime();
445 prof.count++;
446 prof.print();
447#endif
448
449 return d;
450}
451
452
453
455
464template<class RHS, class T>
465typename UnaryReturn<OLattice<T>, FnSum>::Type_t
466sum(const QDPExpr<RHS,OLattice<T> >& s1, const Subset& s)
467{
468 typename UnaryReturn<OLattice<T>, FnSum>::Type_t d;
469 OScalar<T> tmp; // Note, expect to have ILattice inner grid
470
471#if defined(QDP_USE_PROFILING)
472 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
473 prof.time -= getClockTime();
474#endif
475
476 // Must initialize to zero since we do not know if the loop will be entered
477 zero_rep(d.elem());
478
479 if (s.hasOrderedRep())
480 {
481 const int istart = s.start() >> INNER_LOG;
482 const int iend = s.end() >> INNER_LOG;
483
484 for(int i=istart; i <= iend; ++i)
485 {
486 tmp.elem() = forEach(s1, EvalLeaf1(i), OpCombine()); // Evaluate to ILattice part
487 d.elem() += sum(tmp.elem()); // sum as well the ILattice part
488 }
489 }
490 else
491 {
492 const int *tab = s.siteTable().slice();
493 for(int j=0; j < s.numSiteTable(); ++j)
494 {
495 int i = tab[j];
496 int outersite = i >> INNER_LOG;
497 int innersite = i & (INNER_LEN-1);
498
499 tmp.elem() = forEach(s1, EvalLeaf1(outersite), OpCombine()); // Evaluate to ILattice part
500 d.elem() += getSite(tmp.elem(),innersite); // wasteful - only extract a single site worth
501 }
502 }
503
504 // Do a global sum on the result
506
507#if defined(QDP_USE_PROFILING)
508 prof.time += getClockTime();
509 prof.count++;
510 prof.print();
511#endif
512
513 return d;
514}
515
516
517
518
519
521
525template<class RHS, class T>
526typename UnaryReturn<OLattice<T>, FnSum>::Type_t
527sum(const QDPExpr<RHS,OLattice<T> >& s1)
528{
529 return sum(s1,all);
530}
531
532
533//-----------------------------------------------------------------------------
534// Multiple global sums
536
543template<class RHS, class T>
544typename UnaryReturn<OScalar<T>, FnSum>::Type_t
545sumMulti(const QDPExpr<RHS,OScalar<T> >& s1, const Set& ss)
546{
548
549#if defined(QDP_USE_PROFILING)
550 static QDPProfile_t prof(dest[0], OpAssign(), FnSum(), s1);
551 prof.time -= getClockTime();
552#endif
553
554 // lazy - evaluate repeatedly
555 for(int i=0; i < ss.numSubsets(); ++i)
556 dest[i] = sum(s1,ss[i]);
557
558#if defined(QDP_USE_PROFILING)
559 prof.time += getClockTime();
560 prof.count++;
561 prof.print();
562#endif
563
564 return dest;
565}
566
567
569
577template<class RHS, class T>
578typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t
579sumMulti(const QDPExpr<RHS,OLattice<T> >& s1, const Set& ss)
580{
581 typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t dest(ss.numSubsets());
582
583#if defined(QDP_USE_PROFILING)
584 static QDPProfile_t prof(dest[0], OpAssign(), FnSum(), s1);
585 prof.time -= getClockTime();
586#endif
587
588 // lazy - evaluate repeatedly
589 for(int i=0; i < ss.numSubsets(); ++i)
590 dest[i] = sum(s1,ss[i]);
591
592#if defined(QDP_USE_PROFILING)
593 prof.time += getClockTime();
594 prof.count++;
595 prof.print();
596#endif
597
598 return dest;
599}
600
601
602//-----------------------------------------------------------------------------
603// Multiple global sums
605
612template<class T>
613multi2d<typename UnaryReturn<OScalar<T>, FnSum>::Type_t>
614sumMulti(const multi1d< OScalar<T> >& s1, const Set& ss)
615{
616 multi2d<typename UnaryReturn<OScalar<T>, FnSum>::Type_t> dest(s1.size(), ss.numSubsets());
617
618#if defined(QDP_USE_PROFILING)
619 static QDPProfile_t prof(dest(0,0), OpAssign(), FnSum(), s1);
620 prof.time -= getClockTime();
621#endif
622
623 // lazy - evaluate repeatedly
624 for(int i=0; i < dest.size1(); ++i)
625 for(int j=0; j < dest.size2(); ++j)
626 dest(j,i) = s1[j];
627
628#if defined(QDP_USE_PROFILING)
629 prof.time += getClockTime();
630 prof.count++;
631 prof.print();
632#endif
633
634 return dest;
635}
636
637
639
647template<class T>
648multi2d<typename UnaryReturn<OLattice<T>, FnSum>::Type_t>
649sumMulti(const multi1d< OLattice<T> >& s1, const Set& ss)
650{
651 multi2d<typename UnaryReturn<OLattice<T>, FnSum>::Type_t> dest(s1.size(),ss.numSubsets());
652
653#if defined(QDP_USE_PROFILING)
654 static QDPProfile_t prof(dest(0,0), OpAssign(), FnSum(), s1);
655 prof.time -= getClockTime();
656#endif
657
658 // lazy - evaluate repeatedly
659 for(int k=0; k < s1.size(); ++k)
660 for(int i=0; i < ss.numSubsets(); ++i)
661 dest(k,i) = sum(s1[k],ss[i]);
662
663#if defined(QDP_USE_PROFILING)
664 prof.time += getClockTime();
665 prof.count++;
666 prof.print();
667#endif
668
669 return dest;
670}
671
672
673//-----------------------------------------------------------------------------
675
681template<class T>
682inline typename UnaryReturn<OScalar<T>, FnNorm2>::Type_t
683norm2(const multi1d< OScalar<T> >& s1)
684{
685 typename UnaryReturn<OScalar<T>, FnNorm2>::Type_t d;
686
687#if defined(QDP_USE_PROFILING)
688 static QDPProfile_t prof(d, OpAssign(), FnNorm2(), s1[0]);
689 prof.time -= getClockTime();
690#endif
691
692 // Possibly loop entered
693 zero_rep(d.elem());
694
695 for(int n=0; n < s1.size(); ++n)
696 {
697 OScalar<T>& ss1 = s1[n];
698 d.elem() += localNorm2(ss1.elem());
699 }
700
701#if defined(QDP_USE_PROFILING)
702 prof.time += getClockTime();
703 prof.count++;
704 prof.print();
705#endif
706
707 return d;
708}
709
711
712template<class T>
713inline typename UnaryReturn<OScalar<T>, FnNorm2>::Type_t
714norm2(const multi1d< OScalar<T> >& s1, const Subset& s)
715{
716 return norm2(s1);
717}
718
719
721
727template<class T>
728inline typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t
729norm2(const multi1d< OLattice<T> >& s1, const Subset& s)
730{
731 typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t d;
732
733#if defined(QDP_USE_PROFILING)
734 static QDPProfile_t prof(d, OpAssign(), FnNorm2(), s1[0]);
735 prof.time -= getClockTime();
736#endif
737
738 // Possibly loop entered
739 zero_rep(d.elem());
740
741#if ! defined(QDP_NOT_IMPLEMENTED)
742 const int *tab = s.siteTable().slice();
743 for(int n=0; n < s1.size(); ++n)
744 {
745 const OLattice<T>& ss1 = s1[n];
746 for(int j=0; j < s.numSiteTable(); ++j)
747 {
748 int i = tab[j];
749 d.elem() += localNorm2(ss1.elem(i));
750 }
751 }
752#else
753 QDP_error_exit("norm2-Subset not implemented");
754#endif
755
756 // Do a global sum on the result
758
759#if defined(QDP_USE_PROFILING)
760 prof.time += getClockTime();
761 prof.count++;
762 prof.print();
763#endif
764
765 return d;
766}
767
768
769
771
777template<class T>
778inline typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t
779norm2(const multi1d< OLattice<T> >& s1)
780{
781 return norm2(s1,all);
782}
783
784
785//-----------------------------------------------------------------------------
786// Peek and poke at individual sites. This is very architecture specific
787// NOTE: these two routines assume there is no underlying inner grid
788
790
796template<class T1>
797inline typename UnaryReturn<OScalar<T1>, FnPeekSite>::Type_t
798peekSite(const OScalar<T1>& l, const multi1d<int>& coord)
799{
800 return l;
801}
802
804
810template<class RHS, class T1>
811inline OScalar<T1>
812peekSite(const QDPExpr<RHS,OScalar<T1> > & l, const multi1d<int>& coord)
813{
814 // For now, simply evaluate the expression and then call the function
815 typedef OScalar<T1> C1;
816
817 return peekSite(C1(l), coord);
818}
819
820
822
828template<class T1>
830peekSite(const OLattice<T1>& l, const multi1d<int>& coord)
831{
833 int nodenum = Layout::nodeNumber(coord);
834
835 // Find the result somewhere within the machine.
836 // Then we must get it to node zero so we can broadcast it
837 // out to all nodes
838 if (Layout::nodeNumber() == nodenum)
839 {
840 int i = Layout::linearSiteIndex(coord);
841 int iouter = i >> INNER_LOG;
842 int iinner = i & ((1 << INNER_LOG)-1);
843 dest.elem() = getSite(l.elem(iouter), iinner);
844 }
845 else
846 zero_rep(dest.elem());
847
848 // Send result to primary node via some mechanism
849 QDPInternal::sendToPrimaryNode(dest, nodenum);
850
851 // Now broadcast back out to all nodes
853
854 return dest;
855}
856
858
864template<class RHS, class T1>
865inline OScalar<T1>
866peekSite(const QDPExpr<RHS,OLattice<T1> > & l, const multi1d<int>& coord)
867{
868 // For now, simply evaluate the expression and then call the function
869 typedef OLattice<T1> C1;
870
871 return peekSite(C1(l), coord);
872}
873
874
876
883template<class T1, class T2>
884inline OLattice<T1>&
886{
888 {
889 int i = Layout::linearSiteIndex(coord);
890 int iouter = i >> INNER_LOG;
891 int iinner = i & ((1 << INNER_LOG)-1);
892 copy_site(l.elem(iouter), iinner, r.elem());
893 }
894 return l;
895}
896
897
899
905template<class T>
906inline void
908 const OLattice<T>& src, const Subset& s)
909{
910 const int *tab = s.siteTable().slice();
911 for(int j=0; j < s.numSiteTable(); ++j)
912 {
913 int i = tab[j];
914 int iouter = i >> INNER_LOG;
915 int iinner = i & ((1 << INNER_LOG)-1);
916
917 dest[i].elem() = getSite(src.elem(iouter),iinner);
918 }
919}
920
921
923
929template<class T>
930inline void
932 const multi1d<OScalar<typename UnaryReturn<T, FnGetSite>::Type_t> >& src,
933 const Subset& s)
934{
935 const int *tab = s.siteTable().slice();
936 for(int j=0; j < s.numSiteTable(); ++j)
937 {
938 int i = tab[j];
939 int iouter = i >> INNER_LOG;
940 int iinner = i & ((1 << INNER_LOG)-1);
941 copy_site(dest.elem(iouter), iinner, src[i].elem());
942 }
943}
944
945
946
947//-----------------------------------------------------------------------------
948// Map
949//
950// Empty map
951struct FnMap
952{
954};
955
956#if defined(QDP_USE_PROFILING)
957template <>
958struct TagVisitor<FnMap, PrintTag> : public ParenPrinter<FnMap>
959{
960 static void visit(FnMap op, PrintTag t)
961 { t.os_m << "shift"; }
962};
963#endif
964
965
967class Map
968{
969public:
971 Map() {}
972
974 ~Map() {}
975
977 Map(const MapFunc& fn) {make(fn);}
978
980
981 void make(const MapFunc& func);
982
984
993 template<class T1>
996 {
997 OLattice<T1> d;
998 int nodeSites = Layout::sitesOnNode();
999
1000#if QDP_DEBUG >= 3
1001 QDP_info("Map()");
1002#endif
1003
1004 typedef typename UnaryReturn<T1, FnGetSite>::Type_t Site_t; // strip-off inner-grid
1005
1006 if (offnodeP)
1007 {
1008 // Off-node communications required
1009#if QDP_DEBUG >= 3
1010 QDP_info("Map: off-node communications required");
1011#endif
1012
1013 // Eventually these declarations should move into d - the return object
1014 typedef Site_t * T1ptr;
1015
1016
1017 Site_t **dest = new T1ptr[nodeSites];
1018 if( dest == 0x0 ) {
1019 QDP_error_exit("Unable to new memory in OLattice<T1>::operator()\n");
1020 }
1021 QMP_msgmem_t msg[2];
1022 QMP_msghandle_t mh_a[2], mh;
1023
1024 //------------
1025 // yukky hack - transform all source to packed format
1026 Site_t *ll = new Site_t[nodeSites];
1027 if ( ll == 0x0 ) {
1028 QDP_error_exit("Unable to new memory in OLattice<T1>::operator()\n");
1029 }
1030 for(int i=0; i < nodeSites; ++i)
1031 {
1032 int iouter = i >> INNER_LOG;
1033 int iinner = i & (INNER_LEN - 1);
1034
1035 ll[i] = getSite(l.elem(iouter), iinner);
1036 }
1037 //-------------
1038
1039
1040 int dstnum = destnodes_num[0]*sizeof(Site_t);
1041 int srcnum = srcenodes_num[0]*sizeof(Site_t);
1042 QMP_mem_t* send_buf_mem_t;
1043 QMP_mem_t* recv_buf_mem_t;
1044
1045 send_buf_mem_t = QMP_allocate_aligned_memory(dstnum,QDP_ALIGNMENT_SIZE,(QMP_MEM_COMMS|QMP_MEM_FAST)); // packed data to send
1046 if( send_buf_mem_t == 0x0 ) {
1047 send_buf_mem_t = QMP_allocate_aligned_memory(dstnum, QDP_ALIGNMENT_SIZE, QMP_MEM_COMMS);
1048 if( send_buf_mem_t == 0x0) {
1049 QDP_error_exit("QMP_allocate_aligned_memory failed (send_buf_mem_t)\n");
1050 }
1051 }
1052
1053 Site_t* send_buf=(Site_t *)QMP_get_memory_pointer(send_buf_mem_t);
1054 if( send_buf == 0x0 ) {
1055 QDP_error_exit("QMP_get_memory_pointer returned NULL pointer from non NULL QMP_mem_t (send_buf)\n");
1056 }
1057
1058 recv_buf_mem_t = QMP_allocate_aligned_memory(srcnum,QDP_ALIGNMENT_SIZE,(QMP_MEM_COMMS|QMP_MEM_FAST)); // packed receive data
1059 if( recv_buf_mem_t == 0x0 ) {
1060 recv_buf_mem_t = QMP_allocate_aligned_memory(srcnum, QDP_ALIGNMENT_SIZE, QMP_MEM_COMMS);
1061 if( recv_buf_mem_t == 0x0 ) {
1062 QDP_error_exit("QMP_allocate_aligned_memory failed (recv_buf_mem_t)\n");
1063 }
1064 }
1065 Site_t* recv_buf=(Site_t *)QMP_get_memory_pointer(recv_buf_mem_t);
1066 if (recv_buf == 0x0) {
1067 QDP_error_exit("QMP_get_memory_pointer returned NULL pointer from non NULL QMP_mem_t (recv_buf)\n");
1068 }
1069
1070 const int my_node = Layout::nodeNumber();
1071
1072 // Gather the face of data to send
1073 // For now, use the all subset
1074 for(int si=0; si < soffsets.size(); ++si)
1075 {
1076#if QDP_DEBUG >= 3
1077 QDP_info("Map_scatter_send(buf[%d],olattice[%d])",si,soffsets[si]);
1078#endif
1079
1080 send_buf[si] = ll[soffsets[si]];
1081 }
1082
1083 // Set the dest gather pointers
1084 // For now, use the all subset
1085 for(int i=0, ri=0; i < nodeSites; ++i)
1086 {
1087 if (srcnode[i] != my_node)
1088 {
1089#if QDP_DEBUG >= 3
1090 QDP_info("Map_gather_recv(olattice[%d],recv[%d])",i,ri);
1091#endif
1092
1093 dest[i] = &(recv_buf[ri++]);
1094 }
1095 else
1096 {
1097#if QDP_DEBUG >= 3
1098 QDP_info("Map_gather_onnode(olattice[%d],olattice[%d])",i,goffsets[i]);
1099#endif
1100
1101 dest[i] = &(ll[goffsets[i]]);
1102 }
1103 }
1104
1105 QMP_status_t err;
1106
1107#if QDP_DEBUG >= 3
1108 QDP_info("Map: send = 0x%x recv = 0x%x",send_buf,recv_buf);
1109#endif
1110
1111 msg[0] = QMP_declare_msgmem(recv_buf, srcnum);
1112 if( msg[0] == (QMP_msgmem_t)NULL ) {
1113 QDP_error_exit("QMP_declare_msgmem for msg[0] failed in Map::operator()\n");
1114 }
1115 msg[1] = QMP_declare_msgmem(send_buf, dstnum);
1116 if( msg[1] == (QMP_msgmem_t)NULL ) {
1117 QDP_error_exit("QMP_declare_msgmem for msg[1] failed in Map::operator()\n");
1118 }
1119
1120 mh_a[0] = QMP_declare_receive_from(msg[0], srcenodes[0], 0);
1121 if( mh_a[0] == (QMP_msghandle_t)NULL ) {
1122 QDP_error_exit("QMP_declare_receive_from for mh_a[0] failed in Map::operator()\n");
1123 }
1124
1125 mh_a[1] = QMP_declare_send_to(msg[1], destnodes[0], 0);
1126 if( mh_a[1] == (QMP_msghandle_t)NULL ) {
1127 QDP_error_exit("QMP_declare_send_to for mh_a[1] failed in Map::operator()\n");
1128 }
1129
1130 mh = QMP_declare_multiple(mh_a, 2);
1131 if( mh == (QMP_msghandle_t)NULL ) {
1132 QDP_error_exit("QMP_declare_multiple for mh failed in Map::operator()\n");
1133 }
1134
1135
1136#if QDP_DEBUG >= 3
1137 QDP_info("Map: calling start send=%d recv=%d",destnodes[0],srcenodes[0]);
1138#endif
1139
1140 // Launch the faces
1141 if ((err = QMP_start(mh)) != QMP_SUCCESS)
1142 QDP_error_exit(QMP_error_string(err));
1143
1144#if QDP_DEBUG >= 3
1145 QDP_info("Map: calling wait");
1146#endif
1147
1148 // Wait on the faces
1149 if ((err = QMP_wait(mh)) != QMP_SUCCESS)
1150 QDP_error_exit(QMP_error_string(err));
1151
1152#if QDP_DEBUG >= 3
1153 QDP_info("Map: calling free msgs");
1154#endif
1155
1156 /* QMP_free_msghandle(mh_a[1]); */
1157 /* QMP_free_msghandle(mh_a[0]); */
1158 QMP_free_msghandle(mh);
1159 QMP_free_msgmem(msg[1]);
1160 QMP_free_msgmem(msg[0]);
1161
1162 // Scatter the data into the destination
1163 // Some of the data maybe in receive buffers
1164 // For now, use the all subset
1165 for(int i=0; i < nodeSites; ++i)
1166 {
1167#if QDP_DEBUG >= 3
1168 QDP_info("Map_scatter(olattice[%d],olattice[0x%x])",i,dest[i]);
1169#endif
1170 int iouter = i >> INNER_LOG;
1171 int iinner = i & (INNER_LEN-1);
1172
1173 copy_site(d.elem(iouter), iinner, *(dest[i])); // slow - should use gather_sites
1174 }
1175
1176 // Cleanup
1177 QMP_free_memory(recv_buf_mem_t);
1178 QMP_free_memory(send_buf_mem_t);
1179 delete[] ll;
1180 delete[] dest;
1181
1182#if QDP_DEBUG >= 3
1183 QDP_info("finished cleanup");
1184#endif
1185 }
1186 else
1187 {
1188 // No off-node communications - copy on node
1189#if QDP_DEBUG >= 3
1190 QDP_info("Map: copy on node - no communications, try this");
1191#endif
1192
1193 // *** SHOULD IMPROVE THIS - JUST GET IT TO WORK FIRST ***
1194 // For now, use the all subset
1195#if INNER_LOG == 2
1196
1197 for(int i=0; i < nodeSites; i+= INNER_LEN)
1198 {
1199 int ii = i >> INNER_LOG;
1200 int o0 = goffsets[i+0] >> INNER_LOG;
1201 int i0 = goffsets[i+0] & (INNER_LEN - 1);
1202
1203 int o1 = goffsets[i+1] >> INNER_LOG;
1204 int i1 = goffsets[i+1] & (INNER_LEN - 1);
1205
1206 int o2 = goffsets[i+2] >> INNER_LOG;
1207 int i2 = goffsets[i+2] & (INNER_LEN - 1);
1208
1209 int o3 = goffsets[i+3] >> INNER_LOG;
1210 int i3 = goffsets[i+3] & (INNER_LEN - 1);
1211
1212#if QDP_DEBUG >= 3
1213 QDP_info("Map(lattice[%d]=lattice([%d,%d],[%d,%d],[%d,%d],[%d,%d])",
1214 ii,o0,i0,o1,i1,o2,i2,o3,i3);
1215#endif
1216
1217 // Gather 4 inner-grid sites together
1218 gather_sites(d.elem(ii),
1219 l.elem(o0),i0,
1220 l.elem(o1),i1,
1221 l.elem(o2),i2,
1222 l.elem(o3),i3);
1223 }
1224
1225#else
1226#error "Map: this inner grid length is not supported - easy to fix"
1227#endif
1228
1229 }
1230
1231#if QDP_DEBUG >= 3
1232 QDP_info("exiting Map()");
1233#endif
1234
1235 return d;
1236 }
1237
1238
1239 template<class T1>
1242 {
1243 return l;
1244 }
1245
1246 template<class RHS, class T1>
1249 {
1250 // For now, simply evaluate the expression and then do the map
1251 typedef OScalar<T1> C1;
1252
1253// fprintf(stderr,"map(QDPExpr<OScalar>)\n");
1254 OScalar<T1> d = this->operator()(C1(l));
1255
1256 return d;
1257 }
1258
1259 template<class RHS, class T1>
1262 {
1263 // For now, simply evaluate the expression and then do the map
1264 typedef OLattice<T1> C1;
1265
1266// fprintf(stderr,"map(QDPExpr<OLattice>)\n");
1267 OLattice<T1> d = this->operator()(C1(l));
1268
1269 return d;
1270 }
1271
1272
1273public:
1275 const multi1d<int>& goffset() const {return goffsets;}
1276 const multi1d<int>& soffset() const {return soffsets;}
1277
1278private:
1280 Map(const Map&) {}
1281
1283 void operator=(const Map&) {}
1284
1285private:
1287
1291 multi1d<int> goffsets;
1292 multi1d<int> soffsets;
1293 multi1d<int> srcnode;
1294 multi1d<int> dstnode;
1295
1296 multi1d<int> srcenodes;
1297 multi1d<int> destnodes;
1298
1299 multi1d<int> srcenodes_num;
1300 multi1d<int> destnodes_num;
1301
1302 // Indicate off-node communications is needed;
1303 bool offnodeP;
1304};
1305
1306
1307//-----------------------------------------------------------------------------
1309class ArrayMap
1310{
1311public:
1314
1317
1319 ArrayMap(const ArrayMapFunc& fn) {make(fn);}
1320
1322
1323 void make(const ArrayMapFunc& func);
1324
1326
1335 template<class T1>
1337 operator()(const OLattice<T1> & l, int dir)
1338 {
1339#if QDP_DEBUG >= 3
1340 QDP_info("ArrayMap(OLattice,%d)",dir);
1341#endif
1342
1343 return mapsa[dir](l);
1344 }
1345
1346 template<class T1>
1348 operator()(const OScalar<T1> & l, int dir)
1349 {
1350#if QDP_DEBUG >= 3
1351 QDP_info("ArrayMap(OScalar,%d)",dir);
1352#endif
1353
1354 return mapsa[dir](l);
1355 }
1356
1357
1358 template<class RHS, class T1>
1360 operator()(const QDPExpr<RHS,OScalar<T1> > & l, int dir)
1361 {
1362// fprintf(stderr,"ArrayMap(QDPExpr<OScalar>,%d)\n",dir);
1363
1364 // For now, simply evaluate the expression and then do the map
1365 return mapsa[dir](l);
1366 }
1367
1368 template<class RHS, class T1>
1370 operator()(const QDPExpr<RHS,OLattice<T1> > & l, int dir)
1371 {
1372// fprintf(stderr,"ArrayMap(QDPExpr<OLattice>,%d)\n",dir);
1373
1374 // For now, simply evaluate the expression and then do the map
1375 return mapsa[dir](l);
1376 }
1377
1378
1379private:
1381 ArrayMap(const ArrayMap&) {}
1382
1384 void operator=(const ArrayMap&) {}
1385
1386private:
1387 multi1d<Map> mapsa;
1388
1389};
1390
1391//-----------------------------------------------------------------------------
1393class BiDirectionalMap
1394{
1395public:
1398
1401
1404
1406
1407 void make(const MapFunc& func);
1408
1410
1419 template<class T1>
1421 operator()(const OLattice<T1> & l, int isign)
1422 {
1423#if QDP_DEBUG >= 3
1424 QDP_info("BiDirectionalMap(OLattice,%d)",isign);
1425#endif
1426
1427 return bimaps[(isign+1)>>1](l);
1428 }
1429
1430
1431 template<class T1>
1433 operator()(const OScalar<T1> & l, int isign)
1434 {
1435#if QDP_DEBUG >= 3
1436 QDP_info("BiDirectionalMap(OScalar,%d)",isign);
1437#endif
1438
1439 return bimaps[(isign+1)>>1](l);
1440 }
1441
1442
1443 template<class RHS, class T1>
1445 operator()(const QDPExpr<RHS,OScalar<T1> > & l, int isign)
1446 {
1447// fprintf(stderr,"BiDirectionalMap(QDPExpr<OScalar>,%d)\n",isign);
1448
1449 // For now, simply evaluate the expression and then do the map
1450 return bimaps[(isign+1)>>1](l);
1451 }
1452
1453 template<class RHS, class T1>
1455 operator()(const QDPExpr<RHS,OLattice<T1> > & l, int isign)
1456 {
1457// fprintf(stderr,"BiDirectionalMap(QDPExpr<OLattice>,%d)\n",isign);
1458
1459 // For now, simply evaluate the expression and then do the map
1460 return bimaps[(isign+1)>>1](l);
1461 }
1462
1463
1464private:
1467
1469 void operator=(const BiDirectionalMap&) {}
1470
1471private:
1472 multi1d<Map> bimaps;
1473
1474};
1475
1476
1477//-----------------------------------------------------------------------------
1479class ArrayBiDirectionalMap
1480{
1481public:
1484
1487
1490
1492
1493 void make(const ArrayMapFunc& func);
1494
1496
1513 template<class T1>
1515 operator()(const OLattice<T1> & l, int isign, int dir)
1516 {
1517#if QDP_DEBUG >= 3
1518 QDP_info("ArrayBiDirectionalMap(OLattice,%d,%d)",isign,dir);
1519#endif
1520
1521 return bimapsa((isign+1)>>1,dir)(l);
1522 }
1523
1524 template<class T1>
1526 operator()(const OScalar<T1> & l, int isign, int dir)
1527 {
1528#if QDP_DEBUG >= 3
1529 QDP_info("ArrayBiDirectionalMap(OScalar,%d,%d)",isign,dir);
1530#endif
1531
1532 return bimapsa((isign+1)>>1,dir)(l);
1533 }
1534
1535
1536 template<class RHS, class T1>
1538 operator()(const QDPExpr<RHS,OScalar<T1> > & l, int isign, int dir)
1539 {
1540// fprintf(stderr,"ArrayBiDirectionalMap(QDPExpr<OScalar>,%d,%d)\n",isign,dir);
1541
1542 // For now, simply evaluate the expression and then do the map
1543 return bimapsa((isign+1)>>1,dir)(l);
1544 }
1545
1546 template<class RHS, class T1>
1548 operator()(const QDPExpr<RHS,OLattice<T1> > & l, int isign, int dir)
1549 {
1550// fprintf(stderr,"ArrayBiDirectionalMap(QDPExpr<OLattice>,%d,%d)\n",isign,dir);
1551
1552 // For now, simply evaluate the expression and then do the map
1553 return bimapsa((isign+1)>>1,dir)(l);
1554 }
1555
1556
1557private:
1560
1562 void operator=(const ArrayBiDirectionalMap&) {}
1563
1564private:
1565 multi2d<Map> bimapsa;
1566
1567};
1568
1569
1570//-----------------------------------------------------------------------------
1571// Input and output of various flavors that are architecture specific
1572
1574
1575template<class T>
1576inline
1577void write(BinaryWriter& bin, const OScalar<T>& d)
1578{
1579 bin.writeArray((const char *)&(d.elem()),
1580 sizeof(typename WordType<T>::Type_t),
1581 sizeof(T) / sizeof(typename WordType<T>::Type_t));
1582}
1583
1585
1586template<class T>
1587void read(BinaryReader& bin, OScalar<T>& d)
1588{
1589 bin.readArray((char*)&(d.elem()),
1590 sizeof(typename WordType<T>::Type_t),
1591 sizeof(T) / sizeof(typename WordType<T>::Type_t));
1592}
1593
1594
1595
1596// There are 2 main classes of binary/xml reader/writer methods.
1597// The first is a simple/portable but inefficient method of send/recv
1598// to/from the destination node.
1599// The second method (the else) is a more efficient roll-around method.
1600// However, this method more constrains the data layout - it must be
1601// close to the original lexicographic order.
1602// For now, use the direct send method
1603
1605multi1d<int> crtesn(int ipos, const multi1d<int>& latt_size);
1606
1608
1609template<class T>
1610XMLWriter& operator<<(XMLWriter& xml, const OLattice<T>& d)
1611{
1612 typedef typename UnaryReturn<T, FnGetSite>::Type_t Site_t;
1613 Site_t recv_buf;
1614
1615 xml.openTag("OLattice");
1616 XMLWriterAPI::AttributeList alist;
1617
1618 // Find the location of each site and send to primary node
1619 for(int site=0; site < Layout::vol(); ++site)
1620 {
1621 multi1d<int> coord = crtesn(site, Layout::lattSize());
1622
1623 int node = Layout::nodeNumber(coord);
1624 int linear = Layout::linearSiteIndex(coord);
1625 int outersite = linear >> INNER_LOG;
1626 int innersite = linear & ((1 << INNER_LOG)-1);
1627
1628 // Copy to buffer: be really careful since max(linear) could vary among nodes
1629 if (Layout::nodeNumber() == node)
1630 recv_buf = getSite(d.elem(outersite),innersite); // extract into conventional scalar form
1631
1632 // Send result to primary node. Avoid sending prim-node sending to itself
1633 if (node != 0)
1634 {
1635#if 1
1636 // All nodes participate
1637 QDPInternal::route((void *)&recv_buf, node, 0, sizeof(Site_t));
1638#else
1639 if (Layout::primaryNode())
1640 QDPInternal::recvFromWait((void *)&recv_buf, node, sizeof(Site_t));
1641
1642 if (Layout::nodeNumber() == node)
1643 QDPInternal::sendToWait((void *)&recv_buf, 0, sizeof(Site_t));
1644#endif
1645 }
1646
1647 if (Layout::primaryNode())
1648 {
1649 std::ostringstream os;
1650 os << coord[0];
1651 for(int i=1; i < coord.size(); ++i)
1652 os << " " << coord[i];
1653
1654 alist.clear();
1655 alist.push_back(XMLWriterAPI::Attribute("site", site));
1656 alist.push_back(XMLWriterAPI::Attribute("coord", os.str()));
1657
1658 xml.openTag("elem", alist);
1659 xml << recv_buf;
1660 xml.closeTag();
1661 }
1662 }
1663
1664 xml.closeTag(); // OLattice
1665 return xml;
1666}
1667
1668
1670
1671template<class T>
1672void write(BinaryWriter& bin, const OLattice<T>& d)
1673{
1674 typedef typename UnaryReturn<T, FnGetSite>::Type_t Site_t;
1675 Site_t recv_buf;
1676
1677 // Find the location of each site and send to primary node
1678 for(int site=0; site < Layout::vol(); ++site)
1679 {
1680 multi1d<int> coord = crtesn(site, Layout::lattSize());
1681
1682 int node = Layout::nodeNumber(coord);
1683 int linear = Layout::linearSiteIndex(coord);
1684 int outersite = linear >> INNER_LOG;
1685 int innersite = linear & ((1 << INNER_LOG)-1);
1686
1687 // Copy to buffer: be really careful since max(linear) could vary among nodes
1688 if (Layout::nodeNumber() == node)
1689 recv_buf = getSite(d.elem(outersite),innersite); // extract into conventional scalar form
1690
1691 // Send result to primary node. Avoid sending prim-node sending to itself
1692 if (node != 0)
1693 {
1694#if 1
1695 // All nodes participate
1696 QDPInternal::route((void *)&recv_buf, node, 0, sizeof(Site_t));
1697#else
1698 if (Layout::primaryNode())
1699 QDPInternal::recvFromWait((void *)&recv_buf, node, sizeof(Site_t));
1700
1701 if (Layout::nodeNumber() == node)
1702 QDPInternal::sendToWait((void *)&recv_buf, 0, sizeof(Site_t));
1703#endif
1704 }
1705
1706 if (Layout::primaryNode())
1707 bin.writeArray((char *)&recv_buf,
1708 sizeof(typename WordType<Site_t>::Type_t),
1709 sizeof(Site_t) / sizeof(typename WordType<Site_t>::Type_t));
1710 }
1711}
1712
1714
1715template<class T>
1716void write(BinaryWriter& bin, const OLattice<T>& d, const multi1d<int>& coord)
1717{
1718 typedef typename UnaryReturn<T, FnGetSite>::Type_t Site_t;
1719 Site_t recv_buf;
1720
1721 // Find the location of each site and send to primary node
1722 int node = Layout::nodeNumber(coord);
1723 int linear = Layout::linearSiteIndex(coord);
1724 int outersite = linear >> INNER_LOG;
1725 int innersite = linear & ((1 << INNER_LOG)-1);
1726
1727 // Copy to buffer: be really careful since max(linear) could vary among nodes
1728 if (Layout::nodeNumber() == node)
1729 recv_buf = getSite(d.elem(outersite),innersite); // extract into conventional scalar form
1730
1731 // Send result to primary node. Avoid sending prim-node sending to itself
1732 if (node != 0)
1733 {
1734#if 1
1735 // All nodes participate
1736 QDPInternal::route((void *)&recv_buf, node, 0, sizeof(Site_t));
1737#else
1738 if (Layout::primaryNode())
1739 QDPInternal::recvFromWait((void *)&recv_buf, node, sizeof(Site_t));
1740
1741 if (Layout::nodeNumber() == node)
1742 QDPInternal::sendToWait((void *)&recv_buf, 0, sizeof(Site_t));
1743#endif
1744 }
1745
1746 if (Layout::primaryNode())
1747 bin.writeArray((char *)&recv_buf,
1748 sizeof(typename WordType<Site_t>::Type_t),
1749 sizeof(Site_t) / sizeof(typename WordType<Site_t>::Type_t));
1750}
1751
1752
1754
1755template<class T>
1756void read(BinaryReader& bin, OLattice<T>& d)
1757{
1758 typedef typename UnaryReturn<T, FnGetSite>::Type_t Site_t;
1759 Site_t recv_buf;
1760
1761 // Find the location of each site and send to primary node
1762 for(int site=0; site < Layout::vol(); ++site)
1763 {
1764 multi1d<int> coord = crtesn(site, Layout::lattSize());
1765
1766 int node = Layout::nodeNumber(coord);
1767 int linear = Layout::linearSiteIndex(coord);
1768 int outersite = linear >> INNER_LOG;
1769 int innersite = linear & ((1 << INNER_LOG)-1);
1770
1771 // Only on primary node read the data
1772 bin.readArrayPrimaryNode((char *)&recv_buf,
1773 sizeof(typename WordType<Site_t>::Type_t),
1774 sizeof(Site_t) / sizeof(typename WordType<Site_t>::Type_t));
1775
1776 // Send result to destination node. Avoid sending prim-node sending to itself
1777 if (node != 0)
1778 {
1779#if 1
1780 // All nodes participate
1781 QDPInternal::route((void *)&recv_buf, 0, node, sizeof(Site_t));
1782#else
1783 if (Layout::primaryNode())
1784 QDPInternal::sendToWait((void *)&recv_buf, node, sizeof(Site_t));
1785
1786 if (Layout::nodeNumber() == node)
1787 QDPInternal::recvFromWait((void *)&recv_buf, 0, sizeof(Site_t));
1788#endif
1789 }
1790
1791 if (Layout::nodeNumber() == node)
1792 copy_site(d.elem(outersite), innersite, recv_buf);// insert into conventional scalar form
1793 }
1794}
1795
1797
1798template<class T>
1799void read(BinaryReader& bin, OLattice<T>& d, const multi1d<int>& coord)
1800{
1801 typedef typename UnaryReturn<T, FnGetSite>::Type_t Site_t;
1802 Site_t recv_buf;
1803
1804 // Find the location of each site and send to primary node
1805 int node = Layout::nodeNumber(coord);
1806 int linear = Layout::linearSiteIndex(coord);
1807 int outersite = linear >> INNER_LOG;
1808 int innersite = linear & ((1 << INNER_LOG)-1);
1809
1810 // Only on primary node read the data
1811 bin.readArrayPrimaryNode((char *)&recv_buf,
1812 sizeof(typename WordType<Site_t>::Type_t),
1813 sizeof(Site_t) / sizeof(typename WordType<Site_t>::Type_t));
1814
1815 // Send result to destination node. Avoid sending prim-node sending to itself
1816 if (node != 0)
1817 {
1818#if 1
1819 // All nodes participate
1820 QDPInternal::route((void *)&recv_buf, 0, node, sizeof(Site_t));
1821#else
1822 if (Layout::primaryNode())
1823 QDPInternal::sendToWait((void *)&recv_buf, node, sizeof(Site_t));
1824
1825 if (Layout::nodeNumber() == node)
1826 QDPInternal::recvFromWait((void *)&recv_buf, 0, sizeof(Site_t));
1827#endif
1828 }
1829
1830 if (Layout::nodeNumber() == node)
1831 copy_site(d.elem(outersite), innersite, recv_buf);// insert into conventional scalar form
1832}
1833
1834} // namespace QDP
1835
1836#endif
ForEach< Expr, FTag, CTag >::Type_t forEach(const Expr &e, const FTag &f, const CTag &c)
Definition ForEach.h:87
#define PETE_EMPTY_CONSTRUCTORS(CLASS)
Definition PETE.h:58
ArrayBiDirectional of general permutation map class for communications.
OLattice< T1 > operator()(const OLattice< T1 > &l, int isign, int dir)
Function call operator for a shift.
void make(const ArrayMapFunc &func)
Actual constructor from a function object.
Definition qdp_map.cc:153
ArrayBiDirectionalMap(const ArrayMapFunc &fn)
Constructor from a function object.
ArrayBiDirectionalMap()
Constructor - does nothing really.
OScalar< T1 > operator()(const QDPExpr< RHS, OScalar< T1 > > &l, int isign, int dir)
OScalar< T1 > operator()(const OScalar< T1 > &l, int isign, int dir)
OLattice< T1 > operator()(const QDPExpr< RHS, OLattice< T1 > > &l, int isign, int dir)
ArrayMapFunc.
Definition qdp_map.h:45
Array of general permutation map class for communications.
OLattice< T1 > operator()(const OLattice< T1 > &l, int dir)
Function call operator for a shift.
ArrayMap()
Constructor - does nothing really.
OScalar< T1 > operator()(const OScalar< T1 > &l, int dir)
OLattice< T1 > operator()(const QDPExpr< RHS, OLattice< T1 > > &l, int dir)
ArrayMap(const ArrayMapFunc &fn)
Constructor from a function object.
OScalar< T1 > operator()(const QDPExpr< RHS, OScalar< T1 > > &l, int dir)
void make(const ArrayMapFunc &func)
Actual constructor from a function object.
Definition qdp_map.cc:74
BiDirectional of general permutation map class for communications.
OScalar< T1 > operator()(const QDPExpr< RHS, OScalar< T1 > > &l, int isign)
void make(const MapFunc &func)
Actual constructor from a function object.
Definition qdp_map.cc:114
OLattice< T1 > operator()(const QDPExpr< RHS, OLattice< T1 > > &l, int isign)
BiDirectionalMap(const MapFunc &fn)
Constructor from a function object.
OScalar< T1 > operator()(const OScalar< T1 > &l, int isign)
OLattice< T1 > operator()(const OLattice< T1 > &l, int isign)
Function call operator for a shift.
BiDirectionalMap()
Constructor - does nothing really.
MapFunc.
Definition qdp_map.h:32
General permutation map class for communications.
OLattice< T1 > operator()(const QDPExpr< RHS, OLattice< T1 > > &l)
Map(const MapFunc &fn)
Constructor from a function object.
OScalar< T1 > operator()(const QDPExpr< RHS, OScalar< T1 > > &l)
OScalar< T1 > operator()(const OScalar< T1 > &l)
const multi1d< int > & goffset() const
Accessor to offsets.
const multi1d< int > & soffset() const
Map()
Constructor - does nothing really.
OLattice< T1 > operator()(const OLattice< T1 > &l)
Function call operator for a shift.
void make(const MapFunc &func)
Actual constructor from a function object.
Outer grid Lattice type.
Definition qdp_outer.h:264
T & elem(int i)
Definition qdp_outer.h:400
Outer grid Scalar class *‍/.
Definition qdp_outer.h:37
OLattice class narrowed to a subset.
const Subset & subset() const
Expression class for QDP.
Definition qdp_qdpexpr.h:16
OScalar< T1 > peekSite(const QDPExpr< RHS, OScalar< T1 > > &l, const multi1d< int > &coord)
Extract site element.
UnaryReturn< OScalar< T1 >, FnPeekSite >::Type_t peekSite(const OScalar< T1 > &l, const multi1d< int > &coord)
Extract site element.
UnaryReturn< OLattice< T1 >, FnPeekSite >::Type_t peekSite(const OLattice< T1 > &l, const multi1d< int > &coord)
Extract site element.
OScalar< T1 > peekSite(const QDPExpr< RHS, OLattice< T1 > > &l, const multi1d< int > &coord)
Extract site element.
Set - collection of subsets controlling which sites are involved in an operation.
Definition qdp_subset.h:96
int numSubsets() const
Return number of subsets.
Definition qdp_subset.h:111
Subsets - controls how lattices are looped.
Definition qdp_subset.h:39
const multi1d< int > & siteTable() const
Definition qdp_subset.h:83
int numSiteTable() const
Definition qdp_subset.h:84
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
#define INNER_LEN
OLattice< PScalar< PSeed< RScalar< INTEGER32 > > > > LatticeSeed
OScalar< PScalar< PSeed< RScalar< INTEGER32 > > > > Seed
#define INNER_LOG
OLattice< PScalar< PScalar< RScalar< INTEGER32 > > > > LatticeInteger
OLattice< T1 > & pokeSite(OLattice< T1 > &l, const OScalar< T2 > &r, const multi1d< int > &coord)
Insert site element.
OScalar< T1 > peekSite(const OScalar< T1 > &l, const multi1d< int > &coord)
Extract site element.
void QDP_extract(multi1d< OScalar< typename UnaryReturn< T, FnGetSite >::Type_t > > &dest, const OLattice< T > &src, const Subset &s)
Copy data values from field src to array dest.
void QDP_insert(OLattice< T > &dest, const multi1d< OScalar< typename UnaryReturn< T, FnGetSite >::Type_t > > &src, const Subset &s)
Inserts data values from site array src.
UnaryReturn< C, FnNorm2 >::Type_t norm2(const QDPType< T, C > &s1)
OScalar = norm2(trace(adj(source)*source)).
UnaryReturn< C, FnSumMulti >::Type_t sumMulti(const QDPType< T, C > &s1, const Set &ss)
dest = sumMulti(source1,Set)
UnaryReturn< C, FnSum >::Type_t sum(const QDPType< T, C > &s1)
OScalar = sum(source).
void gather_sites(ILattice< T, 2 > &d, const ILattice< T1, 2 > &s0, int i0, const ILattice< T1, 2 > &s1, int i1)
gather several inner sites together
Definition qdp_inner.h:3307
TextWriter & operator<<(TextWriter &txt, const std::string &output)
Definition qdp_io.cc:283
void write(BinaryWriter &bin, const std::string &output)
Definition qdp_io.cc:1204
void read(BinaryReader &bin, std::string &input, size_t maxBytes)
Definition qdp_io.cc:778
void fill_gaussian(IScalar< T > &d, IScalar< T > &r1, IScalar< T > &r2)
dest = gaussian
Definition qdp_inner.h:1861
void copy_site(IScalar< T > &d, int isite, const IScalar< T1 > &s1)
dest [some type] = source [some type]
Definition qdp_inner.h:1682
void zero_rep(IScalar< T > &dest)
dest = 0
Definition qdp_inner.h:1841
void copymask(IScalar< T > &d, const IScalar< T1 > &mask, const IScalar< T > &s1)
dest = (mask) ? s1 : dest
Definition qdp_inner.h:1656
UnaryReturn< IScalar< T >, FnGetSite >::Type_t getSite(const IScalar< T > &s1, int innersite)
Definition qdp_inner.h:1605
void evaluate(OLattice< DCol > &d, const OpAssign &op, const QDPExpr< BinaryNode< OpMultiply, Reference< QDPType< DCol, OLattice< DCol > > >, Reference< QDPType< DCol, OLattice< DCol > > > >, OLattice< DCol > > &rhs, const Subset &s)
void gaussian(OSubScalar< T > &d)
dest = gaussian
Definition qdp_outer.h:1462
void random(OScalar< T > &d)
dest = random
Subset all
Default all subset.
Definition qdp_subset.cc:16
Layout namespace holding info on problem size and machine info.
Definition qdp_layout.cc:16
int nodeNumber()
Returns the node number of this node.
int linearSiteIndex(int site)
The linearized site index for the corresponding lexicographic site.
int sitesOnNode()
Subgrid lattice volume.
int outerSitesOnNode()
Subgrid lattice volume.
const multi1d< int > & lattSize()
Virtual grid (problem grid) lattice size.
LatticeInteger latticeCoordinate(int mu)
coord[mu] <- mu : fill with lattice coord in mu direction
int vol()
Total lattice volume.
bool primaryNode()
Returns whether this is the primary node.
void broadcast(T &dest)
Broadcast from primary node to all other nodes.
void sendToWait(void *send_buf, int dest_node, int count)
Send to another node (wait).
void globalSum(T &dest)
Sum across all nodes.
void route(void *buffer, int srce_node, int dest_node, int count)
Route to another node (blocking).
void sendToPrimaryNode(T &dest, int srcnode)
Via some mechanism, get the dest to node 0.
void wait(int dir)
Wait on send-receive.
void recvFromWait(void *recv_buf, int srce_node, int count)
Receive from another node (wait).
void broadcast_str(std::string &result)
Broadcast a string from primary node to all other nodes.
void sumAnUnsigned(void *inout, void *in)
Unsigned accumulate.
void globalSumArray(unsigned int *dest, int len)
Wrapper to get a functional unsigned global sum.
Seed ran_mult_n
RNG multiplier raised to the volume+1.
Definition qdp_random.cc:24
Seed ran_mult
RNG multiplier.
Definition qdp_random.cc:22
LatticeSeed * lattice_ran_mult
The lattice of skewed RNG multipliers.
Definition qdp_random.cc:26
Seed ran_seed
Global (current) seed.
Definition qdp_random.cc:20
Yet another random number generator.
ForEach< Expr, FTag, CTag >::Type_t forEach(const Expr &e, const FTag &f, const CTag &c)
Definition qdp.h:88
void QDP_error_exit(const char *format,...)
Simple error display and abort routine.
Definition qdp_util.cc:93
QDPTime_t getClockTime()
Get the wallclock time.
int QDP_error(const char *format,...)
Simple error display routine.
Definition qdp_util.cc:69
multi1d< int > crtesn(int ipos, const multi1d< int > &latt_size)
Decompose a lexicographic site into coordinates.
void fill_random(float &d, T1 &seed, T2 &skewed_seed, const T1 &seed_mult)
dest = random
Definition qdp_random.h:54
MakeReturn< UnaryNode< FnLocalNorm2, typenameCreateLeaf< QDPExpr< T1, C1 > >::Leaf_t >, typenameUnaryReturn< C1, FnLocalNorm2 >::Type_t >::Expression_t localNorm2(const QDPExpr< T1, C1 > &l)
Definition qdp.h:4998
int QDP_info(const char *format,...)
Simple information display routine.
Definition qdp_util.cc:43
#define QDP_ALIGNMENT_SIZE
Definition qdp.h:82
#define QDP_CONST
Definition qdp.h:63