QDP++
qdp_parscalar_specific.h
Go to the documentation of this file.
1// -*- C++ -*-
2
6
7#ifndef QDP_PARSCALAR_SPECIFIC_H
8#define QDP_PARSCALAR_SPECIFIC_H
9
10#include "qmp.h"
11
12namespace QDP {
13
14
15// Use separate defs here. This will cause subroutine calls under g++
16
17//-----------------------------------------------------------------------------
18// Layout stuff specific to a parallel architecture
19namespace Layout
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
38 void sendToWait(void *send_buf, int dest_node, int count);
39
41 void recvFromWait(void *recv_buf, int srce_node, int count);
42
44
45 template<class T>
46 void sendToPrimaryNode(T& dest, int srcnode)
47 {
48 if (srcnode != 0)
49 {
51 recvFromWait((void *)&dest, srcnode, sizeof(T));
52
53 if (Layout::nodeNumber() == srcnode)
54 sendToWait((void *)&dest, 0, sizeof(T));
55 }
56 }
57
59 inline void sumAnUnsigned(void* inout, void* in)
60 {
61 *(unsigned int*)inout += *(unsigned int*)in;
62 }
63
65 inline void globalSumArray(unsigned int *dest, int len)
66 {
67 for(int i=0; i < len; i++, dest++)
68 QMP_binary_reduction(dest, sizeof(unsigned int), sumAnUnsigned);
69 }
70
72 inline void globalSumArray(int *dest, int len)
73 {
74 for(int i=0; i < len; i++, dest++)
75 QMP_sum_int(dest);
76 }
77
79 inline void globalSumArray(float *dest, int len)
80 {
81 QMP_sum_float_array(dest, len);
82 }
83
85 inline void globalSumArray(double *dest, int len)
86 {
87 QMP_sum_double_array(dest, len);
88 }
89
90 //! Global sum on a multi1d
91 template<class T>
92 inline void globalSumArray(multi1d<T>& dest)
93 {
94 // The implementation here is relying on the structure being packed
95 // tightly in memory - no padding
96 typedef typename WordType<T>::Type_t W; // find the machine word type
97
98#if 0
99 QDPIO::cout << "sizeof(T) = " << sizeof(T) << endl;
100 QDPIO::cout << "sizeof(W) = " << sizeof(W) << endl;
101 QDPIO::cout << "Calling multi1d global sum array with length " << dest.size()*sizeof(T)/sizeof(W) << endl;
102#endif
103 globalSumArray((W *)dest.slice(), dest.size()*sizeof(T)/sizeof(W)); // call appropriate hook
104 }
107 template<class T>
108 inline void globalSumArray(multi2d<T>& dest)
109 {
110 // The implementation here is relying on the structure being packed
111 // tightly in memory - no padding
112 typedef typename WordType<T>::Type_t W; // find the machine word type
113
114#if 0
115 QDPIO::cout << "sizeof(T) = " << sizeof(T) << endl;
116 QDPIO::cout << "sizeof(W) = " << sizeof(W) << endl;
117 QDPIO::cout << "Calling multi2d global sum array with length " << dest.size1()*dest.size2()*sizeof(T)/sizeof(W) << endl;
118#endif
119 // call appropriate hook
120 globalSumArray((W *)dest.slice(0), dest.size1()*dest.size2()*sizeof(T)/sizeof(W));
121 }
122
124 template<class T>
125 inline void globalSum(T& dest)
126 {
127 // The implementation here is relying on the structure being packed
128 // tightly in memory - no padding
129 typedef typename WordType<T>::Type_t W; // find the machine word type
130
131#if 0
132 QDPIO::cout << "sizeof(T) = " << sizeof(T) << endl;
133 QDPIO::cout << "sizeof(W) = " << sizeof(W) << endl;
134 QDPIO::cout << "Calling global sum array with length " << sizeof(T)/sizeof(W) << endl;
135#endif
136 globalSumArray((W *)&dest, int(sizeof(T)/sizeof(W))); // call appropriate hook
137 }
138
139 template<>
140 inline void globalSum(double& dest)
141 {
142#if 0
143 QDPIO::cout << "Using simple sum_double" << endl;
144#endif
145 QMP_sum_double(&dest);
146 }
147
148
150 inline void globalMaxValue(float* dest)
151 {
152 QMP_max_float(dest);
153 }
154
156 inline void globalMaxValue(double* dest)
157 {
158 QMP_max_double(dest);
159 }
160
161
163 template<class T>
164 inline void globalMax(T& dest)
165 {
166 typedef typename WordType<T>::Type_t W; // find the machine word type
167
168 globalMaxValue((W *)&dest);
169 }
170
171
173 inline void globalMinValue(float* dest)
174 {
175 QMP_min_float(dest);
176 }
177
179 inline void globalMinValue(double* dest)
180 {
181 QMP_min_double(dest);
182 }
183
184
186 template<class T>
187 inline void globalMin(T& dest)
188 {
189 typedef typename WordType<T>::Type_t W; // find the machine word type
190
191 globalMinValue((W *)&dest);
192 }
193
194
196 inline void globalCheckAnd(void* inout, void* in)
197 {
198 *(unsigned int*)inout = *(unsigned int*)inout & *(unsigned int*)in;
199 }
200
202 inline void globalAnd(bool& dest)
203 {
204 QMP_binary_reduction(&dest, sizeof(bool), globalCheckAnd);
205 }
206
207
208
210 inline void globalCheckOr(void* inout, void* in)
211 {
212 *(unsigned int*)inout = *(unsigned int*)inout | *(unsigned int*)in;
213 }
214
216 inline void globalOr(bool& dest)
217 {
218 QMP_binary_reduction(&dest, sizeof(bool), globalCheckOr);
219 }
220
222 template<class T>
223 inline void broadcast(T& dest)
224 {
225 QMP_broadcast((void *)&dest, sizeof(T));
226 }
227
229 void broadcast_str(std::string& dest);
230
232 inline void broadcast(void* dest, size_t nbytes)
233 {
234 QMP_broadcast(dest, nbytes);
235 }
236
238 template<>
239 inline void broadcast(std::string& dest)
240 {
241 broadcast_str(dest);
242 }
243
244}
245
247// Threading evaluate with openmp and qmt implementation
248//
249// by Xu Guo, EPCC, 16 June 2008
251
253// "OLattice Op Scalar(Expression(source)) under an Subset"
254//
255template<class T, class T1, class Op, class RHS>
256struct u_arg{
258 OLattice<T>& d_,
259 const QDPExpr<RHS,OScalar<T1> >& r_,
260 const Op& op_,
261 const int *tab_
262 ) : d(d_), r(r_), op(op_), tab(tab_) {}
263
266 const Op& op;
267 const int *tab;
268 };
269
271// "OLattice Op Scalar(Expression(source)) under an Subset"
272//
273template<class T, class T1, class Op, class RHS>
274void ev_userfunc(int lo, int hi, int myId, u_arg<T,T1,Op,RHS> *a)
275{
276 OLattice<T>& dest = a->d;
277 const QDPExpr<RHS,OScalar<T1> >&rhs = a->r;
278 const int* tab = a->tab;
279 const Op& op= a->op;
280
281
282 for(int j=lo; j < hi; ++j)
283 {
284 int i = tab[j];
285 op(dest.elem(i), forEach(rhs, EvalLeaf1(0), OpCombine()));
286 }
287}
288
290// "OLattice Op OLattice(Expression(source)) under an Subset"
291//
292template<class T, class T1, class Op, class RHS>
293struct user_arg{
295 OLattice<T>& d_,
296 const QDPExpr<RHS,OLattice<T1> >& r_,
297 const Op& op_,
298 const int *tab_ ) : d(d_), r(r_), op(op_), tab(tab_) {}
299
302 const Op& op;
303 const int *tab;
304 };
305
307// "OLattice Op OLattice(Expression(source)) under an Subset"
308//
309template<class T, class T1, class Op, class RHS>
310void evaluate_userfunc(int lo, int hi, int myId, user_arg<T,T1,Op,RHS> *a)
311{
312
313 OLattice<T>& dest = a->d;
314 const QDPExpr<RHS,OLattice<T1> >&rhs = a->r;
315 const int* tab = a->tab;
316 const Op& op= a->op;
317
318
319 for(int j=lo; j < hi; ++j)
320 {
321 int i = tab[j];
322 op(dest.elem(i), forEach(rhs, EvalLeaf1(i), OpCombine()));
323 }
324}
325
327#include "qdp_dispatch.h"
328
329
330
331//-----------------------------------------------------------------------------
333
337template<class T, class T1, class Op, class RHS>
338//inline
339void evaluate(OLattice<T>& dest, const Op& op, const QDPExpr<RHS,OScalar<T1> >& rhs,
340 const Subset& s)
341{
342// cerr << "In evaluateSubset(olattice,oscalar)\n";
343
344#if defined(QDP_USE_PROFILING)
345 static QDPProfile_t prof(dest, op, rhs);
346 prof.time -= getClockTime();
347#endif
348
349#if 0
350 int numSiteTable = s.numSiteTable();
351
352 u_arg<T,T1,Op,RHS> a(dest, rhs, op, s.siteTable().slice());
353
355#else
357 // Original code
359 const int* tab = s.siteTable().slice();
360 int numSiteTable = s.numSiteTable();
361#pragma omp parallel for
362 for(int j=0; j < numSiteTable; ++j)
363 {
364 int i = tab[j];
365 op(dest.elem(i), forEach(rhs, EvalLeaf1(0), OpCombine()));
366 }
367#endif
368
369#if defined(QDP_USE_PROFILING)
370 prof.time += getClockTime();
371 prof.count++;
372 prof.print();
373#endif
374}
375
376
378
382template<class T, class T1, class Op, class RHS>
383//inline
384void evaluate(OLattice<T>& dest, const Op& op, const QDPExpr<RHS,OLattice<T1> >& rhs,
385 const Subset& s)
386{
387// cerr << "In evaluateSubset(olattice,olattice)" << endl;
388
389#if defined(QDP_USE_PROFILING)
390 static QDPProfile_t prof(dest, op, rhs);
391 prof.time -= getClockTime();
392#endif
393
394#if 0
395 int numSiteTable = s.numSiteTable();
396
397 user_arg<T,T1,Op,RHS> a(dest, rhs, op, s.siteTable().slice());
398
400#else
401 const int *tab = s.siteTable().slice();
402 const int numSiteTable = s.numSiteTable();
403#pragma omp parallel for
404 for(int j=0; j < numSiteTable; ++j)
405 {
406 int i = tab[j];
407 op(dest.elem(i), forEach(rhs, EvalLeaf1(i), OpCombine()));
408 }
409#endif
410#if defined(QDP_USE_PROFILING)
411 prof.time += getClockTime();
412 prof.count++;
413 prof.print();
414#endif
415}
416
417
418
419
420template<class T, class T1, class Op, class RHS>
421//inline
422void evaluate_F(T* dest, const Op& op, const QDPExpr<RHS,OLattice<T1> >& rhs,
423 const Subset& s)
424{
425 //cerr << "In evaluate_F(olattice,olattice)" << endl;
426
427#if defined(QDP_USE_PROFILING)
428 static QDPProfile_t prof(dest, op, rhs);
429 prof.time -= getClockTime();
430#endif
431
432 // int numSiteTable = s.numSiteTable();
433 // user_arg<T,T1,Op,RHS> a(dest, rhs, op, s.siteTable().slice());
434 // dispatch_to_threads< user_arg<T,T1,Op,RHS> >(numSiteTable, a, evaluate_userfunc);
435
437 // Original code
439
440 //QDP_info("eval_F %d sites",s.numSiteTable());
441
442 // General form of loop structure
443 const int *tab = s.siteTable().slice();
444 for(int j=0; j < s.numSiteTable(); ++j)
445 {
446 int i = tab[j];
447 //fprintf(stderr,"eval(olattice,olattice): site %d\n",i);
448 op( dest[j], forEach(rhs, EvalLeaf1(i), OpCombine()));
449 }
450
451#if defined(QDP_USE_PROFILING)
452 prof.time += getClockTime();
453 prof.count++;
454 prof.print();
455#endif
456}
457
458
459//-----------------------------------------------------------------------------
461template<class T1, class T2>
462void copymask(OSubLattice<T2> d, const OLattice<T1>& mask, const OLattice<T2>& s1)
463{
464 OLattice<T2>& dest = d.field();
465 const Subset& s = d.subset();
466
467 const int *tab = s.siteTable().slice();
468 const int nodeSites = s.numSiteTable();
469#pragma omp parallel for
470 for(int j=0; j < nodeSites; ++j)
471 {
472 int i = tab[j];
473 copymask(dest.elem(i), mask.elem(i), s1.elem(i));
474 }
475}
476
478template<class T1, class T2>
479void copymask(OLattice<T2>& dest, const OLattice<T1>& mask, const OLattice<T2>& s1)
480{
481 int nodeSites = Layout::sitesOnNode();
482
483#pragma omp parallel for
484 for(int i=0; i < nodeSites; ++i)
485 copymask(dest.elem(i), mask.elem(i), s1.elem(i));
486}
487
488
489//-----------------------------------------------------------------------------
490// Random numbers
491namespace RNG
492{
493 extern Seed ran_seed;
494 extern Seed ran_mult;
495 extern Seed ran_mult_n;
497}
498
499
501
502template<class T>
503void
505{
506 Seed seed = RNG::ran_seed;
507 Seed skewed_seed = RNG::ran_seed * RNG::ran_mult;
508
509 fill_random(d.elem(), seed, skewed_seed, RNG::ran_mult);
510
511 RNG::ran_seed = seed; // The seed from any site is the same as the new global seed
512}
513
514
516template<class T>
517void
519{
520 const int *tab = s.siteTable().slice();
521 const int nodeSites = s.numSiteTable();
522
523#pragma omp parallel
524 {
525 Seed seed;
526 Seed skewed_seed;
527
528#pragma omp for // need the barrier to avoid that RNG::ran_seed is changed too early!
529 for(int j=0; j < nodeSites; ++j)
530 {
531 int i = tab[j];
532 seed = RNG::ran_seed;
533
534 skewed_seed.elem() = RNG::ran_seed.elem() * RNG::lattice_ran_mult->elem(i);
535 fill_random(d.elem(i), seed, skewed_seed, RNG::ran_mult_n);
536 }
537
538 int myId = qdpThreadNum();
539 if( myId < nodeSites ) {
540#pragma omp critical (random)
541 {
542 RNG::ran_seed = seed; // The seed from any site is the same as the new global seed
543 }
544 }
545 }
546}
547
548
549
551template<class T>
553{
554 OLattice<T>& d = dd.field();
555 const Subset& s = dd.subset();
556
557 random(d,s);
558}
559
560
562template<class T>
564{
565 random(d,all);
566}
567
568
570template<class T>
571void gaussian(OLattice<T>& d, const Subset& s)
572{
573 OLattice<T> r1, r2;
574
575 random(r1,s);
576 random(r2,s);
577
578 const int *tab = s.siteTable().slice();
579 const int nodeSites = s.numSiteTable();
580
581#pragma omp parallel for
582 for(int j=0; j < nodeSites; ++j)
583 {
584 int i = tab[j];
585 fill_gaussian(d.elem(i), r1.elem(i), r2.elem(i));
586 }
587}
588
589
590
592template<class T>
594{
595 OLattice<T>& d = dd.field();
596 const Subset& s = dd.subset();
597
598 gaussian(d,s);
599}
600
601
603template<class T>
605{
606 gaussian(d,all);
607}
608
609
610
611//-----------------------------------------------------------------------------
612// Broadcast operations
614template<class T>
615inline
616void zero_rep(OLattice<T>& dest, const Subset& s)
617{
618 const int *tab = s.siteTable().slice();
619 const int nodeSites = s.numSiteTable();
620
621#pragma omp parallel for
622 for(int j=0; j < nodeSites; ++j)
623 {
624 int i = tab[j];
625 zero_rep(dest.elem(i));
626 }
627}
628
629
630#if 0
631 /* There is remotes/origin/jacques */
633template<class T>
634void zero_rep(OSubLattice<T> dd)
635{
636 OLattice<T>& d = dd.field();
637 const Subset& s = dd.subset();
638
639 zero_rep(d,s);
640}
641#endif
642
643
644
646template<class T>
648{
649 const int nodeSites = Layout::sitesOnNode();
650
651#pragma omp parallel for
652 for(int i=0; i < nodeSites; ++i)
653 zero_rep(dest.elem(i));
654}
655
656
657
658//-----------------------------------------------
659// Global sums
661
665template<class RHS, class T>
666typename UnaryReturn<OScalar<T>, FnSum>::Type_t
667sum(const QDPExpr<RHS,OScalar<T> >& s1, const Subset& s)
668{
670
671#if defined(QDP_USE_PROFILING)
672 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
673 prof.time -= getClockTime();
674#endif
675
676 evaluate(d,OpAssign(),s1,all); // since OScalar, no global sum needed
677
678#if defined(QDP_USE_PROFILING)
679 prof.time += getClockTime();
680 prof.count++;
681 prof.print();
682#endif
683
684 return d;
685}
686
687
689
693template<class RHS, class T>
694typename UnaryReturn<OScalar<T>, FnSum>::Type_t
695sum(const QDPExpr<RHS,OScalar<T> >& s1)
696{
698
699#if defined(QDP_USE_PROFILING)
700 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
701 prof.time -= getClockTime();
702#endif
703
704 evaluate(d,OpAssign(),s1,all); // since OScalar, no global sum needed
705
706#if defined(QDP_USE_PROFILING)
707 prof.time += getClockTime();
708 prof.count++;
709 prof.print();
710#endif
711
712 return d;
713}
714
715
716
718
722template<class RHS, class T>
723typename UnaryReturn<OLattice<T>, FnSum>::Type_t
724sum(const QDPExpr<RHS,OLattice<T> >& s1, const Subset& s)
725{
727
728#if defined(QDP_USE_PROFILING)
729 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
730 prof.time -= getClockTime();
731#endif
732
733 // Must initialize to zero since we do not know if the loop will be entered
734 zero_rep(d.elem());
735
736 const int *tab = s.siteTable().slice();
737 const int nodeSites = s.numSiteTable();
738
739#pragma omp parallel
740 {
741 typename UnaryReturn<OLattice<T>, FnSum>::Type_t dthread;
742 zero_rep(dthread.elem());
743
744#pragma omp for
745 for(int j=0; j < nodeSites; ++j)
746 {
747 int i = tab[j];
748 dthread.elem() += forEach(s1, EvalLeaf1(i), OpCombine());
749 }
750
751 int myId = qdpThreadNum();
752 if( myId < nodeSites ) {
753#pragma omp critical
754 {
755 d.elem() += dthread.elem();
756 }
757 }
758 }
759
760 // Do a global sum on the result
762
763#if defined(QDP_USE_PROFILING)
764 prof.time += getClockTime();
765 prof.count++;
766 prof.print();
767#endif
768
769 return d;
770}
771
772
774
778template<class RHS, class T>
779typename UnaryReturn<OLattice<T>, FnSum>::Type_t
780sum(const QDPExpr<RHS,OLattice<T> >& s1)
781{
783
784#if defined(QDP_USE_PROFILING)
785 static QDPProfile_t prof(d, OpAssign(), FnSum(), s1);
786 prof.time -= getClockTime();
787#endif
788
789 // Loop always entered - could unroll
790 zero_rep(d.elem());
791 const int nodeSites = Layout::sitesOnNode();
792
793#pragma omp parallel
794 {
795 typename UnaryReturn<OLattice<T>, FnSum>::Type_t dthread;
796 zero_rep(dthread.elem());
797
798#pragma omp for nowait
799 for(int i=0; i < nodeSites; ++i)
800 dthread.elem() += forEach(s1, EvalLeaf1(i), OpCombine());
801
802
803 int myId = qdpThreadNum();
804 if( myId < nodeSites ) {
805#pragma omp critical
806 {
807 d.elem() += dthread.elem();
808 }
809 }
810 }
811
812 // Do a global sum on the result
814
815#if defined(QDP_USE_PROFILING)
816 prof.time += getClockTime();
817 prof.count++;
818 prof.print();
819#endif
820
821 return d;
822}
823
824
825//-----------------------------------------------------------------------------
826// Multiple global sums
828
835template<class RHS, class T>
836typename UnaryReturn<OScalar<T>, FnSumMulti>::Type_t
837sumMulti(const QDPExpr<RHS,OScalar<T> >& s1, const Set& ss)
838{
840
841#if defined(QDP_USE_PROFILING)
842 static QDPProfile_t prof(dest[0], OpAssign(), FnSum(), s1);
843 prof.time -= getClockTime();
844#endif
845
846 // lazy - evaluate repeatedly
847 for(int i=0; i < ss.numSubsets(); ++i)
848 evaluate(dest[i],OpAssign(),s1,all);
849
850
851#if defined(QDP_USE_PROFILING)
852 prof.time += getClockTime();
853 prof.count++;
854 prof.print();
855#endif
856
857 return dest;
858}
859
860
862
870template<class RHS, class T>
871typename UnaryReturn<OLattice<T>, FnSumMulti>::Type_t
872sumMulti(const QDPExpr<RHS,OLattice<T> >& s1, const Set& ss)
873{
875
876#if defined(QDP_USE_PROFILING)
877 static QDPProfile_t prof(dest[0], OpAssign(), FnSum(), s1);
878 prof.time -= getClockTime();
879#endif
880
881 // Initialize result with zero
882 for(int k=0; k < ss.numSubsets(); ++k)
883 zero_rep(dest[k]);
884
885 // Loop over all sites and accumulate based on the coloring
886 const multi1d<int>& lat_color = ss.latticeColoring();
887 const int nodeSites = Layout::sitesOnNode();
888
889 for(int i=0; i < nodeSites; ++i)
890 {
891 int j = lat_color[i];
892 dest[j].elem() += forEach(s1, EvalLeaf1(i), OpCombine());
893 }
894
895 // Do a global sum on the result
897
898#if defined(QDP_USE_PROFILING)
899 prof.time += getClockTime();
900 prof.count++;
901 prof.print();
902#endif
903
904 return dest;
905}
906
907
908//-----------------------------------------------------------------------------
909// Multiple global sums on an array
911
918template<class T>
919multi2d<typename UnaryReturn<OScalar<T>, FnSum>::Type_t>
920sumMulti(const multi1d< OScalar<T> >& s1, const Set& ss)
921{
923
924#if defined(QDP_USE_PROFILING)
925 static QDPProfile_t prof(dest(0,0), OpAssign(), FnSum(), s1);
926 prof.time -= getClockTime();
927#endif
928
929 // lazy - evaluate repeatedly
930 for(int i=0; i < dest.size1(); ++i)
931 for(int j=0; j < dest.size2(); ++j)
932 dest(j,i) = s1[j];
933
934#if defined(QDP_USE_PROFILING)
935 prof.time += getClockTime();
936 prof.count++;
937 prof.print();
938#endif
939
940 return dest;
941}
942
943
945
953template<class T>
954multi2d<typename UnaryReturn<OLattice<T>, FnSum>::Type_t>
955sumMulti(const multi1d< OLattice<T> >& s1, const Set& ss)
956{
958
959#if defined(QDP_USE_PROFILING)
960 static QDPProfile_t prof(dest[0], OpAssign(), FnSum(), s1);
961 prof.time -= getClockTime();
962#endif
963
964 // Initialize result with zero
965 for(int i=0; i < dest.size1(); ++i)
966 for(int j=0; j < dest.size2(); ++j)
967 zero_rep(dest(j,i));
968
969 // Loop over all sites and accumulate based on the coloring
970 const multi1d<int>& lat_color = ss.latticeColoring();
971
972 for(int k=0; k < s1.size(); ++k)
973 {
974 const OLattice<T>& ss1 = s1[k];
975 const int nodeSites = Layout::sitesOnNode();
976 for(int i=0; i < nodeSites; ++i)
977 {
978 int j = lat_color[i];
979 dest(k,j).elem() += ss1.elem(i);
980 }
981 }
982
983 // Do a global sum on the result
985
986#if defined(QDP_USE_PROFILING)
987 prof.time += getClockTime();
988 prof.count++;
989 prof.print();
990#endif
991
992 return dest;
993}
994
995
996//-----------------------------------------------------------------------------
998
1004template<class T>
1005inline typename UnaryReturn<OScalar<T>, FnNorm2>::Type_t
1007{
1009
1010#if defined(QDP_USE_PROFILING)
1011 static QDPProfile_t prof(d, OpAssign(), FnNorm2(), s1[0]);
1012 prof.time -= getClockTime();
1013#endif
1014
1015 // Possibly loop entered
1016 zero_rep(d.elem());
1017
1018 for(int n=0; n < s1.size(); ++n)
1019 {
1020 OScalar<T>& ss1 = s1[n];
1021 d.elem() += localNorm2(ss1.elem());
1022 }
1023
1024#if defined(QDP_USE_PROFILING)
1025 prof.time += getClockTime();
1026 prof.count++;
1027 prof.print();
1028#endif
1029
1030 return d;
1031}
1032
1034
1035template<class T>
1036inline typename UnaryReturn<OScalar<T>, FnNorm2>::Type_t
1037norm2(const multi1d< OScalar<T> >& s1, const Subset& s)
1038{
1039 return norm2(s1);
1040}
1041
1042
1044
1050template<class T>
1051inline typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t
1052norm2(const multi1d< OLattice<T> >& s1, const Subset& s)
1053{
1055
1056#if defined(QDP_USE_PROFILING)
1057 static QDPProfile_t prof(d, OpAssign(), FnNorm2(), s1[0]);
1058 prof.time -= getClockTime();
1059#endif
1060
1061 // Possibly loop entered
1062 zero_rep(d.elem());
1063
1064 const int *tab = s.siteTable().slice();
1065 const int nodeSites = s.numSiteTable();
1066
1067 for(int n=0; n < s1.size(); ++n)
1068 {
1069 const OLattice<T>& ss1 = s1[n];
1070
1071 #pragma omp parallel
1072 {
1073 typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t dthread;
1074 zero_rep(dthread.elem());
1075
1076 #pragma omp for
1077 for(int j=0; j < nodeSites; ++j)
1078 {
1079 int i = tab[j];
1080 dthread.elem() += localNorm2(ss1.elem(i));
1081 }
1082
1083 int myId = qdpThreadNum();
1084 if ( myId < nodeSites ) {
1085 #pragma omp critical
1086 {
1087 d.elem() += dthread.elem();
1088 }
1089 }
1090 }
1091 }
1092
1093 // Do a global sum on the result
1095
1096#if defined(QDP_USE_PROFILING)
1097 prof.time += getClockTime();
1098 prof.count++;
1099 prof.print();
1100#endif
1101
1102 return d;
1103}
1104
1105
1107
1113template<class T>
1114inline typename UnaryReturn<OLattice<T>, FnNorm2>::Type_t
1116{
1117 return norm2(s1,all);
1118}
1119
1120
1121
1122//-----------------------------------------------------------------------------
1124
1130template<class T1, class T2>
1131inline typename BinaryReturn<OScalar<T1>, OScalar<T2>, FnInnerProduct>::Type_t
1133{
1135
1136#if defined(QDP_USE_PROFILING)
1137 static QDPProfile_t prof(d, OpAssign(), FnInnerProduct(), s1[0]);
1138 prof.time -= getClockTime();
1139#endif
1140
1141 // Possibly loop entered
1142 zero_rep(d.elem());
1143
1144 for(int n=0; n < s1.size(); ++n)
1145 {
1146 OScalar<T1>& ss1 = s1[n];
1147 OScalar<T2>& ss2 = s2[n];
1148 d.elem() += localInnerProduct(ss1.elem(),ss2.elem());
1149 }
1150
1151#if defined(QDP_USE_PROFILING)
1152 prof.time += getClockTime();
1153 prof.count++;
1154 prof.print();
1155#endif
1156
1157 return d;
1158}
1159
1161
1162template<class T1, class T2>
1163inline typename BinaryReturn<OScalar<T1>, OScalar<T2>, FnInnerProduct>::Type_t
1165 const Subset& s)
1166{
1167 return innerProduct(s1,s2);
1168}
1169
1170
1171
1173
1179template<class T1, class T2>
1180inline typename BinaryReturn<OLattice<T1>, OLattice<T2>, FnInnerProduct>::Type_t
1182 const Subset& s)
1183{
1185
1186#if defined(QDP_USE_PROFILING)
1187 static QDPProfile_t prof(d, OpAssign(), FnInnerProduct(), s1[0]);
1188 prof.time -= getClockTime();
1189#endif
1190
1191 // Possibly loop entered
1192 zero_rep(d.elem());
1193
1194 const int *tab = s.siteTable().slice();
1195 const int nodeSites = s.numSiteTable();
1196 for(int n=0; n < s1.size(); ++n)
1197 {
1198 const OLattice<T1>& ss1 = s1[n];
1199 const OLattice<T2>& ss2 = s2[n];
1200
1201 #pragma omp parallel
1202 {
1204 zero_rep(dthread.elem());
1205
1206 #pragma omp for
1207 for(int j=0; j < nodeSites; ++j)
1208 {
1209 int i = tab[j];
1210 dthread.elem() += localInnerProduct(ss1.elem(i),ss2.elem(i));
1211 }
1212
1213 int myId = qdpThreadNum();
1214 if( myId < nodeSites ) {
1215 #pragma omp critical
1216 {
1217 d.elem() += dthread.elem();
1218 }
1219 }
1220 }
1221 }
1222
1223 // Do a global sum on the result
1225
1226#if defined(QDP_USE_PROFILING)
1227 prof.time += getClockTime();
1228 prof.count++;
1229 prof.print();
1230#endif
1231
1232 return d;
1233}
1234
1235
1237
1243template<class T1, class T2>
1244inline typename BinaryReturn<OLattice<T1>, OLattice<T2>, FnInnerProduct>::Type_t
1246{
1247 return innerProduct(s1,s2,all);
1248}
1249
1250
1251
1252//-----------------------------------------------------------------------------
1254
1260template<class T1, class T2>
1261inline typename BinaryReturn<OScalar<T1>, OScalar<T2>, FnInnerProductReal>::Type_t
1263{
1265
1266#if defined(QDP_USE_PROFILING)
1267 static QDPProfile_t prof(d, OpAssign(), FnInnerProductReal(), s1[0]);
1268 prof.time -= getClockTime();
1269#endif
1270
1271 // Possibly loop entered
1272 zero_rep(d.elem());
1273
1274 for(int n=0; n < s1.size(); ++n)
1275 {
1276 OScalar<T1>& ss1 = s1[n];
1277 OScalar<T2>& ss2 = s2[n];
1278 d.elem() += localInnerProductReal(ss1.elem(),ss2.elem());
1279 }
1280
1281#if defined(QDP_USE_PROFILING)
1282 prof.time += getClockTime();
1283 prof.count++;
1284 prof.print();
1285#endif
1286
1287 return d;
1288}
1289
1291
1292template<class T1, class T2>
1293inline typename BinaryReturn<OScalar<T1>, OScalar<T2>, FnInnerProductReal>::Type_t
1295 const Subset& s)
1296{
1297 return innerProductReal(s1,s2);
1298}
1299
1300
1301
1303
1309template<class T1, class T2>
1310inline typename BinaryReturn<OLattice<T1>, OLattice<T2>, FnInnerProductReal>::Type_t
1312 const Subset& s)
1313{
1315
1316#if defined(QDP_USE_PROFILING)
1317 static QDPProfile_t prof(d, OpAssign(), FnInnerProductReal(), s1[0]);
1318 prof.time -= getClockTime();
1319#endif
1320
1321 // Possibly loop entered
1322 zero_rep(d.elem());
1323
1324 const int *tab = s.siteTable().slice();
1325 const int nodeSites = s.numSiteTable();
1326
1327 for(int n=0; n < s1.size(); ++n)
1328 {
1329 const OLattice<T1>& ss1 = s1[n];
1330 const OLattice<T2>& ss2 = s2[n];
1331
1332 #pragma omp parallel
1333 {
1335 zero_rep(dthread.elem());
1336
1337 #pragma omp for
1338 for(int j=0; j < nodeSites; ++j)
1339 {
1340 int i = tab[j];
1341 dthread.elem() += localInnerProductReal(ss1.elem(i),ss2.elem(i));
1342 }
1343
1344 int myId = qdpThreadNum();
1345 if( myId < nodeSites ) {
1346 #pragma omp critical
1347 {
1348 d.elem() += dthread.elem();
1349 }
1350 }
1351 }
1352 }
1353
1354 // Do a global sum on the result
1356
1357#if defined(QDP_USE_PROFILING)
1358 prof.time += getClockTime();
1359 prof.count++;
1360 prof.print();
1361#endif
1362
1363 return d;
1364}
1365
1366
1368
1374template<class T1, class T2>
1375inline typename BinaryReturn<OLattice<T1>, OLattice<T2>, FnInnerProductReal>::Type_t
1377{
1378 return innerProductReal(s1,s2,all);
1379}
1380
1381
1382
1383
1384//-----------------------------------------------
1385// Global max and min
1386// NOTE: there are no subset version of these operations. It is very problematic
1387// and QMP does not support them.
1389
1392template<class RHS, class T>
1393typename UnaryReturn<OScalar<T>, FnGlobalMax>::Type_t
1395{
1397
1398#if defined(QDP_USE_PROFILING)
1399 static QDPProfile_t prof(d, OpAssign(), FnGlobalMax(), s1);
1400 prof.time -= getClockTime();
1401#endif
1402
1403 evaluate(d,OpAssign(),s1,all); // since OScalar, no global max needed
1404
1405#if defined(QDP_USE_PROFILING)
1406 prof.time += getClockTime();
1407 prof.count++;
1408 prof.print();
1409#endif
1410
1411 return d;
1412}
1413
1414
1416
1419template<class RHS, class T>
1420typename UnaryReturn<OLattice<T>, FnGlobalMax>::Type_t
1422{
1424
1425#if defined(QDP_USE_PROFILING)
1426 static QDPProfile_t prof(d, OpAssign(), FnGlobalMax(), s1);
1427 prof.time -= getClockTime();
1428#endif
1429
1430 // Loop always entered so unroll
1431 d.elem() = forEach(s1, EvalLeaf1(0), OpCombine()); // SINGLE NODE VERSION FOR NOW
1432
1433 const int vvol = Layout::sitesOnNode();
1434 for(int i=1; i < vvol; ++i)
1435 {
1437 forEach(s1, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
1438
1439 if (toBool(dd > d.elem()))
1440 d.elem() = dd;
1441 }
1442
1443 // Do a global max on the result
1445
1446#if defined(QDP_USE_PROFILING)
1447 prof.time += getClockTime();
1448 prof.count++;
1449 prof.print();
1450#endif
1451
1452 return d;
1453}
1454
1455
1457
1460template<class RHS, class T>
1461typename UnaryReturn<OScalar<T>, FnGlobalMin>::Type_t
1463{
1465
1466#if defined(QDP_USE_PROFILING)
1467 static QDPProfile_t prof(d, OpAssign(), FnGlobalMin(), s1);
1468 prof.time -= getClockTime();
1469#endif
1470
1471 evaluate(d,OpAssign(),s1,all); // since OScalar, no global min needed
1472
1473#if defined(QDP_USE_PROFILING)
1474 prof.time += getClockTime();
1475 prof.count++;
1476 prof.print();
1477#endif
1478
1479 return d;
1480}
1481
1482
1484
1487template<class RHS, class T>
1488typename UnaryReturn<OLattice<T>, FnGlobalMin>::Type_t
1490{
1492
1493#if defined(QDP_USE_PROFILING)
1494 static QDPProfile_t prof(d, OpAssign(), FnGlobalMin(), s1);
1495 prof.time -= getClockTime();
1496#endif
1497
1498 // Loop always entered so unroll
1499 d.elem() = forEach(s1, EvalLeaf1(0), OpCombine()); // SINGLE NODE VERSION FOR NOW
1500
1501 const int vvol = Layout::sitesOnNode();
1502 for(int i=1; i < vvol; ++i)
1503 {
1505 forEach(s1, EvalLeaf1(i), OpCombine()); // SINGLE NODE VERSION FOR NOW
1506
1507 if (toBool(dd < d.elem()))
1508 d.elem() = dd;
1509 }
1510
1511 // Do a global min on the result
1513
1514#if defined(QDP_USE_PROFILING)
1515 prof.time += getClockTime();
1516 prof.count++;
1517 prof.print();
1518#endif
1519
1520 return d;
1521}
1522
1523
1524//-----------------------------------------------
1525// Test badness/goodness of floating point numbers.
1526// These functions always return bool
1528
1531template<class T>
1532inline bool
1534{
1535 return isnan(s1.elem());
1536}
1537
1538
1540
1543template<class T>
1544inline bool
1546{
1547 bool d = false;
1548
1549#if defined(QDP_USE_PROFILING)
1550 static QDPProfile_t prof(d, OpAssign(), FnIsNan(), s1);
1551 prof.time -= getClockTime();
1552#endif
1553
1554 const int nodeSites = Layout::sitesOnNode();
1555 for(int i=0; i < nodeSites; ++i)
1556 {
1557 d |= isnan(s1.elem(i));
1558 }
1559
1561
1562#if defined(QDP_USE_PROFILING)
1563 prof.time += getClockTime();
1564 prof.count++;
1565 prof.print();
1566#endif
1567
1568 return d;
1569}
1570
1571
1573
1576template<class T>
1577inline bool
1579{
1580 return isinf(s1.elem());
1581}
1582
1583
1585
1588template<class T>
1589inline bool
1591{
1592 bool d = false;
1593
1594#if defined(QDP_USE_PROFILING)
1595 static QDPProfile_t prof(d, OpAssign(), FnIsInf(), s1);
1596 prof.time -= getClockTime();
1597#endif
1598
1599 const int nodeSites = Layout::sitesOnNode();
1600 for(int i=0; i < nodeSites; ++i)
1601 {
1602 d |= isinf(s1.elem(i));
1603 }
1604
1606
1607#if defined(QDP_USE_PROFILING)
1608 prof.time += getClockTime();
1609 prof.count++;
1610 prof.print();
1611#endif
1612
1613 return d;
1614}
1615
1616
1618
1621template<class T>
1622inline bool
1624{
1625 return isfinite(s1.elem());
1626}
1627
1628
1630
1633template<class T>
1634inline bool
1636{
1637 bool d = true;
1638
1639#if defined(QDP_USE_PROFILING)
1640 static QDPProfile_t prof(d, OpAssign(), FnIsFinite(), s1);
1641 prof.time -= getClockTime();
1642#endif
1643
1644 const int nodeSites = Layout::sitesOnNode();
1645 for(int i=0; i < nodeSites; ++i)
1646 {
1647 d &= isfinite(s1.elem(i));
1648 }
1649
1651
1652#if defined(QDP_USE_PROFILING)
1653 prof.time += getClockTime();
1654 prof.count++;
1655 prof.print();
1656#endif
1657
1658 return d;
1659}
1660
1661
1663
1666template<class T>
1667inline bool
1669{
1670 return isnormal(s1.elem());
1671}
1672
1673
1675
1678template<class T>
1679inline bool
1681{
1682 bool d = true;
1683
1684#if defined(QDP_USE_PROFILING)
1685 static QDPProfile_t prof(d, OpAssign(), FnIsNormal(), s1);
1686 prof.time -= getClockTime();
1687#endif
1688
1689 const int nodeSites = Layout::sitesOnNode();
1690 for(int i=0; i < nodeSites; ++i)
1691 {
1692 d &= isnormal(s1.elem(i));
1693 }
1694
1696
1697#if defined(QDP_USE_PROFILING)
1698 prof.time += getClockTime();
1699 prof.count++;
1700 prof.print();
1701#endif
1702
1703 return d;
1704}
1705
1706
1707//-----------------------------------------------------------------------------
1708// Peek and poke at individual sites. This is very architecture specific
1709// NOTE: these two routines assume there is no underlying inner grid
1710
1712
1718template<class T1>
1719inline OScalar<T1>
1720peekSite(const OScalar<T1>& l, const multi1d<int>& coord)
1721{
1722 return l;
1723}
1724
1726
1732template<class RHS, class T1>
1733inline OScalar<T1>
1734peekSite(const QDPExpr<RHS,OScalar<T1> > & l, const multi1d<int>& coord)
1735{
1736 // For now, simply evaluate the expression and then call the function
1737 typedef OScalar<T1> C1;
1738
1739 return peekSite(C1(l), coord);
1740}
1741
1742
1743
1745
1751template<class T1>
1752inline OScalar<T1>
1753peekSite(const OLattice<T1>& l, const multi1d<int>& coord)
1754{
1755 OScalar<T1> dest;
1756 int nodenum = Layout::nodeNumber(coord);
1757
1758 // Find the result somewhere within the machine.
1759 // Then we must get it to node zero so we can broadcast it
1760 // out to all nodes
1761 if (Layout::nodeNumber() == nodenum)
1762 dest.elem() = l.elem(Layout::linearSiteIndex(coord));
1763 else
1764 zero_rep(dest.elem());
1765
1766 // Send result to primary node via some mechanism
1767 QDPInternal::sendToPrimaryNode(dest, nodenum);
1768
1769 // Now broadcast back out to all nodes
1771
1772 return dest;
1773}
1774
1776
1782template<class RHS, class T1>
1783inline OScalar<T1>
1784peekSite(const QDPExpr<RHS,OLattice<T1> > & l, const multi1d<int>& coord)
1785{
1786 // For now, simply evaluate the expression and then call the function
1787 typedef OLattice<T1> C1;
1788
1789 return peekSite(C1(l), coord);
1790}
1791
1792
1794
1801template<class T1>
1802inline OLattice<T1>&
1804{
1805 if (Layout::nodeNumber() == Layout::nodeNumber(coord))
1806 l.elem(Layout::linearSiteIndex(coord)) = r.elem();
1807
1808 return l;
1809}
1810
1811
1813
1819template<class T>
1820inline void
1821QDP_extract(multi1d<OScalar<T> >& dest, const OLattice<T>& src, const Subset& s)
1822{
1823 const int *tab = s.siteTable().slice();
1824 const int nodeSites = s.numSiteTable();
1825
1826#pragma omp parallel for
1827 for(int j=0; j < nodeSites; ++j)
1828 {
1829 int i = tab[j];
1830 dest[i].elem() = src.elem(i);
1831 }
1832}
1833
1835
1841template<class T>
1842inline void
1843QDP_insert(OLattice<T>& dest, const multi1d<OScalar<T> >& src, const Subset& s)
1844{
1845 const int *tab = s.siteTable().slice();
1846 const int nodeSites = s.numSiteTable();
1847
1848#pragma omp parallel for
1849 for(int j=0; j < nodeSites; ++j)
1850 {
1851 int i = tab[j];
1852 dest.elem(i) = src[i].elem();
1853 }
1854}
1855
1856
1857
1858//-----------------------------------------------------------------------------
1859// Map
1860//
1861
1862// Empty map
1863struct FnMap
1864{
1866};
1867
1868#if defined(QDP_USE_PROFILING)
1869template <>
1870struct TagVisitor<FnMap, PrintTag> : public ParenPrinter<FnMap>
1871{
1872 static void visit(FnMap op, PrintTag t)
1873 { t.os_m << "shift"; }
1874};
1875#endif
1876
1877
1879class Map
1880{
1881public:
1883 Map() {}
1884
1886 ~Map() {}
1887
1889 Map(const MapFunc& fn) {make(fn);}
1890
1892
1893 void make(const MapFunc& func);
1894
1896
1905 template<class T1>
1908 {
1909#if QDP_DEBUG >= 3
1910 QDP_info("Map()");
1911#endif
1912
1913 OLattice<T1> d;
1914 const int nodeSites = Layout::sitesOnNode();
1915
1916 if (offnodeP)
1917 {
1918 // Off-node communications required
1919#if QDP_DEBUG >= 3
1920 QDP_info("Map: off-node communications required");
1921#endif
1922
1923 // Eventually these declarations should move into d - the return object
1924 typedef T1 * T1ptr;
1925 T1 **dest = new(std::nothrow) T1ptr[nodeSites];
1926 if( dest == 0x0 ) {
1927 QDP_error_exit("Unable to new T1ptr in OLattice<T1>::operator()\n");
1928 }
1929 QMP_msgmem_t msg[2];
1930 QMP_msghandle_t mh_a[2], mh;
1931
1932#if 0
1933 // This test has been moved into Map::create.
1934 // For now, will assume there is only 1 destination nod e
1935 // and receive from only 1 node
1936 if (srcenodes.size() != 1)
1937 QDP_error_exit("Map: for now only allow 1 destination node");
1938
1939 if (destnodes.size() != 1)
1940 QDP_error_exit("Map: for now only allow receives from 1 node");
1941#endif
1942
1943 int dstnum = destnodes_num[0]*sizeof(T1);
1944 int srcnum = srcenodes_num[0]*sizeof(T1);
1945
1946 // Try getting fast and communicable memory
1947 QMP_mem_t *send_buf_mem = QMP_allocate_aligned_memory(dstnum,QDP_ALIGNMENT_SIZE,
1948 (QMP_MEM_COMMS|QMP_MEM_FAST) ); // packed data to send
1949 if( send_buf_mem == 0x0 ) {
1950 send_buf_mem = QMP_allocate_aligned_memory(dstnum, QDP_ALIGNMENT_SIZE,
1951 QMP_MEM_COMMS);
1952 if( send_buf_mem == 0x0 ) {
1953 QDP_error_exit("Unable to allocate send_buf_mem\n");
1954 }
1955 }
1956
1957 QMP_mem_t *recv_buf_mem = QMP_allocate_aligned_memory(srcnum,QDP_ALIGNMENT_SIZE,
1958 (QMP_MEM_COMMS|QMP_MEM_FAST)); // packed receive data
1959 if( recv_buf_mem == 0x0 ) {
1960 recv_buf_mem = QMP_allocate_aligned_memory(srcnum, QDP_ALIGNMENT_SIZE, QMP_MEM_COMMS);
1961 if( recv_buf_mem == 0x0 ) {
1962 QDP_error_exit("Unable to allocate recv_buf_mem\n");
1963 }
1964 }
1965
1966 T1 *send_buf = (T1 *)QMP_get_memory_pointer(send_buf_mem);
1967 T1 *recv_buf = (T1 *)QMP_get_memory_pointer(recv_buf_mem);
1968
1969 // Total and utter paranoia
1970 if ( send_buf == 0x0 ) {
1971 QDP_error_exit("QMP_get_memory_pointer returned NULL pointer from non NULL QMP_mem_t (send_buf)\n");
1972 }
1973
1974 if ( recv_buf == 0x0 ) {
1975 QDP_error_exit("QMP_get_memory_pointer returned NULL pointer from non NULL QMP_mem_t (recv_buf)\n");
1976 }
1977
1978 const int my_node = Layout::nodeNumber();
1979
1980 // Gather the face of data to send
1981 // For now, use the all subset
1982 for(int si=0; si < soffsets.size(); ++si)
1983 {
1984#if QDP_DEBUG >= 3
1985 QDP_info("Map_scatter_send(buf[%d],olattice[%d])",si,soffsets[si]);
1986#endif
1987
1988 send_buf[si] = l.elem(soffsets[si]);
1989 }
1990
1991 // Set the dest gather pointers
1992 // For now, use the all subset
1993
1994 // no threading to avoid confusion with order of recv_buf (and fast anyways)
1995 for(int i=0, ri=0; i < nodeSites; ++i)
1996 {
1997 if (srcnode[i] != my_node)
1998 {
1999#if QDP_DEBUG >= 3
2000 QDP_info("Map_gather_recv(olattice[%d],recv[%d])",i,ri);
2001#endif
2002
2003 dest[i] = &(recv_buf[ri++]);
2004 }
2005 else
2006 {
2007#if QDP_DEBUG >= 3
2008 QDP_info("Map_gather_onnode(olattice[%d],olattice[%d])",i,goffsets[i]);
2009#endif
2010
2011 dest[i] = &(const_cast<T1&>(l.elem(goffsets[i])));
2012 }
2013 }
2014
2015 QMP_status_t err;
2016
2017#if QDP_DEBUG >= 3
2018 QDP_info("Map: send = 0x%x recv = 0x%x",send_buf,recv_buf);
2019 QDP_info("Map: establish send=%d recv=%d",destnodes[0],srcenodes[0]);
2020 {
2021 const multi1d<int>& me = Layout::nodeCoord();
2022 multi1d<int> scrd = Layout::getLogicalCoordFrom(destnodes[0]);
2023 multi1d<int> rcrd = Layout::getLogicalCoordFrom(srcenodes[0]);
2024
2025 QDP_info("Map: establish-info my_crds=[%d,%d,%d,%d]",me[0],me[1],me[2],me[3]);
2026 QDP_info("Map: establish-info send_crds=[%d,%d,%d,%d]",scrd[0],scrd[1],scrd[2],scrd[3]);
2027 QDP_info("Map: establish-info recv_crds=[%d,%d,%d,%d]",rcrd[0],rcrd[1],rcrd[2],rcrd[3]);
2028 }
2029#endif
2030
2031 msg[0] = QMP_declare_msgmem(recv_buf, srcnum);
2032 if( msg[0] == (QMP_msgmem_t)NULL ) {
2033 QDP_error_exit("QMP_declare_msgmem for msg[0] failed in Map::operator()\n");
2034 }
2035 msg[1] = QMP_declare_msgmem(send_buf, dstnum);
2036 if( msg[1] == (QMP_msgmem_t)NULL ) {
2037 QDP_error_exit("QMP_declare_msgmem for msg[1] failed in Map::operator()\n");
2038 }
2039
2040 mh_a[0] = QMP_declare_receive_from(msg[0], srcenodes[0], 0);
2041 if( mh_a[0] == (QMP_msghandle_t)NULL ) {
2042 QDP_error_exit("QMP_declare_receive_from for mh_a[0] failed in Map::operator()\n");
2043 }
2044
2045 mh_a[1] = QMP_declare_send_to(msg[1], destnodes[0], 0);
2046 if( mh_a[1] == (QMP_msghandle_t)NULL ) {
2047 QDP_error_exit("QMP_declare_send_to for mh_a[1] failed in Map::operator()\n");
2048 }
2049
2050 mh = QMP_declare_multiple(mh_a, 2);
2051 if( mh == (QMP_msghandle_t)NULL ) {
2052 QDP_error_exit("QMP_declare_multiple for mh failed in Map::operator()\n");
2053 }
2054
2055#if QDP_DEBUG >= 3
2056 QDP_info("Map: calling start send=%d recv=%d",destnodes[0],srcenodes[0]);
2057#endif
2058
2059 // Launch the faces
2060 if ((err = QMP_start(mh)) != QMP_SUCCESS)
2061 QDP_error_exit(QMP_error_string(err));
2062
2063#if QDP_DEBUG >= 3
2064 QDP_info("Map: calling wait");
2065#endif
2066
2067 // Wait on the faces
2068 if ((err = QMP_wait(mh)) != QMP_SUCCESS)
2069 QDP_error_exit(QMP_error_string(err));
2070
2071#if QDP_DEBUG >= 3
2072 QDP_info("Map: calling free msgs");
2073#endif
2074
2075 // QMP_free_msghandle(mh_a[1]);
2076 // QMP_free_msghandle(mh_a[0]);
2077 QMP_free_msghandle(mh);
2078 QMP_free_msgmem(msg[1]);
2079 QMP_free_msgmem(msg[0]);
2080
2081 // Scatter the data into the destination
2082 // Some of the data maybe in receive buffers
2083 // For now, use the all subset
2084#pragma omp parallel for
2085 for(int i=0; i < nodeSites; ++i)
2086 {
2087#if QDP_DEBUG >= 3
2088 QDP_info("Map_scatter(olattice[%d],olattice[0x%x])",i,dest[i]);
2089#endif
2090 d.elem(i) = *(dest[i]);
2091 }
2092
2093 // Cleanup
2094 QMP_free_memory(recv_buf_mem);
2095 QMP_free_memory(send_buf_mem);
2096 delete[] dest;
2097
2098#if QDP_DEBUG >= 3
2099 QDP_info("finished cleanup");
2100#endif
2101 }
2102 else
2103 {
2104 // No off-node communications - copy on node
2105#if QDP_DEBUG >= 3
2106 QDP_info("Map: copy on node - no communications, try this");
2107#endif
2108
2109 // For now, use the all subset
2110#pragma omp parallel for
2111 for(int i=0; i < nodeSites; ++i)
2112 {
2113#if QDP_DEBUG >= 3
2114 QDP_info("Map(olattice[%d],olattice[%d])",i,goffsets[i]);
2115#endif
2116 d.elem(i) = l.elem(goffsets[i]);
2117 }
2118 }
2119
2120#if QDP_DEBUG >= 3
2121 QDP_info("exiting Map()");
2122#endif
2123
2124 return d;
2125 }
2126
2127
2128 template<class T1>
2131 {
2132 return l;
2133 }
2134
2135 template<class RHS, class T1>
2138 {
2139 // For now, simply evaluate the expression and then do the map
2140 typedef OScalar<T1> C1;
2141
2142// fprintf(stderr,"map(QDPExpr<OScalar>)\n");
2143 OScalar<T1> d = this->operator()(C1(l));
2144
2145 return d;
2146 }
2147
2148 template<class RHS, class T1>
2151 {
2152 // For now, simply evaluate the expression and then do the map
2153 typedef OLattice<T1> C1;
2154
2155// fprintf(stderr,"map(QDPExpr<OLattice>)\n");
2156 OLattice<T1> d = this->operator()(C1(l));
2157
2158 return d;
2159 }
2160
2161
2162public:
2164 const multi1d<int>& goffset() const {return goffsets;}
2165 const multi1d<int>& soffset() const {return soffsets;}
2166
2167private:
2169 Map(const Map&) {}
2170
2172 void operator=(const Map&) {}
2173
2174private:
2176
2180 multi1d<int> goffsets;
2181 multi1d<int> soffsets;
2182 multi1d<int> srcnode;
2183 multi1d<int> dstnode;
2184
2185 multi1d<int> srcenodes;
2186 multi1d<int> destnodes;
2187
2188 multi1d<int> srcenodes_num;
2189 multi1d<int> destnodes_num;
2190
2191 // Indicate off-node communications is needed;
2192 bool offnodeP;
2193};
2194
2195
2196//-----------------------------------------------------------------------------
2199{
2200public:
2203
2206
2208 ArrayMap(const ArrayMapFunc& fn) {make(fn);}
2209
2211
2212 void make(const ArrayMapFunc& func);
2213
2215
2224 template<class T1>
2226 operator()(const OLattice<T1> & l, int dir)
2227 {
2228#if QDP_DEBUG >= 3
2229 QDP_info("ArrayMap(OLattice,%d)",dir);
2230#endif
2231
2232 return mapsa[dir](l);
2233 }
2234
2235 template<class T1>
2237 operator()(const OScalar<T1> & l, int dir)
2238 {
2239#if QDP_DEBUG >= 3
2240 QDP_info("ArrayMap(OScalar,%d)",dir);
2241#endif
2242
2243 return mapsa[dir](l);
2244 }
2245
2246
2247 template<class RHS, class T1>
2249 operator()(const QDPExpr<RHS,OScalar<T1> > & l, int dir)
2250 {
2251// fprintf(stderr,"ArrayMap(QDPExpr<OScalar>,%d)\n",dir);
2252
2253 // For now, simply evaluate the expression and then do the map
2254 return mapsa[dir](l);
2255 }
2256
2257 template<class RHS, class T1>
2259 operator()(const QDPExpr<RHS,OLattice<T1> > & l, int dir)
2260 {
2261// fprintf(stderr,"ArrayMap(QDPExpr<OLattice>,%d)\n",dir);
2262
2263 // For now, simply evaluate the expression and then do the map
2264 return mapsa[dir](l);
2265 }
2266
2267
2268private:
2270 ArrayMap(const ArrayMap&) {}
2271
2273 void operator=(const ArrayMap&) {}
2274
2275private:
2276 multi1d<Map> mapsa;
2277
2278};
2279
2280//-----------------------------------------------------------------------------
2283{
2284public:
2287
2290
2293
2295
2296 void make(const MapFunc& func);
2297
2299
2308 template<class T1>
2310 operator()(const OLattice<T1> & l, int isign)
2311 {
2312#if QDP_DEBUG >= 3
2313 QDP_info("BiDirectionalMap(OLattice,%d)",isign);
2314#endif
2315
2316 return bimaps[(isign+1)>>1](l);
2317 }
2318
2319
2320 template<class T1>
2322 operator()(const OScalar<T1> & l, int isign)
2323 {
2324#if QDP_DEBUG >= 3
2325 QDP_info("BiDirectionalMap(OScalar,%d)",isign);
2326#endif
2327
2328 return bimaps[(isign+1)>>1](l);
2329 }
2330
2331
2332 template<class RHS, class T1>
2334 operator()(const QDPExpr<RHS,OScalar<T1> > & l, int isign)
2335 {
2336// fprintf(stderr,"BiDirectionalMap(QDPExpr<OScalar>,%d)\n",isign);
2337
2338 // For now, simply evaluate the expression and then do the map
2339 return bimaps[(isign+1)>>1](l);
2340 }
2341
2342 template<class RHS, class T1>
2344 operator()(const QDPExpr<RHS,OLattice<T1> > & l, int isign)
2345 {
2346// fprintf(stderr,"BiDirectionalMap(QDPExpr<OLattice>,%d)\n",isign);
2347
2348 // For now, simply evaluate the expression and then do the map
2349 return bimaps[(isign+1)>>1](l);
2350 }
2351
2352
2353private:
2356
2358 void operator=(const BiDirectionalMap&) {}
2359
2360private:
2361 multi1d<Map> bimaps;
2362
2363};
2364
2365
2366//-----------------------------------------------------------------------------
2369{
2370public:
2373
2376
2379
2381
2382 void make(const ArrayMapFunc& func);
2383
2385
2402 template<class T1>
2404 operator()(const OLattice<T1> & l, int isign, int dir)
2405 {
2406#if QDP_DEBUG >= 3
2407 QDP_info("ArrayBiDirectionalMap(OLattice,%d,%d)",isign,dir);
2408#endif
2409
2410 return bimapsa((isign+1)>>1,dir)(l);
2411 }
2412
2413 template<class T1>
2415 operator()(const OScalar<T1> & l, int isign, int dir)
2416 {
2417#if QDP_DEBUG >= 3
2418 QDP_info("ArrayBiDirectionalMap(OScalar,%d,%d)",isign,dir);
2419#endif
2420
2421 return bimapsa((isign+1)>>1,dir)(l);
2422 }
2423
2424
2425 template<class RHS, class T1>
2427 operator()(const QDPExpr<RHS,OScalar<T1> > & l, int isign, int dir)
2428 {
2429// fprintf(stderr,"ArrayBiDirectionalMap(QDPExpr<OScalar>,%d,%d)\n",isign,dir);
2430
2431 // For now, simply evaluate the expression and then do the map
2432 return bimapsa((isign+1)>>1,dir)(l);
2433 }
2434
2435 template<class RHS, class T1>
2437 operator()(const QDPExpr<RHS,OLattice<T1> > & l, int isign, int dir)
2438 {
2439// fprintf(stderr,"ArrayBiDirectionalMap(QDPExpr<OLattice>,%d,%d)\n",isign,dir);
2440
2441 // For now, simply evaluate the expression and then do the map
2442 return bimapsa((isign+1)>>1,dir)(l);
2443 }
2444
2445
2446private:
2449
2451 void operator=(const ArrayBiDirectionalMap&) {}
2452
2453private:
2454 multi2d<Map> bimapsa;
2455
2456};
2457
2458
2459//-----------------------------------------------------------------------------
2460
2462
2463template<class T>
2464inline
2465void write(BinaryWriter& bin, const OScalar<T>& d)
2466{
2467 bin.writeArray((const char *)&(d.elem()),
2468 sizeof(typename WordType<T>::Type_t),
2469 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2470}
2471
2472
2474
2475template<class T>
2477{
2478 bin.readArray((char*)&(d.elem()),
2479 sizeof(typename WordType<T>::Type_t),
2480 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2481}
2482
2483
2484
2485// There are 2 main classes of binary/xml reader/writer methods.
2486// The first is a simple/portable but inefficient method of send/recv
2487// to/from the destination node.
2488// The second method (the else) is a more efficient roll-around method.
2489// However, this method more constrains the data layout - it must be
2490// close to the original lexicographic order.
2491// For now, use the direct send method
2492
2494multi1d<int> crtesn(int ipos, const multi1d<int>& latt_size);
2495
2497template<class T>
2499{
2500 T recv_buf;
2501
2502 xml.openTag("OLattice");
2503 XMLWriterAPI::AttributeList alist;
2504
2505 // Find the location of each site and send to primary node
2506 for(int site=0; site < Layout::vol(); ++site)
2507 {
2508 multi1d<int> coord = crtesn(site, Layout::lattSize());
2509
2510 int node = Layout::nodeNumber(coord);
2511 int linear = Layout::linearSiteIndex(coord);
2512
2513 // Copy to buffer: be really careful since max(linear) could vary among nodes
2514 if (Layout::nodeNumber() == node)
2515 recv_buf = d.elem(linear);
2516
2517 // Send result to primary node. Avoid sending prim-node sending to itself
2518 if (node != 0)
2519 {
2520#if 1
2521 // All nodes participate
2522 QDPInternal::route((void *)&recv_buf, node, 0, sizeof(T));
2523#else
2524 if (Layout::primaryNode())
2525 QDPInternal::recvFromWait((void *)&recv_buf, node, sizeof(T));
2526
2527 if (Layout::nodeNumber() == node)
2528 QDPInternal::sendToWait((void *)&recv_buf, 0, sizeof(T));
2529#endif
2530 }
2531
2532 if (Layout::primaryNode())
2533 {
2534 std::ostringstream os;
2535 os << coord[0];
2536 for(int i=1; i < coord.size(); ++i)
2537 os << " " << coord[i];
2538
2539 alist.clear();
2540 alist.push_back(XMLWriterAPI::Attribute("site", site));
2541 alist.push_back(XMLWriterAPI::Attribute("coord", os.str()));
2542
2543 xml.openTag("elem", alist);
2544 xml << recv_buf;
2545 xml.closeTag();
2546 }
2547 }
2548
2549 xml.closeTag(); // OLattice
2550 return xml;
2551}
2552
2553
2555
2556void writeOLattice(BinaryWriter& bin,
2557 const char* output, size_t size, size_t nmemb);
2558
2560
2561template<class T>
2562void write(BinaryWriter& bin, const OLattice<T>& d)
2563{
2564 writeOLattice(bin, (const char *)&(d.elem(0)),
2565 sizeof(typename WordType<T>::Type_t),
2566 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2567}
2568
2570
2571void writeOLattice(BinaryWriter& bin,
2572 const char* output, size_t size, size_t nmemb,
2573 const multi1d<int>& coord);
2574
2576
2577template<class T>
2578void write(BinaryWriter& bin, const OLattice<T>& d, const multi1d<int>& coord)
2579{
2580 writeOLattice(bin, (const char *)&(d.elem(0)),
2581 sizeof(typename WordType<T>::Type_t),
2582 sizeof(T) / sizeof(typename WordType<T>::Type_t),
2583 coord);
2584}
2585
2587
2588void writeOLattice(BinaryWriter& bin,
2589 const char* output, size_t size, size_t nmemb,
2590 const Subset& sub);
2591
2593
2594template<class T>
2596{
2597 const OLattice<T>& d = dd.field();
2598
2599 writeOLattice(bin, (const char *)&(d.elem(0)),
2600 sizeof(typename WordType<T>::Type_t),
2601 sizeof(T) / sizeof(typename WordType<T>::Type_t),
2602 dd.subset());
2603}
2604
2605
2607
2608void readOLattice(BinaryReader& bin,
2609 char* input, size_t size, size_t nmemb);
2610
2612
2613template<class T>
2615{
2616 readOLattice(bin, (char *)&(d.elem(0)),
2617 sizeof(typename WordType<T>::Type_t),
2618 sizeof(T) / sizeof(typename WordType<T>::Type_t));
2619}
2620
2622
2623void readOLattice(BinaryReader& bin,
2624 char* input, size_t size, size_t nmemb,
2625 const multi1d<int>& coord);
2626
2628
2629template<class T>
2630void read(BinaryReader& bin, OLattice<T>& d, const multi1d<int>& coord)
2631{
2632 readOLattice(bin, (char *)&(d.elem(0)),
2633 sizeof(typename WordType<T>::Type_t),
2634 sizeof(T) / sizeof(typename WordType<T>::Type_t),
2635 coord);
2636}
2637
2639
2640void readOLattice(BinaryReader& bin,
2641 char* input, size_t size, size_t nmemb,
2642 const Subset& sub);
2643
2645
2646template<class T>
2648{
2649 readOLattice(bin, (char *)(d.field().getF()),
2650 sizeof(typename WordType<T>::Type_t),
2651 sizeof(T) / sizeof(typename WordType<T>::Type_t),
2652 d.subset());
2653}
2654
2655
2656
2657// **************************************************************
2658// Special support for slices of a lattice
2659namespace LatticeTimeSliceIO
2660{
2662 void readOLatticeSlice(BinaryReader& bin, char* data,
2663 size_t size, size_t nmemb,
2664 int start_lexico, int stop_lexico);
2665
2666 void writeOLatticeSlice(BinaryWriter& bin, const char* data,
2667 size_t size, size_t nmemb,
2668 int start_lexico, int stop_lexico);
2669
2670
2671 // Read a time slice of a lattice quantity (time must be most slowly varying)
2672 template<class T>
2674 int start_lexico, int stop_lexico)
2675 {
2676 readOLatticeSlice(bin, (char *)&(data.elem(0)),
2677 sizeof(typename WordType<T>::Type_t),
2678 sizeof(T) / sizeof(typename WordType<T>::Type_t),
2679 start_lexico, stop_lexico);
2680 }
2681
2682
2683 // Write a time slice of a lattice quantity (time must be most slowly varying)
2684 template<class T>
2685 void writeSlice(BinaryWriter& bin, const OLattice<T>& data,
2686 int start_lexico, int stop_lexico)
2687 {
2688 writeOLatticeSlice(bin, (const char *)&(data.elem(0)),
2689 sizeof(typename WordType<T>::Type_t),
2690 sizeof(T) / sizeof(typename WordType<T>::Type_t),
2691 start_lexico, stop_lexico);
2692 }
2693
2694} // namespace LatticeTimeSliceIO
2695
2696} // namespace QDP
2697#endif
#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.
Binary input base class.
Definition qdp_io.h:372
virtual void readArray(char *output, size_t nbytes, size_t nmemb)
Read data on the primary node and broadcast to all nodes.
Definition qdp_io.cc:706
Binary writer base class.
Definition qdp_io.h:1010
virtual void writeArray(const char *output, size_t nbytes, size_t nmemb)
Write data from the primary node.
Definition qdp_io.cc:1182
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
QDPType - major type class/container for all QDP objects.
Definition qdp_qdptype.h:29
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
const multi1d< int > & latticeColoring() const
The coloring of the lattice sites.
Definition qdp_subset.h:131
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
Metadata output class.
Definition qdp_xmlio.h:506
void openTag(const std::string &tagname)
Writes an opening XML tag.
Definition qdp_xmlio.cc:636
void closeTag()
Closes a tag.
Definition qdp_xmlio.cc:662
Container for a multi-dimensional 1D array.
Definition qdp_multi.h:25
int size() const
Size of array.
Definition qdp_multi.h:60
const T * slice() const
Return ref to a column slice.
Definition qdp_multi.h:225
Container for a multi-dimensional 2D array.
Definition qdp_multi.h:640
const T * slice(int j) const
Return ref to a row slice.
Definition qdp_multi.h:706
int size1() const
Size of array.
Definition qdp_multi.h:673
int size2() const
Definition qdp_multi.h:674
OLattice< PScalar< PSeed< RScalar< INTEGER32 > > > > LatticeSeed
OScalar< PScalar< PSeed< RScalar< INTEGER32 > > > > Seed
OLattice< PScalar< PScalar< RScalar< INTEGER32 > > > > LatticeInteger
void QDP_extract(multi1d< OScalar< T > > &dest, const OLattice< T > &src, const Subset &s)
Copy data values from field src to array dest.
OLattice< T1 > & pokeSite(OLattice< T1 > &l, const OScalar< T1 > &r, const multi1d< int > &coord)
Insert site element.
OScalar< T1 > peekSite(const QDPExpr< RHS, OScalar< T1 > > &l, const multi1d< int > &coord)
Extract site element.
void QDP_insert(OLattice< T > &dest, const multi1d< OScalar< T > > &src, const Subset &s)
Inserts data values from site array src.
OScalar< T1 > peekSite(const OScalar< T1 > &l, const multi1d< int > &coord)
Extract site element.
OScalar< T1 > 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.
BinaryReturn< C1, C2, FnInnerProductReal >::Type_t innerProductReal(const QDPType< T1, C1 > &s1, const QDPType< T2, C2 > &s2)
OScalar = innerProductReal(adj(source1)*source2).
UnaryReturn< C, FnGlobalMin >::Type_t globalMin(const QDPType< T, C > &s1)
OScalar = globalMin(source).
UnaryReturn< C, FnNorm2 >::Type_t norm2(const QDPType< T, C > &s1)
OScalar = norm2(trace(adj(source)*source)).
bool isnan(const QDPExpr< T, C > &s1)
bool = isnan(source)
bool isfinite(const QDPExpr< T, C > &s1)
bool = isfinite(source)
BinaryReturn< C1, C2, FnInnerProduct >::Type_t innerProduct(const QDPType< T1, C1 > &s1, const QDPType< T2, C2 > &s2)
OScalar = innerProduct(adj(source1)*source2).
bool isnormal(const QDPExpr< T, C > &s1)
bool = isnormal(source)
bool isinf(const QDPExpr< T, C > &s1)
bool = isinf(source)
UnaryReturn< C, FnGlobalMax >::Type_t globalMax(const QDPType< T, C > &s1)
OScalar = globalMax(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).
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 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
bool toBool(const IScalar< T > &s)
QDP Boolean to bool primitive in conversion routine.
Definition qdp_inner.h:1639
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
void readSlice(BinaryReader &bin, OLattice< T > &data, int start_lexico, int stop_lexico)
void writeOLatticeSlice(BinaryWriter &bin, const char *output, size_t size, size_t nmemb, int start_lexico, int stop_lexico)
void readOLatticeSlice(BinaryReader &bin, char *input, size_t size, size_t nmemb, int start_lexico, int stop_lexico)
Lattice time slice reader.
void writeSlice(BinaryWriter &bin, const OLattice< T > &data, int start_lexico, int stop_lexico)
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.
const multi1d< int > & lattSize()
Virtual grid (problem grid) lattice size.
multi1d< int > getLogicalCoordFrom(int node)
Returns the logical node coordinates given some node number.
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.
const multi1d< int > & nodeCoord()
Returns the logical node coordinates for this node.
StandardOutputStream cout
Definition qdp_stdio.cc:21
void globalOr(bool &dest)
Wrapper to get a functional global Or.
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 globalMax(T &dest)
Global max across all nodes.
void globalCheckAnd(void *inout, void *in)
Global And.
void globalSum(T &dest)
Sum across all nodes.
void globalCheckOr(void *inout, void *in)
Global Or.
void route(void *buffer, int srce_node, int dest_node, int count)
Route to another node (blocking).
void globalMinValue(float *dest)
Low level hook to QMP_min_float.
void sendToPrimaryNode(T &dest, int srcnode)
Via some mechanism, get the dest to node 0.
void wait(int dir)
Wait on send-receive.
void globalAnd(bool &dest)
Wrapper to get a functional global And.
void recvFromWait(void *recv_buf, int srce_node, int count)
Receive from another node (wait).
void globalMin(T &dest)
Global min across all nodes.
void broadcast_str(std::string &result)
Broadcast a string from primary node to all other nodes.
void globalMaxValue(float *dest)
Low level hook to QMP_max_double.
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.
void dispatch_to_threads(int numSiteTable, Arg a, void(*func)(int, int, int, Arg *))
ForEach< Expr, FTag, CTag >::Type_t forEach(const Expr &e, const FTag &f, const CTag &c)
Definition qdp.h:88
void evaluate_userfunc(int lo, int hi, int myId, user_arg< T, T1, Op, RHS > *a)
user function for the evaluate function:
int qdpThreadNum()
void QDP_error_exit(const char *format,...)
Simple error display and abort routine.
Definition qdp_util.cc:93
MakeReturn< BinaryNode< FnLocalInnerProductReal, typenameCreateLeaf< QDPType< T1, C1 > >::Leaf_t, typenameCreateLeaf< QDPExpr< T2, C2 > >::Leaf_t >, typenameBinaryReturn< C1, C2, FnLocalInnerProductReal >::Type_t >::Expression_t localInnerProductReal(const QDPType< T1, C1 > &l, const QDPExpr< T2, C2 > &r)
Definition qdp.h:2428
QDPTime_t getClockTime()
Get the wallclock time.
void evaluate_F(T *dest, const Op &op, const QDPExpr< RHS, OScalar< T1 > > &rhs, const Subset &s)
Definition qdp_outer.h:242
void readOLattice(BinaryReader &bin, char *input, size_t size, size_t nmemb)
Read a lattice quantity.
MakeReturn< BinaryNode< FnLocalInnerProduct, typenameCreateLeaf< QDPType< T1, C1 > >::Leaf_t, typenameCreateLeaf< QDPExpr< T2, C2 > >::Leaf_t >, typenameBinaryReturn< C1, C2, FnLocalInnerProduct >::Type_t >::Expression_t localInnerProduct(const QDPType< T1, C1 > &l, const QDPExpr< T2, C2 > &r)
Definition qdp.h:2412
void writeOLattice(BinaryWriter &bin, const char *output, size_t size, size_t nmemb)
Write a lattice quantity.
void ev_userfunc(int lo, int hi, int myId, u_arg< T, T1, Op, RHS > *a)
user function for the evaluate function:
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
FnMap(const int *goffsets)
user argument for the evaluate function:
u_arg(OLattice< T > &d_, const QDPExpr< RHS, OScalar< T1 > > &r_, const Op &op_, const int *tab_)
const QDPExpr< RHS, OScalar< T1 > > & r
OLattice< T > & d
user argument for the evaluate function:
user_arg(OLattice< T > &d_, const QDPExpr< RHS, OLattice< T1 > > &r_, const Op &op_, const int *tab_)
const QDPExpr< RHS, OLattice< T1 > > & r