mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-10-25 10:09:34 +01:00 
			
		
		
		
	Compare commits
	
		
			84 Commits
		
	
	
		
			hotfix/vir
			...
			feature/gp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 4fefae1745 | ||
|  | 758e2edcad | ||
|  | 1538b15f3b | ||
|  | deac621c2c | ||
|  | ba974960e6 | ||
|  | 6755dc57f8 | ||
|  | aa620ca52c | ||
|  | 2c46c942cc | ||
|  | adeba8059a | ||
|  | c4ac528126 | ||
|  | 551b93ba8e | ||
|  | ddf7540510 | ||
|  | de68d12c3d | ||
|  | 6d26a2a1ad | ||
|  | a1211cdcce | ||
|  | e78acf77ff | ||
|  | f7e9621492 | ||
|  | f14be15f8b | ||
|  | 6a3aaa52ef | ||
|  | 9ba47b4696 | ||
|  | e85af80c39 | ||
|  | 0b91e90dd4 | ||
|  | d184b8c921 | ||
|  | c92e390b08 | ||
|  | 5b36a8af54 | ||
|  | 75a1f85162 | ||
|  | ac4f2d9798 | ||
|  | c3b99de33f | ||
|  | e1a02bb80a | ||
|  | 86f08c6b9a | ||
|  | 9f0271039f | ||
|  | 24df770f74 | ||
|  | 45b6c7effc | ||
|  | 1c70d8c4d9 | ||
|  | f0e9a5299f | ||
|  | f1b8ba45e7 | ||
|  | fe998ab578 | ||
|  | c2ee2b5fd1 | ||
|  | 3b734ee397 | ||
|  | 8637a9512a | ||
|  | 7f6e2ee03e | ||
|  | 7b02acb2bd | ||
|  | 86948c6ea0 | ||
|  | 53d226924a | ||
|  | 80176b1b39 | ||
|  | 29ddafd0fc | ||
|  | 0f08364e4f | ||
|  | a198d59381 | ||
|  | 3a4f5f2324 | ||
|  | 824d84473f | ||
|  | 38964a4076 | ||
|  | 0d9aa87228 | ||
|  | 0e959d9b94 | ||
|  | 752f70cd48 | ||
|  | e0e42873c1 | ||
|  | 0ff3bf6dc5 | ||
|  | 351eab02ae | ||
|  | feee5ccde2 | ||
|  | e0f6a146d8 | ||
|  | daa095c519 | ||
|  | c2676853ca | ||
|  | 6a824033f8 | ||
|  | cee6a37639 | ||
|  | 6cc3ad110c | ||
|  | e6c6f82c52 | ||
|  | d10d0c4e7f | ||
|  | 9c106d625a | ||
|  | 6795bbca31 | ||
|  | d161c2dc35 | ||
|  | 7a06826cf1 | ||
|  | c3712b8e06 | ||
|  | 901ee77b84 | ||
|  | 1b84f59273 | ||
|  | 1fb41a4300 | ||
|  | 287bac946f | ||
|  | 80c14be65e | ||
|  | d7a2a4852d | ||
|  | d185f2eaa7 | ||
|  | 813d4cd900 | ||
|  | 75c6c6b173 | ||
|  | 220ad5e3ee | ||
|  | ba5dc670a5 | ||
|  | a0ca362690 | ||
|  | 249b6e61ec | 
| @@ -34,6 +34,9 @@ directory | ||||
|  | ||||
| #if defined __GNUC__ && __GNUC__>=6 | ||||
| #pragma GCC diagnostic ignored "-Wignored-attributes" | ||||
| #endif | ||||
| #if defined __GNUC__  | ||||
| #pragma GCC diagnostic ignored "-Wpsabi" | ||||
| #endif | ||||
|  | ||||
|  //disables and intel compiler specific warning (in json.hpp) | ||||
| @@ -44,22 +47,14 @@ directory | ||||
| #ifdef __NVCC__ | ||||
|  //disables nvcc specific warning in json.hpp | ||||
| #pragma clang diagnostic ignored "-Wdeprecated-register" | ||||
|  | ||||
| #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ | ||||
|  //disables nvcc specific warning in json.hpp | ||||
| #pragma nv_diag_suppress unsigned_compare_with_zero | ||||
| #pragma nv_diag_suppress cast_to_qualified_type | ||||
|  //disables nvcc specific warning in many files | ||||
| #pragma nv_diag_suppress esa_on_defaulted_function_ignored | ||||
| #pragma nv_diag_suppress extra_semicolon | ||||
| #else | ||||
|  //disables nvcc specific warning in json.hpp | ||||
| #pragma diag_suppress unsigned_compare_with_zero | ||||
| #pragma diag_suppress cast_to_qualified_type | ||||
|  | ||||
|  //disables nvcc specific warning in many files | ||||
| #pragma diag_suppress esa_on_defaulted_function_ignored | ||||
| #pragma diag_suppress extra_semicolon | ||||
| #endif | ||||
|  | ||||
| //Eigen only | ||||
| #endif | ||||
|  | ||||
| // Disable vectorisation in Eigen on the Power8/9 and PowerPC | ||||
|   | ||||
| @@ -44,10 +44,9 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| #include <Grid/GridStd.h> | ||||
| #include <Grid/threads/Pragmas.h> | ||||
| #include <Grid/perfmon/Timer.h> | ||||
| //#include <Grid/perfmon/PerfCount.h> | ||||
| #include <Grid/perfmon/PerfCount.h> | ||||
| #include <Grid/util/Util.h> | ||||
| #include <Grid/log/Log.h> | ||||
| #include <Grid/perfmon/Tracing.h> | ||||
| #include <Grid/allocator/Allocator.h> | ||||
| #include <Grid/simd/Simd.h> | ||||
| #include <Grid/threads/ThreadReduction.h> | ||||
|   | ||||
| @@ -16,7 +16,6 @@ | ||||
| #include <functional> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <strings.h> | ||||
| #include <stdio.h> | ||||
| #include <signal.h> | ||||
| #include <ctime> | ||||
|   | ||||
| @@ -14,11 +14,7 @@ | ||||
| /* NVCC save and restore compile environment*/ | ||||
| #ifdef __NVCC__ | ||||
| #pragma push | ||||
| #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ | ||||
| #pragma nv_diag_suppress code_is_unreachable | ||||
| #else | ||||
| #pragma diag_suppress code_is_unreachable | ||||
| #endif | ||||
| #pragma push_macro("__CUDA_ARCH__") | ||||
| #pragma push_macro("__NVCC__") | ||||
| #pragma push_macro("__CUDACC__") | ||||
|   | ||||
| @@ -55,7 +55,6 @@ NAMESPACE_CHECK(BiCGSTAB); | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientMultiShift.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientMixedPrec.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientMultiShiftMixedPrec.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientMixedPrecBatched.h> | ||||
| #include <Grid/algorithms/iterative/BiCGSTABMixedPrec.h> | ||||
| #include <Grid/algorithms/iterative/BlockConjugateGradient.h> | ||||
| #include <Grid/algorithms/iterative/ConjugateGradientReliableUpdate.h> | ||||
|   | ||||
| @@ -262,7 +262,7 @@ public: | ||||
| 	autoView( Tnp_v , (*Tnp), AcceleratorWrite); | ||||
| 	autoView( Tnm_v , (*Tnm), AcceleratorWrite); | ||||
| 	const int Nsimd = CComplex::Nsimd(); | ||||
| 	accelerator_for(ss, FineGrid->oSites(), Nsimd, { | ||||
| 	accelerator_forNB(ss, FineGrid->oSites(), Nsimd, { | ||||
| 	  coalescedWrite(y_v[ss],xscale*y_v(ss)+mscale*Tn_v(ss)); | ||||
| 	  coalescedWrite(Tnp_v[ss],2.0*y_v(ss)-Tnm_v(ss)); | ||||
|         }); | ||||
| @@ -324,9 +324,9 @@ public: | ||||
|   GridBase*        _cbgrid; | ||||
|   int hermitian; | ||||
|  | ||||
|   CartesianStencil<siteVector,siteVector,DefaultImplParams> Stencil;  | ||||
|   CartesianStencil<siteVector,siteVector,DefaultImplParams> StencilEven; | ||||
|   CartesianStencil<siteVector,siteVector,DefaultImplParams> StencilOdd; | ||||
|   CartesianStencil<siteVector,siteVector,int> Stencil;  | ||||
|   CartesianStencil<siteVector,siteVector,int> StencilEven; | ||||
|   CartesianStencil<siteVector,siteVector,int> StencilOdd; | ||||
|  | ||||
|   std::vector<CoarseMatrix> A; | ||||
|   std::vector<CoarseMatrix> Aeven; | ||||
| @@ -631,7 +631,7 @@ public: | ||||
|     assert(Aself != nullptr); | ||||
|   } | ||||
|  | ||||
|   void DselfInternal(CartesianStencil<siteVector,siteVector,DefaultImplParams> &st, CoarseMatrix &a, | ||||
|   void DselfInternal(CartesianStencil<siteVector,siteVector,int> &st, CoarseMatrix &a, | ||||
|                        const CoarseVector &in, CoarseVector &out, int dag) { | ||||
|     int point = geom.npoint-1; | ||||
|     autoView( out_v, out, AcceleratorWrite); | ||||
| @@ -694,7 +694,7 @@ public: | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void DhopInternal(CartesianStencil<siteVector,siteVector,DefaultImplParams> &st, std::vector<CoarseMatrix> &a, | ||||
|   void DhopInternal(CartesianStencil<siteVector,siteVector,int> &st, std::vector<CoarseMatrix> &a, | ||||
|                     const CoarseVector &in, CoarseVector &out, int dag) { | ||||
|     SimpleCompressor<siteVector> compressor; | ||||
|  | ||||
| @@ -784,9 +784,9 @@ public: | ||||
|     _cbgrid(new GridRedBlackCartesian(&CoarseGrid)), | ||||
|     geom(CoarseGrid._ndimension), | ||||
|     hermitian(hermitian_), | ||||
|     Stencil(&CoarseGrid,geom.npoint,Even,geom.directions,geom.displacements), | ||||
|     StencilEven(_cbgrid,geom.npoint,Even,geom.directions,geom.displacements), | ||||
|     StencilOdd(_cbgrid,geom.npoint,Odd,geom.directions,geom.displacements), | ||||
|     Stencil(&CoarseGrid,geom.npoint,Even,geom.directions,geom.displacements,0), | ||||
|     StencilEven(_cbgrid,geom.npoint,Even,geom.directions,geom.displacements,0), | ||||
|     StencilOdd(_cbgrid,geom.npoint,Odd,geom.directions,geom.displacements,0), | ||||
|     A(geom.npoint,&CoarseGrid), | ||||
|     Aeven(geom.npoint,_cbgrid), | ||||
|     Aodd(geom.npoint,_cbgrid), | ||||
| @@ -804,9 +804,9 @@ public: | ||||
|     _cbgrid(&CoarseRBGrid), | ||||
|     geom(CoarseGrid._ndimension), | ||||
|     hermitian(hermitian_), | ||||
|     Stencil(&CoarseGrid,geom.npoint,Even,geom.directions,geom.displacements), | ||||
|     StencilEven(&CoarseRBGrid,geom.npoint,Even,geom.directions,geom.displacements), | ||||
|     StencilOdd(&CoarseRBGrid,geom.npoint,Odd,geom.directions,geom.displacements), | ||||
|     Stencil(&CoarseGrid,geom.npoint,Even,geom.directions,geom.displacements,0), | ||||
|     StencilEven(&CoarseRBGrid,geom.npoint,Even,geom.directions,geom.displacements,0), | ||||
|     StencilOdd(&CoarseRBGrid,geom.npoint,Odd,geom.directions,geom.displacements,0), | ||||
|     A(geom.npoint,&CoarseGrid), | ||||
|     Aeven(geom.npoint,&CoarseRBGrid), | ||||
|     Aodd(geom.npoint,&CoarseRBGrid), | ||||
|   | ||||
| @@ -526,7 +526,6 @@ public: | ||||
|       (*this)(Linop,in[k],out[k]); | ||||
|     } | ||||
|   }; | ||||
|   virtual ~OperatorFunction(){}; | ||||
| }; | ||||
|  | ||||
| template<class Field> class LinearFunction { | ||||
| @@ -542,7 +541,6 @@ public: | ||||
|       (*this)(in[i], out[i]); | ||||
|     } | ||||
|   } | ||||
|   virtual ~LinearFunction(){}; | ||||
| }; | ||||
|  | ||||
| template<class Field> class IdentityLinearFunction : public LinearFunction<Field> { | ||||
|   | ||||
| @@ -258,12 +258,26 @@ public: | ||||
|     for(int n=2;n<order;n++){ | ||||
|  | ||||
|       Linop.HermOp(*Tn,y); | ||||
| #if 0 | ||||
|       auto y_v = y.View(); | ||||
|       auto Tn_v = Tn->View(); | ||||
|       auto Tnp_v = Tnp->View(); | ||||
|       auto Tnm_v = Tnm->View(); | ||||
|       constexpr int Nsimd = vector_type::Nsimd(); | ||||
|       accelerator_forNB(ss, in.Grid()->oSites(), Nsimd, { | ||||
| 	  coalescedWrite(y_v[ss],xscale*y_v(ss)+mscale*Tn_v(ss)); | ||||
| 	  coalescedWrite(Tnp_v[ss],2.0*y_v(ss)-Tnm_v(ss)); | ||||
|       }); | ||||
|       if ( Coeffs[n] != 0.0) { | ||||
| 	axpy(out,Coeffs[n],*Tnp,out); | ||||
|       } | ||||
| #else | ||||
|       axpby(y,xscale,mscale,y,(*Tn)); | ||||
|       axpby(*Tnp,2.0,-1.0,y,(*Tnm)); | ||||
|       if ( Coeffs[n] != 0.0) { | ||||
| 	axpy(out,Coeffs[n],*Tnp,out); | ||||
|       } | ||||
|  | ||||
| #endif | ||||
|       // Cycle pointers to avoid copies | ||||
|       Field *swizzle = Tnm; | ||||
|       Tnm    =Tn; | ||||
| @@ -278,6 +292,7 @@ public: | ||||
| template<class Field> | ||||
| class ChebyshevLanczos : public Chebyshev<Field> { | ||||
| private: | ||||
|  | ||||
|   std::vector<RealD> Coeffs; | ||||
|   int order; | ||||
|   RealD alpha; | ||||
|   | ||||
| @@ -58,7 +58,6 @@ public: | ||||
|  | ||||
|   void operator()(LinearOperatorBase<Field> &Linop, const Field &src, Field &psi) { | ||||
|  | ||||
|     GRID_TRACE("ConjugateGradient"); | ||||
|     psi.Checkerboard() = src.Checkerboard(); | ||||
|  | ||||
|     conformable(psi, src); | ||||
| @@ -118,13 +117,9 @@ public: | ||||
|     GridStopWatch MatrixTimer; | ||||
|     GridStopWatch SolverTimer; | ||||
|  | ||||
|     RealD usecs = -usecond(); | ||||
|     SolverTimer.Start(); | ||||
|     int k; | ||||
|     for (k = 1; k <= MaxIterations; k++) { | ||||
|  | ||||
|       GridStopWatch IterationTimer; | ||||
|       IterationTimer.Start(); | ||||
|       c = cp; | ||||
|  | ||||
|       MatrixTimer.Start(); | ||||
| @@ -157,41 +152,31 @@ public: | ||||
|       LinearCombTimer.Stop(); | ||||
|       LinalgTimer.Stop(); | ||||
|  | ||||
|       IterationTimer.Stop(); | ||||
|       if ( (k % 500) == 0 ) { | ||||
| 	std::cout << GridLogMessage << "ConjugateGradient: Iteration " << k | ||||
|                 << " residual " << sqrt(cp/ssq) << " target " << Tolerance << std::endl; | ||||
|       } else {  | ||||
|       std::cout << GridLogIterative << "ConjugateGradient: Iteration " << k | ||||
| 		  << " residual " << sqrt(cp/ssq) << " target " << Tolerance << " took " << IterationTimer.Elapsed() << std::endl; | ||||
|       } | ||||
|                 << " residual " << sqrt(cp/ssq) << " target " << Tolerance << std::endl; | ||||
|  | ||||
|       // Stopping condition | ||||
|       if (cp <= rsq) { | ||||
| 	usecs +=usecond(); | ||||
|         SolverTimer.Stop(); | ||||
|         Linop.HermOpAndNorm(psi, mmp, d, qq); | ||||
|         p = mmp - src; | ||||
| 	GridBase *grid = src.Grid(); | ||||
| 	RealD DwfFlops = (1452. )*grid->gSites()*4*k | ||||
|    	               + (8+4+8+4+4)*12*grid->gSites()*k; // CG linear algebra | ||||
|  | ||||
|         RealD srcnorm = std::sqrt(norm2(src)); | ||||
|         RealD resnorm = std::sqrt(norm2(p)); | ||||
|         RealD true_residual = resnorm / srcnorm; | ||||
|  | ||||
|         std::cout << GridLogMessage << "ConjugateGradient Converged on iteration " << k  | ||||
| 		  << "\tComputed residual " << std::sqrt(cp / ssq) | ||||
| 		  << "\tTrue residual " << true_residual | ||||
| 		  << "\tTarget " << Tolerance << std::endl; | ||||
|  | ||||
|         std::cout << GridLogMessage << "Time breakdown "<<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tElapsed    " << SolverTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tMatrix     " << MatrixTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tLinalg     " << LinalgTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tInner      " << InnerTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tAxpyNorm   " << AxpyNormTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tLinearComb " << LinearCombTimer.Elapsed() <<std::endl; | ||||
|  | ||||
| 	std::cout << GridLogDebug << "\tMobius flop rate " << DwfFlops/ usecs<< " Gflops " <<std::endl; | ||||
|         std::cout << GridLogIterative << "Time breakdown "<<std::endl; | ||||
| 	std::cout << GridLogIterative << "\tElapsed    " << SolverTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogIterative << "\tMatrix     " << MatrixTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogIterative << "\tLinalg     " << LinalgTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogIterative << "\tInner      " << InnerTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogIterative << "\tAxpyNorm   " << AxpyNormTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogIterative << "\tLinearComb " << LinearCombTimer.Elapsed() <<std::endl; | ||||
|  | ||||
|         if (ErrorOnNoConverge) assert(true_residual / Tolerance < 10000.0); | ||||
|  | ||||
|   | ||||
| @@ -82,6 +82,11 @@ NAMESPACE_BEGIN(Grid); | ||||
|     RealD stop = src_norm * Tolerance*Tolerance; | ||||
|  | ||||
|     GridBase* DoublePrecGrid = src_d_in.Grid(); | ||||
|  | ||||
|     //Generate precision change workspaces | ||||
|     precisionChangeWorkspace wk_dp_from_sp(DoublePrecGrid, SinglePrecGrid); | ||||
|     precisionChangeWorkspace wk_sp_from_dp(SinglePrecGrid, DoublePrecGrid); | ||||
|  | ||||
|     FieldD tmp_d(DoublePrecGrid); | ||||
|     tmp_d.Checkerboard() = cb; | ||||
|      | ||||
| @@ -109,9 +114,6 @@ NAMESPACE_BEGIN(Grid); | ||||
|      | ||||
|     Integer &outer_iter = TotalOuterIterations; //so it will be equal to the final iteration count | ||||
|        | ||||
|     precisionChangeWorkspace pc_wk_sp_to_dp(DoublePrecGrid, SinglePrecGrid); | ||||
|     precisionChangeWorkspace pc_wk_dp_to_sp(SinglePrecGrid, DoublePrecGrid); | ||||
|      | ||||
|     for(outer_iter = 0; outer_iter < MaxOuterIterations; outer_iter++){ | ||||
|       //Compute double precision rsd and also new RHS vector. | ||||
|       Linop_d.HermOp(sol_d, tmp_d); | ||||
| @@ -126,7 +128,7 @@ NAMESPACE_BEGIN(Grid); | ||||
|       while(norm * inner_tol * inner_tol < stop) inner_tol *= 2;  // inner_tol = sqrt(stop/norm) ?? | ||||
|  | ||||
|       PrecChangeTimer.Start(); | ||||
|       precisionChange(src_f, src_d, pc_wk_dp_to_sp); | ||||
|       precisionChange(src_f, src_d, wk_sp_from_dp); | ||||
|       PrecChangeTimer.Stop(); | ||||
|        | ||||
|       sol_f = Zero(); | ||||
| @@ -145,7 +147,7 @@ NAMESPACE_BEGIN(Grid); | ||||
|        | ||||
|       //Convert sol back to double and add to double prec solution | ||||
|       PrecChangeTimer.Start(); | ||||
|       precisionChange(tmp_d, sol_f, pc_wk_sp_to_dp); | ||||
|       precisionChange(tmp_d, sol_f, wk_dp_from_sp); | ||||
|       PrecChangeTimer.Stop(); | ||||
|        | ||||
|       axpy(sol_d, 1.0, tmp_d, sol_d); | ||||
|   | ||||
| @@ -1,213 +0,0 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|  | ||||
|     Source file: ./lib/algorithms/iterative/ConjugateGradientMixedPrecBatched.h | ||||
|  | ||||
|     Copyright (C) 2015 | ||||
|  | ||||
|     Author: Raoul Hodgson <raoul.hodgson@ed.ac.uk> | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License along | ||||
|     with this program; if not, write to the Free Software Foundation, Inc., | ||||
|     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
|     See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #ifndef GRID_CONJUGATE_GRADIENT_MIXED_PREC_BATCHED_H | ||||
| #define GRID_CONJUGATE_GRADIENT_MIXED_PREC_BATCHED_H | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| //Mixed precision restarted defect correction CG | ||||
| template<class FieldD,class FieldF,  | ||||
|   typename std::enable_if< getPrecision<FieldD>::value == 2, int>::type = 0, | ||||
|   typename std::enable_if< getPrecision<FieldF>::value == 1, int>::type = 0>  | ||||
| class MixedPrecisionConjugateGradientBatched : public LinearFunction<FieldD> { | ||||
| public: | ||||
|   using LinearFunction<FieldD>::operator(); | ||||
|   RealD   Tolerance; | ||||
|   RealD   InnerTolerance; //Initial tolerance for inner CG. Defaults to Tolerance but can be changed | ||||
|   Integer MaxInnerIterations; | ||||
|   Integer MaxOuterIterations; | ||||
|   Integer MaxPatchupIterations; | ||||
|   GridBase* SinglePrecGrid; //Grid for single-precision fields | ||||
|   RealD OuterLoopNormMult; //Stop the outer loop and move to a final double prec solve when the residual is OuterLoopNormMult * Tolerance | ||||
|   LinearOperatorBase<FieldF> &Linop_f; | ||||
|   LinearOperatorBase<FieldD> &Linop_d; | ||||
|  | ||||
|   //Option to speed up *inner single precision* solves using a LinearFunction that produces a guess | ||||
|   LinearFunction<FieldF> *guesser; | ||||
|   bool updateResidual; | ||||
|    | ||||
|   MixedPrecisionConjugateGradientBatched(RealD tol,  | ||||
|           Integer maxinnerit,  | ||||
|           Integer maxouterit,  | ||||
|           Integer maxpatchit, | ||||
|           GridBase* _sp_grid,  | ||||
|           LinearOperatorBase<FieldF> &_Linop_f,  | ||||
|           LinearOperatorBase<FieldD> &_Linop_d, | ||||
|           bool _updateResidual=true) : | ||||
|     Linop_f(_Linop_f), Linop_d(_Linop_d), | ||||
|     Tolerance(tol), InnerTolerance(tol), MaxInnerIterations(maxinnerit), MaxOuterIterations(maxouterit), MaxPatchupIterations(maxpatchit), SinglePrecGrid(_sp_grid), | ||||
|     OuterLoopNormMult(100.), guesser(NULL), updateResidual(_updateResidual) { }; | ||||
|  | ||||
|   void useGuesser(LinearFunction<FieldF> &g){ | ||||
|     guesser = &g; | ||||
|   } | ||||
|    | ||||
|   void operator() (const FieldD &src_d_in, FieldD &sol_d){ | ||||
|     std::vector<FieldD> srcs_d_in{src_d_in}; | ||||
|     std::vector<FieldD> sols_d{sol_d}; | ||||
|  | ||||
|     (*this)(srcs_d_in,sols_d); | ||||
|  | ||||
|     sol_d = sols_d[0]; | ||||
|   } | ||||
|  | ||||
|   void operator() (const std::vector<FieldD> &src_d_in, std::vector<FieldD> &sol_d){ | ||||
|     assert(src_d_in.size() == sol_d.size()); | ||||
|     int NBatch = src_d_in.size(); | ||||
|  | ||||
|     std::cout << GridLogMessage << "NBatch = " << NBatch << std::endl; | ||||
|  | ||||
|     Integer TotalOuterIterations = 0; //Number of restarts | ||||
|     std::vector<Integer> TotalInnerIterations(NBatch,0);     //Number of inner CG iterations | ||||
|     std::vector<Integer> TotalFinalStepIterations(NBatch,0); //Number of CG iterations in final patch-up step | ||||
|    | ||||
|     GridStopWatch TotalTimer; | ||||
|     TotalTimer.Start(); | ||||
|  | ||||
|     GridStopWatch InnerCGtimer; | ||||
|     GridStopWatch PrecChangeTimer; | ||||
|      | ||||
|     int cb = src_d_in[0].Checkerboard(); | ||||
|      | ||||
|     std::vector<RealD> src_norm; | ||||
|     std::vector<RealD> norm; | ||||
|     std::vector<RealD> stop; | ||||
|      | ||||
|     GridBase* DoublePrecGrid = src_d_in[0].Grid(); | ||||
|     FieldD tmp_d(DoublePrecGrid); | ||||
|     tmp_d.Checkerboard() = cb; | ||||
|      | ||||
|     FieldD tmp2_d(DoublePrecGrid); | ||||
|     tmp2_d.Checkerboard() = cb; | ||||
|  | ||||
|     std::vector<FieldD> src_d; | ||||
|     std::vector<FieldF> src_f; | ||||
|     std::vector<FieldF> sol_f; | ||||
|  | ||||
|     for (int i=0; i<NBatch; i++) { | ||||
|       sol_d[i].Checkerboard() = cb; | ||||
|  | ||||
|       src_norm.push_back(norm2(src_d_in[i])); | ||||
|       norm.push_back(0.); | ||||
|       stop.push_back(src_norm[i] * Tolerance*Tolerance); | ||||
|  | ||||
|       src_d.push_back(src_d_in[i]); //source for next inner iteration, computed from residual during operation | ||||
|  | ||||
|       src_f.push_back(SinglePrecGrid); | ||||
|       src_f[i].Checkerboard() = cb; | ||||
|  | ||||
|       sol_f.push_back(SinglePrecGrid); | ||||
|       sol_f[i].Checkerboard() = cb; | ||||
|     } | ||||
|      | ||||
|     RealD inner_tol = InnerTolerance; | ||||
|      | ||||
|     ConjugateGradient<FieldF> CG_f(inner_tol, MaxInnerIterations); | ||||
|     CG_f.ErrorOnNoConverge = false; | ||||
|      | ||||
|     Integer &outer_iter = TotalOuterIterations; //so it will be equal to the final iteration count | ||||
|        | ||||
|     for(outer_iter = 0; outer_iter < MaxOuterIterations; outer_iter++){ | ||||
|       std::cout << GridLogMessage << std::endl; | ||||
|       std::cout << GridLogMessage << "Outer iteration " << outer_iter << std::endl; | ||||
|        | ||||
|       bool allConverged = true; | ||||
|        | ||||
|       for (int i=0; i<NBatch; i++) { | ||||
|         //Compute double precision rsd and also new RHS vector. | ||||
|         Linop_d.HermOp(sol_d[i], tmp_d); | ||||
|         norm[i] = axpy_norm(src_d[i], -1., tmp_d, src_d_in[i]); //src_d is residual vector | ||||
|          | ||||
|         std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Outer iteration " << outer_iter <<" solve " << i << " residual "<< norm[i] << " target "<< stop[i] <<std::endl; | ||||
|  | ||||
|         PrecChangeTimer.Start(); | ||||
|         precisionChange(src_f[i], src_d[i]); | ||||
|         PrecChangeTimer.Stop(); | ||||
|          | ||||
|         sol_f[i] = Zero(); | ||||
|        | ||||
|         if(norm[i] > OuterLoopNormMult * stop[i]) { | ||||
|           allConverged = false; | ||||
|         } | ||||
|       } | ||||
|       if (allConverged) break; | ||||
|  | ||||
|       if (updateResidual) { | ||||
|         RealD normMax = *std::max_element(std::begin(norm), std::end(norm)); | ||||
|         RealD stopMax = *std::max_element(std::begin(stop), std::end(stop)); | ||||
|         while( normMax * inner_tol * inner_tol < stopMax) inner_tol *= 2;  // inner_tol = sqrt(stop/norm) ?? | ||||
|         CG_f.Tolerance = inner_tol; | ||||
|       } | ||||
|  | ||||
|       //Optionally improve inner solver guess (eg using known eigenvectors) | ||||
|       if(guesser != NULL) { | ||||
|         (*guesser)(src_f, sol_f); | ||||
|       } | ||||
|  | ||||
|       for (int i=0; i<NBatch; i++) { | ||||
|         //Inner CG | ||||
|         InnerCGtimer.Start(); | ||||
|         CG_f(Linop_f, src_f[i], sol_f[i]); | ||||
|         InnerCGtimer.Stop(); | ||||
|         TotalInnerIterations[i] += CG_f.IterationsToComplete; | ||||
|          | ||||
|         //Convert sol back to double and add to double prec solution | ||||
|         PrecChangeTimer.Start(); | ||||
|         precisionChange(tmp_d, sol_f[i]); | ||||
|         PrecChangeTimer.Stop(); | ||||
|          | ||||
|         axpy(sol_d[i], 1.0, tmp_d, sol_d[i]); | ||||
|       } | ||||
|  | ||||
|     } | ||||
|      | ||||
|     //Final trial CG | ||||
|     std::cout << GridLogMessage << std::endl; | ||||
|     std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Starting final patch-up double-precision solve"<<std::endl; | ||||
|      | ||||
|     for (int i=0; i<NBatch; i++) { | ||||
|       ConjugateGradient<FieldD> CG_d(Tolerance, MaxPatchupIterations); | ||||
|       CG_d(Linop_d, src_d_in[i], sol_d[i]); | ||||
|       TotalFinalStepIterations[i] += CG_d.IterationsToComplete; | ||||
|     } | ||||
|  | ||||
|     TotalTimer.Stop(); | ||||
|  | ||||
|     std::cout << GridLogMessage << std::endl; | ||||
|     for (int i=0; i<NBatch; i++) { | ||||
|       std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: solve " << i << " Inner CG iterations " << TotalInnerIterations[i] << " Restarts " << TotalOuterIterations << " Final CG iterations " << TotalFinalStepIterations[i] << std::endl; | ||||
|     } | ||||
|     std::cout << GridLogMessage << std::endl; | ||||
|     std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientBatched: Total time " << TotalTimer.Elapsed() << " Precision change " << PrecChangeTimer.Elapsed() << " Inner CG total " << InnerCGtimer.Elapsed() << std::endl; | ||||
|      | ||||
|   } | ||||
| }; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|  | ||||
| #endif | ||||
| @@ -44,7 +44,7 @@ public: | ||||
|  | ||||
|   using OperatorFunction<Field>::operator(); | ||||
|  | ||||
|   //  RealD   Tolerance; | ||||
|   RealD   Tolerance; | ||||
|   Integer MaxIterations; | ||||
|   Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion | ||||
|   std::vector<int> IterationsToCompleteShift;  // Iterations for this shift | ||||
| @@ -84,7 +84,6 @@ public: | ||||
|  | ||||
|   void operator() (LinearOperatorBase<Field> &Linop, const Field &src, std::vector<Field> &psi) | ||||
|   { | ||||
|     GRID_TRACE("ConjugateGradientMultiShift"); | ||||
|    | ||||
|     GridBase *grid = src.Grid(); | ||||
|    | ||||
| @@ -326,7 +325,7 @@ public: | ||||
|       std::cout << GridLogMessage << "Time Breakdown "<<std::endl; | ||||
|       std::cout << GridLogMessage << "\tElapsed    " << SolverTimer.Elapsed()     <<std::endl; | ||||
|       std::cout << GridLogMessage << "\tAXPY    " << AXPYTimer.Elapsed()     <<std::endl; | ||||
|       std::cout << GridLogMessage << "\tMatrix   " << MatrixTimer.Elapsed()     <<std::endl; | ||||
|       std::cout << GridLogMessage << "\tMarix    " << MatrixTimer.Elapsed()     <<std::endl; | ||||
|       std::cout << GridLogMessage << "\tShift    " << ShiftTimer.Elapsed()     <<std::endl; | ||||
|  | ||||
|       IterationsToComplete = k;	 | ||||
|   | ||||
| @@ -1,373 +0,0 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid  | ||||
|  | ||||
|     Source file: ./lib/algorithms/iterative/ConjugateGradientMultiShift.h | ||||
|  | ||||
|     Copyright (C) 2015 | ||||
|  | ||||
| Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk> | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Christopher Kelly <ckelly@bnl.gov> | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License along | ||||
|     with this program; if not, write to the Free Software Foundation, Inc., | ||||
|     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
|     See the full license in the file "LICENSE" in the top level distribution directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #pragma once | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| //CK 2020: A variant of the multi-shift conjugate gradient with the matrix multiplication in single precision.  | ||||
| //The residual is stored in single precision, but the search directions and solution are stored in double precision.  | ||||
| //Every update_freq iterations the residual is corrected in double precision.  | ||||
| //For safety the a final regular CG is applied to clean up if necessary | ||||
|  | ||||
| //PB Pure single, then double fixup | ||||
|  | ||||
| template<class FieldD, class FieldF, | ||||
| 	 typename std::enable_if< getPrecision<FieldD>::value == 2, int>::type = 0, | ||||
| 	 typename std::enable_if< getPrecision<FieldF>::value == 1, int>::type = 0>  | ||||
| class ConjugateGradientMultiShiftMixedPrecCleanup : public OperatorMultiFunction<FieldD>, | ||||
| 					     public OperatorFunction<FieldD> | ||||
| { | ||||
| public:                                                 | ||||
|  | ||||
|   using OperatorFunction<FieldD>::operator(); | ||||
|  | ||||
|   RealD   Tolerance; | ||||
|   Integer MaxIterationsMshift; | ||||
|   Integer MaxIterations; | ||||
|   Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion | ||||
|   std::vector<int> IterationsToCompleteShift;  // Iterations for this shift | ||||
|   int verbose; | ||||
|   MultiShiftFunction shifts; | ||||
|   std::vector<RealD> TrueResidualShift; | ||||
|  | ||||
|   int ReliableUpdateFreq; //number of iterations between reliable updates | ||||
|  | ||||
|   GridBase* SinglePrecGrid; //Grid for single-precision fields | ||||
|   LinearOperatorBase<FieldF> &Linop_f; //single precision | ||||
|  | ||||
|   ConjugateGradientMultiShiftMixedPrecCleanup(Integer maxit, const MultiShiftFunction &_shifts, | ||||
| 				       GridBase* _SinglePrecGrid, LinearOperatorBase<FieldF> &_Linop_f, | ||||
| 				       int _ReliableUpdateFreq) :  | ||||
|     MaxIterationsMshift(maxit),  shifts(_shifts), SinglePrecGrid(_SinglePrecGrid), Linop_f(_Linop_f), ReliableUpdateFreq(_ReliableUpdateFreq), | ||||
|     MaxIterations(20000) | ||||
|   {  | ||||
|     verbose=1; | ||||
|     IterationsToCompleteShift.resize(_shifts.order); | ||||
|     TrueResidualShift.resize(_shifts.order); | ||||
|   } | ||||
|  | ||||
|   void operator() (LinearOperatorBase<FieldD> &Linop, const FieldD &src, FieldD &psi) | ||||
|   { | ||||
|     GridBase *grid = src.Grid(); | ||||
|     int nshift = shifts.order; | ||||
|     std::vector<FieldD> results(nshift,grid); | ||||
|     (*this)(Linop,src,results,psi); | ||||
|   } | ||||
|   void operator() (LinearOperatorBase<FieldD> &Linop, const FieldD &src, std::vector<FieldD> &results, FieldD &psi) | ||||
|   { | ||||
|     int nshift = shifts.order; | ||||
|  | ||||
|     (*this)(Linop,src,results); | ||||
|    | ||||
|     psi = shifts.norm*src; | ||||
|     for(int i=0;i<nshift;i++){ | ||||
|       psi = psi + shifts.residues[i]*results[i]; | ||||
|     } | ||||
|  | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   void operator() (LinearOperatorBase<FieldD> &Linop_d, const FieldD &src_d, std::vector<FieldD> &psi_d) | ||||
|   {  | ||||
|     GRID_TRACE("ConjugateGradientMultiShiftMixedPrecCleanup"); | ||||
|     GridBase *DoublePrecGrid = src_d.Grid(); | ||||
|  | ||||
|     //////////////////////////////////////////////////////////////////////// | ||||
|     // Convenience references to the info stored in "MultiShiftFunction" | ||||
|     //////////////////////////////////////////////////////////////////////// | ||||
|     int nshift = shifts.order; | ||||
|  | ||||
|     std::vector<RealD> &mass(shifts.poles); // Make references to array in "shifts" | ||||
|     std::vector<RealD> &mresidual(shifts.tolerances); | ||||
|     std::vector<RealD> alpha(nshift,1.0); | ||||
|  | ||||
|     //Double precision search directions | ||||
|     FieldD p_d(DoublePrecGrid); | ||||
|     std::vector<FieldF> ps_f (nshift, SinglePrecGrid);// Search directions (single precision) | ||||
|     std::vector<FieldF> psi_f(nshift, SinglePrecGrid);// solutions (single precision) | ||||
|  | ||||
|     FieldD tmp_d(DoublePrecGrid); | ||||
|     FieldD r_d(DoublePrecGrid); | ||||
|     FieldF r_f(SinglePrecGrid); | ||||
|     FieldD mmp_d(DoublePrecGrid); | ||||
|  | ||||
|     assert(psi_d.size()==nshift); | ||||
|     assert(mass.size()==nshift); | ||||
|     assert(mresidual.size()==nshift); | ||||
|    | ||||
|     // dynamic sized arrays on stack; 2d is a pain with vector | ||||
|     RealD  bs[nshift]; | ||||
|     RealD  rsq[nshift]; | ||||
|     RealD  rsqf[nshift]; | ||||
|     RealD  z[nshift][2]; | ||||
|     int     converged[nshift]; | ||||
|    | ||||
|     const int       primary =0; | ||||
|    | ||||
|     //Primary shift fields CG iteration | ||||
|     RealD a,b,c,d; | ||||
|     RealD cp,bp,qq; //prev | ||||
|    | ||||
|     // Matrix mult fields | ||||
|     FieldF p_f(SinglePrecGrid); | ||||
|     FieldF mmp_f(SinglePrecGrid); | ||||
|  | ||||
|     // Check lightest mass | ||||
|     for(int s=0;s<nshift;s++){ | ||||
|       assert( mass[s]>= mass[primary] ); | ||||
|       converged[s]=0; | ||||
|     } | ||||
|    | ||||
|     // Wire guess to zero | ||||
|     // Residuals "r" are src | ||||
|     // First search direction "p" is also src | ||||
|     cp = norm2(src_d); | ||||
|  | ||||
|     // Handle trivial case of zero src. | ||||
|     if( cp == 0. ){ | ||||
|       for(int s=0;s<nshift;s++){ | ||||
| 	psi_d[s] = Zero(); | ||||
| 	psi_f[s] = Zero(); | ||||
| 	IterationsToCompleteShift[s] = 1; | ||||
| 	TrueResidualShift[s] = 0.; | ||||
|       } | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     for(int s=0;s<nshift;s++){ | ||||
|       rsq[s] = cp * mresidual[s] * mresidual[s]; | ||||
|       rsqf[s] =rsq[s]; | ||||
|       std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrecCleanup: shift "<< s <<" target resid "<<rsq[s]<<std::endl; | ||||
|       //      ps_d[s] = src_d; | ||||
|       precisionChangeFast(ps_f[s],src_d); | ||||
|     } | ||||
|     // r and p for primary | ||||
|     p_d = src_d; //primary copy --- make this a reference to ps_d to save axpys | ||||
|     r_d = p_d; | ||||
|      | ||||
|     //MdagM+m[0] | ||||
|     precisionChangeFast(p_f,p_d); | ||||
|     Linop_f.HermOpAndNorm(p_f,mmp_f,d,qq); // mmp = MdagM p        d=real(dot(p, mmp)),  qq=norm2(mmp) | ||||
|     precisionChangeFast(tmp_d,mmp_f); | ||||
|     Linop_d.HermOpAndNorm(p_d,mmp_d,d,qq); // mmp = MdagM p        d=real(dot(p, mmp)),  qq=norm2(mmp) | ||||
|     tmp_d = tmp_d - mmp_d; | ||||
|     std::cout << " Testing operators match "<<norm2(mmp_d)<<" f "<<norm2(mmp_f)<<" diff "<< norm2(tmp_d)<<std::endl; | ||||
|     //    assert(norm2(tmp_d)< 1.0e-4); | ||||
|  | ||||
|     axpy(mmp_d,mass[0],p_d,mmp_d); | ||||
|     RealD rn = norm2(p_d); | ||||
|     d += rn*mass[0]; | ||||
|  | ||||
|     b = -cp /d; | ||||
|    | ||||
|     // Set up the various shift variables | ||||
|     int       iz=0; | ||||
|     z[0][1-iz] = 1.0; | ||||
|     z[0][iz]   = 1.0; | ||||
|     bs[0]      = b; | ||||
|     for(int s=1;s<nshift;s++){ | ||||
|       z[s][1-iz] = 1.0; | ||||
|       z[s][iz]   = 1.0/( 1.0 - b*(mass[s]-mass[0])); | ||||
|       bs[s]      = b*z[s][iz];  | ||||
|     } | ||||
|    | ||||
|     // r += b[0] A.p[0] | ||||
|     // c= norm(r) | ||||
|     c=axpy_norm(r_d,b,mmp_d,r_d); | ||||
|    | ||||
|     for(int s=0;s<nshift;s++) { | ||||
|       axpby(psi_d[s],0.,-bs[s]*alpha[s],src_d,src_d); | ||||
|       precisionChangeFast(psi_f[s],psi_d[s]); | ||||
|     } | ||||
|    | ||||
|     /////////////////////////////////////// | ||||
|     // Timers | ||||
|     /////////////////////////////////////// | ||||
|     GridStopWatch AXPYTimer, ShiftTimer, QRTimer, MatrixTimer, SolverTimer, PrecChangeTimer, CleanupTimer; | ||||
|  | ||||
|     SolverTimer.Start(); | ||||
|    | ||||
|     // Iteration loop | ||||
|     int k; | ||||
|    | ||||
|     for (k=1;k<=MaxIterationsMshift;k++){     | ||||
|  | ||||
|       a = c /cp; | ||||
|       AXPYTimer.Start(); | ||||
|       axpy(p_d,a,p_d,r_d);  | ||||
|       AXPYTimer.Stop(); | ||||
|  | ||||
|       PrecChangeTimer.Start(); | ||||
|       precisionChangeFast(r_f, r_d); | ||||
|       PrecChangeTimer.Stop(); | ||||
|  | ||||
|       AXPYTimer.Start(); | ||||
|       for(int s=0;s<nshift;s++){ | ||||
| 	if ( ! converged[s] ) {  | ||||
| 	  if (s==0){ | ||||
| 	    axpy(ps_f[s],a,ps_f[s],r_f); | ||||
| 	  } else{ | ||||
| 	    RealD as =a *z[s][iz]*bs[s] /(z[s][1-iz]*b); | ||||
| 	    axpby(ps_f[s],z[s][iz],as,r_f,ps_f[s]); | ||||
| 	  } | ||||
| 	} | ||||
|       } | ||||
|       AXPYTimer.Stop(); | ||||
|  | ||||
|       cp=c; | ||||
|       PrecChangeTimer.Start(); | ||||
|       precisionChangeFast(p_f, p_d); //get back single prec search direction for linop | ||||
|       PrecChangeTimer.Stop(); | ||||
|       MatrixTimer.Start();   | ||||
|       Linop_f.HermOp(p_f,mmp_f); | ||||
|       MatrixTimer.Stop();   | ||||
|       PrecChangeTimer.Start(); | ||||
|       precisionChangeFast(mmp_d, mmp_f); // From Float to Double | ||||
|       PrecChangeTimer.Stop(); | ||||
|  | ||||
|       d=real(innerProduct(p_d,mmp_d));     | ||||
|       axpy(mmp_d,mass[0],p_d,mmp_d); | ||||
|       RealD rn = norm2(p_d); | ||||
|       d += rn*mass[0]; | ||||
|      | ||||
|       bp=b; | ||||
|       b=-cp/d; | ||||
|  | ||||
|       // Toggle the recurrence history | ||||
|       bs[0] = b; | ||||
|       iz = 1-iz; | ||||
|       ShiftTimer.Start(); | ||||
|       for(int s=1;s<nshift;s++){ | ||||
| 	if((!converged[s])){ | ||||
| 	  RealD z0 = z[s][1-iz]; | ||||
| 	  RealD z1 = z[s][iz]; | ||||
| 	  z[s][iz] = z0*z1*bp | ||||
| 	    / (b*a*(z1-z0) + z1*bp*(1- (mass[s]-mass[0])*b));  | ||||
| 	  bs[s] = b*z[s][iz]/z0; // NB sign  rel to Mike | ||||
| 	} | ||||
|       } | ||||
|       ShiftTimer.Stop(); | ||||
|  | ||||
|       //Update single precision solutions | ||||
|       AXPYTimer.Start(); | ||||
|       for(int s=0;s<nshift;s++){ | ||||
| 	int ss = s; | ||||
| 	if( (!converged[s]) ) {  | ||||
| 	  axpy(psi_f[ss],-bs[s]*alpha[s],ps_f[s],psi_f[ss]); | ||||
| 	} | ||||
|       } | ||||
|       c = axpy_norm(r_d,b,mmp_d,r_d); | ||||
|       AXPYTimer.Stop(); | ||||
|      | ||||
|       // Convergence checks | ||||
|       int all_converged = 1; | ||||
|       for(int s=0;s<nshift;s++){ | ||||
|        | ||||
| 	if ( (!converged[s]) ){ | ||||
| 	  IterationsToCompleteShift[s] = k; | ||||
| 	 | ||||
| 	  RealD css  = c * z[s][iz]* z[s][iz]; | ||||
| 	 | ||||
| 	  if(css<rsqf[s]){ | ||||
| 	    if ( ! converged[s] ) | ||||
| 	      std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrecCleanup k="<<k<<" Shift "<<s<<" has converged"<<std::endl; | ||||
| 	    converged[s]=1; | ||||
| 	  } else { | ||||
| 	    all_converged=0; | ||||
| 	  } | ||||
|  | ||||
| 	} | ||||
|       } | ||||
|  | ||||
|       if ( all_converged || k == MaxIterationsMshift-1){ | ||||
|  | ||||
| 	SolverTimer.Stop(); | ||||
|  | ||||
| 	for(int s=0;s<nshift;s++){ | ||||
| 	  precisionChangeFast(psi_d[s],psi_f[s]); | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	if ( all_converged ){ | ||||
| 	  std::cout<<GridLogMessage<< "ConjugateGradientMultiShiftMixedPrecCleanup: All shifts have converged iteration "<<k<<std::endl; | ||||
| 	  std::cout<<GridLogMessage<< "ConjugateGradientMultiShiftMixedPrecCleanup: Checking solutions"<<std::endl; | ||||
| 	} else { | ||||
| 	  std::cout<<GridLogMessage<< "ConjugateGradientMultiShiftMixedPrecCleanup: Not all shifts have converged iteration "<<k<<std::endl; | ||||
| 	} | ||||
| 	 | ||||
| 	// Check answers  | ||||
| 	for(int s=0; s < nshift; s++) {  | ||||
| 	  Linop_d.HermOpAndNorm(psi_d[s],mmp_d,d,qq); | ||||
| 	  axpy(tmp_d,mass[s],psi_d[s],mmp_d); | ||||
| 	  axpy(r_d,-alpha[s],src_d,tmp_d); | ||||
| 	  RealD rn = norm2(r_d); | ||||
| 	  RealD cn = norm2(src_d); | ||||
| 	  TrueResidualShift[s] = std::sqrt(rn/cn); | ||||
| 	  std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrecCleanup: shift["<<s<<"] true residual "<< TrueResidualShift[s] << " target " << mresidual[s] << std::endl; | ||||
|  | ||||
| 	  //If we have not reached the desired tolerance, do a (mixed precision) CG cleanup | ||||
| 	  if(rn >= rsq[s]){ | ||||
| 	    CleanupTimer.Start(); | ||||
| 	    std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrecCleanup: performing cleanup step for shift " << s << std::endl; | ||||
|  | ||||
| 	    //Setup linear operators for final cleanup | ||||
| 	    ConjugateGradientMultiShiftMixedPrecSupport::ShiftedLinop<FieldD> Linop_shift_d(Linop_d, mass[s]); | ||||
| 	    ConjugateGradientMultiShiftMixedPrecSupport::ShiftedLinop<FieldF> Linop_shift_f(Linop_f, mass[s]); | ||||
| 					        | ||||
| 	    MixedPrecisionConjugateGradient<FieldD,FieldF> cg(mresidual[s], MaxIterations, MaxIterations, SinglePrecGrid, Linop_shift_f, Linop_shift_d);  | ||||
| 	    cg(src_d, psi_d[s]); | ||||
| 	     | ||||
| 	    TrueResidualShift[s] = cg.TrueResidual; | ||||
| 	    CleanupTimer.Stop(); | ||||
| 	  } | ||||
| 	} | ||||
|  | ||||
| 	std::cout << GridLogMessage << "ConjugateGradientMultiShiftMixedPrecCleanup: Time Breakdown for body"<<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tSolver    " << SolverTimer.Elapsed()     <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\t\tAXPY    " << AXPYTimer.Elapsed()     <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\t\tMatrix    " << MatrixTimer.Elapsed()     <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\t\tShift    " << ShiftTimer.Elapsed()     <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\t\tPrecision Change " << PrecChangeTimer.Elapsed()     <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tFinal Cleanup " << CleanupTimer.Elapsed()     <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tSolver+Cleanup " << SolverTimer.Elapsed() + CleanupTimer.Elapsed() << std::endl; | ||||
|  | ||||
| 	IterationsToComplete = k;	 | ||||
|  | ||||
| 	return; | ||||
|       } | ||||
|     | ||||
|     } | ||||
|     std::cout<<GridLogMessage<<"CG multi shift did not converge"<<std::endl; | ||||
|     assert(0); | ||||
|   } | ||||
|  | ||||
| }; | ||||
| NAMESPACE_END(Grid); | ||||
|  | ||||
| @@ -81,7 +81,6 @@ public: | ||||
|   using OperatorFunction<FieldD>::operator(); | ||||
|  | ||||
|   RealD   Tolerance; | ||||
|   Integer MaxIterationsMshift; | ||||
|   Integer MaxIterations; | ||||
|   Integer IterationsToComplete; //Number of iterations the CG took to finish. Filled in upon completion | ||||
|   std::vector<int> IterationsToCompleteShift;  // Iterations for this shift | ||||
| @@ -96,9 +95,9 @@ public: | ||||
|  | ||||
|   ConjugateGradientMultiShiftMixedPrec(Integer maxit, const MultiShiftFunction &_shifts, | ||||
| 				       GridBase* _SinglePrecGrid, LinearOperatorBase<FieldF> &_Linop_f, | ||||
| 				       int _ReliableUpdateFreq) :  | ||||
|     MaxIterationsMshift(maxit),  shifts(_shifts), SinglePrecGrid(_SinglePrecGrid), Linop_f(_Linop_f), ReliableUpdateFreq(_ReliableUpdateFreq), | ||||
|     MaxIterations(20000) | ||||
| 				       int _ReliableUpdateFreq | ||||
| 				       ) :  | ||||
|     MaxIterations(maxit),  shifts(_shifts), SinglePrecGrid(_SinglePrecGrid), Linop_f(_Linop_f), ReliableUpdateFreq(_ReliableUpdateFreq) | ||||
|   {  | ||||
|     verbose=1; | ||||
|     IterationsToCompleteShift.resize(_shifts.order); | ||||
| @@ -128,11 +127,9 @@ public: | ||||
|  | ||||
|   void operator() (LinearOperatorBase<FieldD> &Linop_d, const FieldD &src_d, std::vector<FieldD> &psi_d) | ||||
|   {  | ||||
|     GRID_TRACE("ConjugateGradientMultiShiftMixedPrec"); | ||||
|     GridBase *DoublePrecGrid = src_d.Grid(); | ||||
|  | ||||
|     precisionChangeWorkspace pc_wk_s_to_d(DoublePrecGrid,SinglePrecGrid); | ||||
|     precisionChangeWorkspace pc_wk_d_to_s(SinglePrecGrid,DoublePrecGrid); | ||||
|     precisionChangeWorkspace wk_f_from_d(SinglePrecGrid, DoublePrecGrid); | ||||
|     precisionChangeWorkspace wk_d_from_f(DoublePrecGrid, SinglePrecGrid); | ||||
|  | ||||
|     //////////////////////////////////////////////////////////////////////// | ||||
|     // Convenience references to the info stored in "MultiShiftFunction" | ||||
| @@ -158,7 +155,6 @@ public: | ||||
|     // dynamic sized arrays on stack; 2d is a pain with vector | ||||
|     RealD  bs[nshift]; | ||||
|     RealD  rsq[nshift]; | ||||
|     RealD  rsqf[nshift]; | ||||
|     RealD  z[nshift][2]; | ||||
|     int     converged[nshift]; | ||||
|    | ||||
| @@ -169,8 +165,12 @@ public: | ||||
|     RealD cp,bp,qq; //prev | ||||
|    | ||||
|     // Matrix mult fields | ||||
|     FieldF r_f(SinglePrecGrid); | ||||
|     FieldF p_f(SinglePrecGrid); | ||||
|     FieldF tmp_f(SinglePrecGrid); | ||||
|     FieldF mmp_f(SinglePrecGrid); | ||||
|     FieldF src_f(SinglePrecGrid); | ||||
|     precisionChange(src_f, src_d, wk_f_from_d); | ||||
|  | ||||
|     // Check lightest mass | ||||
|     for(int s=0;s<nshift;s++){ | ||||
| @@ -195,26 +195,18 @@ public: | ||||
|  | ||||
|     for(int s=0;s<nshift;s++){ | ||||
|       rsq[s] = cp * mresidual[s] * mresidual[s]; | ||||
|       rsqf[s] =rsq[s]; | ||||
|       std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec: shift "<< s <<" target resid "<<rsq[s]<<std::endl; | ||||
|       ps_d[s] = src_d; | ||||
|     } | ||||
|     // r and p for primary | ||||
|     r_f=src_f; //residual maintained in single | ||||
|     p_f=src_f; | ||||
|     p_d = src_d; //primary copy --- make this a reference to ps_d to save axpys | ||||
|     r_d = p_d; | ||||
|    | ||||
|     //MdagM+m[0] | ||||
|     precisionChange(p_f, p_d, pc_wk_d_to_s); | ||||
|  | ||||
|     Linop_f.HermOpAndNorm(p_f,mmp_f,d,qq); // mmp = MdagM p        d=real(dot(p, mmp)),  qq=norm2(mmp) | ||||
|     precisionChange(tmp_d, mmp_f, pc_wk_s_to_d); | ||||
|     Linop_d.HermOpAndNorm(p_d,mmp_d,d,qq); // mmp = MdagM p        d=real(dot(p, mmp)),  qq=norm2(mmp) | ||||
|     tmp_d = tmp_d - mmp_d; | ||||
|     std::cout << " Testing operators match "<<norm2(mmp_d)<<" f "<<norm2(mmp_f)<<" diff "<< norm2(tmp_d)<<std::endl; | ||||
|     //    assert(norm2(tmp_d)< 1.0e-4); | ||||
|  | ||||
|     axpy(mmp_d,mass[0],p_d,mmp_d); | ||||
|     RealD rn = norm2(p_d); | ||||
|     axpy(mmp_f,mass[0],p_f,mmp_f); | ||||
|     RealD rn = norm2(p_f); | ||||
|     d += rn*mass[0]; | ||||
|  | ||||
|     b = -cp /d; | ||||
| @@ -232,7 +224,7 @@ public: | ||||
|    | ||||
|     // r += b[0] A.p[0] | ||||
|     // c= norm(r) | ||||
|     c=axpy_norm(r_d,b,mmp_d,r_d); | ||||
|     c=axpy_norm(r_f,b,mmp_f,r_f); | ||||
|    | ||||
|     for(int s=0;s<nshift;s++) { | ||||
|       axpby(psi_d[s],0.,-bs[s]*alpha[s],src_d,src_d); | ||||
| @@ -248,9 +240,14 @@ public: | ||||
|     // Iteration loop | ||||
|     int k; | ||||
|    | ||||
|     for (k=1;k<=MaxIterationsMshift;k++){     | ||||
|  | ||||
|     for (k=1;k<=MaxIterations;k++){     | ||||
|       a = c /cp; | ||||
|  | ||||
|       //Update double precision search direction by residual | ||||
|       PrecChangeTimer.Start(); | ||||
|       precisionChange(r_d, r_f, wk_d_from_f); | ||||
|       PrecChangeTimer.Stop(); | ||||
|  | ||||
|       AXPYTimer.Start(); | ||||
|       axpy(p_d,a,p_d,r_d);  | ||||
|  | ||||
| @@ -267,23 +264,19 @@ public: | ||||
|       AXPYTimer.Stop(); | ||||
|  | ||||
|       PrecChangeTimer.Start(); | ||||
|       precisionChange(p_f, p_d, pc_wk_d_to_s); //get back single prec search direction for linop | ||||
|       precisionChange(p_f, p_d, wk_f_from_d); //get back single prec search direction for linop | ||||
|       PrecChangeTimer.Stop(); | ||||
|  | ||||
|       cp=c; | ||||
|       MatrixTimer.Start();   | ||||
|       Linop_f.HermOp(p_f,mmp_f);  | ||||
|       d=real(innerProduct(p_f,mmp_f));     | ||||
|       MatrixTimer.Stop();   | ||||
|  | ||||
|       PrecChangeTimer.Start(); | ||||
|       precisionChange(mmp_d, mmp_f, pc_wk_s_to_d); // From Float to Double | ||||
|       PrecChangeTimer.Stop(); | ||||
|  | ||||
|       AXPYTimer.Start(); | ||||
|       d=real(innerProduct(p_d,mmp_d));     | ||||
|       axpy(mmp_d,mass[0],p_d,mmp_d); | ||||
|       axpy(mmp_f,mass[0],p_f,mmp_f); | ||||
|       AXPYTimer.Stop(); | ||||
|       RealD rn = norm2(p_d); | ||||
|       RealD rn = norm2(p_f); | ||||
|       d += rn*mass[0]; | ||||
|      | ||||
|       bp=b; | ||||
| @@ -314,12 +307,12 @@ public: | ||||
|       } | ||||
|  | ||||
|       //Perform reliable update if necessary; otherwise update residual from single-prec mmp | ||||
|       c = axpy_norm(r_d,b,mmp_d,r_d); | ||||
|  | ||||
|       RealD c_f = axpy_norm(r_f,b,mmp_f,r_f); | ||||
|       AXPYTimer.Stop(); | ||||
|  | ||||
|       c = c_f; | ||||
|  | ||||
|       if(k % ReliableUpdateFreq == 0){ | ||||
| 	RealD c_old = c; | ||||
| 	//Replace r with true residual | ||||
| 	MatrixTimer.Start();   | ||||
| 	Linop_d.HermOp(psi_d[0],mmp_d);  | ||||
| @@ -328,10 +321,15 @@ public: | ||||
| 	AXPYTimer.Start(); | ||||
| 	axpy(mmp_d,mass[0],psi_d[0],mmp_d); | ||||
|  | ||||
| 	c = axpy_norm(r_d, -1.0, mmp_d, src_d); | ||||
| 	RealD c_d = axpy_norm(r_d, -1.0, mmp_d, src_d); | ||||
| 	AXPYTimer.Stop(); | ||||
|  | ||||
| 	std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec k="<<k<< ", replaced |r|^2 = "<<c_old <<" with |r|^2 = "<<c<<std::endl; | ||||
| 	std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec k="<<k<< ", replaced |r|^2 = "<<c_f <<" with |r|^2 = "<<c_d<<std::endl; | ||||
| 	 | ||||
| 	PrecChangeTimer.Start(); | ||||
| 	precisionChange(r_f, r_d, wk_f_from_d); | ||||
| 	PrecChangeTimer.Stop(); | ||||
| 	c = c_d; | ||||
|       } | ||||
|      | ||||
|       // Convergence checks | ||||
| @@ -343,7 +341,7 @@ public: | ||||
| 	 | ||||
| 	  RealD css  = c * z[s][iz]* z[s][iz]; | ||||
| 	 | ||||
| 	  if(css<rsqf[s]){ | ||||
| 	  if(css<rsq[s]){ | ||||
| 	    if ( ! converged[s] ) | ||||
| 	      std::cout<<GridLogMessage<<"ConjugateGradientMultiShiftMixedPrec k="<<k<<" Shift "<<s<<" has converged"<<std::endl; | ||||
| 	    converged[s]=1; | ||||
| @@ -354,16 +352,11 @@ public: | ||||
| 	} | ||||
|       } | ||||
|  | ||||
|       if ( all_converged || k == MaxIterationsMshift-1){ | ||||
|       if ( all_converged ){ | ||||
|  | ||||
| 	SolverTimer.Stop(); | ||||
|  | ||||
| 	if ( all_converged ){ | ||||
| 	std::cout<<GridLogMessage<< "ConjugateGradientMultiShiftMixedPrec: All shifts have converged iteration "<<k<<std::endl; | ||||
| 	std::cout<<GridLogMessage<< "ConjugateGradientMultiShiftMixedPrec: Checking solutions"<<std::endl; | ||||
| 	} else { | ||||
| 	  std::cout<<GridLogMessage<< "ConjugateGradientMultiShiftMixedPrec: Not all shifts have converged iteration "<<k<<std::endl; | ||||
| 	} | ||||
|        | ||||
| 	// Check answers  | ||||
| 	for(int s=0; s < nshift; s++) {  | ||||
| @@ -406,9 +399,11 @@ public: | ||||
| 	return; | ||||
|       } | ||||
|  | ||||
|     | ||||
|     } | ||||
|     // ugly hack | ||||
|     std::cout<<GridLogMessage<<"CG multi shift did not converge"<<std::endl; | ||||
|     assert(0); | ||||
|     //  assert(0); | ||||
|   } | ||||
|  | ||||
| }; | ||||
|   | ||||
| @@ -48,7 +48,7 @@ public: | ||||
|   LinearOperatorBase<FieldF> &Linop_f; | ||||
|   LinearOperatorBase<FieldD> &Linop_d; | ||||
|   GridBase* SinglePrecGrid; | ||||
|   RealD Delta; //reliable update parameter. A reliable update is performed when the residual drops by a factor of Delta relative to its value at the last update | ||||
|   RealD Delta; //reliable update parameter | ||||
|  | ||||
|   //Optional ability to switch to a different linear operator once the tolerance reaches a certain point. Useful for single/half -> single/single | ||||
|   LinearOperatorBase<FieldF> *Linop_fallback; | ||||
| @@ -65,9 +65,7 @@ public: | ||||
|       ErrorOnNoConverge(err_on_no_conv), | ||||
|       DoFinalCleanup(true), | ||||
|       Linop_fallback(NULL) | ||||
|   { | ||||
|     assert(Delta > 0. && Delta < 1. && "Expect  0 < Delta < 1"); | ||||
|   }; | ||||
|   {}; | ||||
|  | ||||
|   void setFallbackLinop(LinearOperatorBase<FieldF> &_Linop_fallback, const RealD _fallback_transition_tol){ | ||||
|     Linop_fallback = &_Linop_fallback; | ||||
| @@ -75,7 +73,6 @@ public: | ||||
|   } | ||||
|      | ||||
|   void operator()(const FieldD &src, FieldD &psi) { | ||||
|     GRID_TRACE("ConjugateGradientReliableUpdate"); | ||||
|     LinearOperatorBase<FieldF> *Linop_f_use = &Linop_f; | ||||
|     bool using_fallback = false; | ||||
|        | ||||
| @@ -118,12 +115,9 @@ public: | ||||
|     } | ||||
|  | ||||
|     //Single prec initialization | ||||
|     precisionChangeWorkspace pc_wk_sp_to_dp(src.Grid(), SinglePrecGrid); | ||||
|     precisionChangeWorkspace pc_wk_dp_to_sp(SinglePrecGrid, src.Grid()); | ||||
|      | ||||
|     FieldF r_f(SinglePrecGrid); | ||||
|     r_f.Checkerboard() = r.Checkerboard(); | ||||
|     precisionChange(r_f, r, pc_wk_dp_to_sp); | ||||
|     precisionChange(r_f, r); | ||||
|  | ||||
|     FieldF psi_f(r_f); | ||||
|     psi_f = Zero(); | ||||
| @@ -139,7 +133,6 @@ public: | ||||
|     GridStopWatch LinalgTimer; | ||||
|     GridStopWatch MatrixTimer; | ||||
|     GridStopWatch SolverTimer; | ||||
|     GridStopWatch PrecChangeTimer; | ||||
|  | ||||
|     SolverTimer.Start(); | ||||
|     int k = 0; | ||||
| @@ -179,9 +172,7 @@ public: | ||||
|       // Stopping condition | ||||
|       if (cp <= rsq) { | ||||
| 	//Although not written in the paper, I assume that I have to add on the final solution | ||||
| 	PrecChangeTimer.Start(); | ||||
| 	precisionChange(mmp, psi_f, pc_wk_sp_to_dp); | ||||
| 	PrecChangeTimer.Stop(); | ||||
| 	precisionChange(mmp, psi_f); | ||||
| 	psi = psi + mmp; | ||||
| 	 | ||||
| 	 | ||||
| @@ -202,9 +193,6 @@ public: | ||||
| 	std::cout << GridLogMessage << "\tElapsed    " << SolverTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tMatrix     " << MatrixTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tLinalg     " << LinalgTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tPrecChange " << PrecChangeTimer.Elapsed() <<std::endl; | ||||
| 	std::cout << GridLogMessage << "\tPrecChange avg time " << PrecChangeTimer.Elapsed()/(2*l+1) <<std::endl; | ||||
|  | ||||
|  | ||||
| 	IterationsToComplete = k;	 | ||||
| 	ReliableUpdatesPerformed = l; | ||||
| @@ -225,21 +213,14 @@ public: | ||||
|       else if(cp < Delta * MaxResidSinceLastRelUp) { //reliable update | ||||
| 	std::cout << GridLogMessage << "ConjugateGradientReliableUpdate " | ||||
| 		  << cp << "(residual) < " << Delta << "(Delta) * " << MaxResidSinceLastRelUp << "(MaxResidSinceLastRelUp) on iteration " << k << " : performing reliable update\n"; | ||||
| 	PrecChangeTimer.Start(); | ||||
| 	precisionChange(mmp, psi_f, pc_wk_sp_to_dp); | ||||
| 	PrecChangeTimer.Stop(); | ||||
| 	precisionChange(mmp, psi_f); | ||||
| 	psi = psi + mmp; | ||||
|  | ||||
| 	MatrixTimer.Start(); | ||||
| 	Linop_d.HermOpAndNorm(psi, mmp, d, qq); | ||||
| 	MatrixTimer.Stop(); | ||||
| 	 | ||||
| 	r = src - mmp; | ||||
|  | ||||
| 	psi_f = Zero(); | ||||
| 	PrecChangeTimer.Start(); | ||||
| 	precisionChange(r_f, r, pc_wk_dp_to_sp); | ||||
| 	PrecChangeTimer.Stop(); | ||||
| 	precisionChange(r_f, r); | ||||
| 	cp = norm2(r); | ||||
| 	MaxResidSinceLastRelUp = cp; | ||||
|  | ||||
|   | ||||
| @@ -113,42 +113,6 @@ public: | ||||
|     blockPromote(guess_coarse,guess,subspace); | ||||
|     guess.Checkerboard() = src.Checkerboard(); | ||||
|   }; | ||||
|  | ||||
|   void operator()(const std::vector<FineField> &src,std::vector<FineField> &guess) { | ||||
|     int Nevec = (int)evec_coarse.size(); | ||||
|     int Nsrc = (int)src.size(); | ||||
|     // make temp variables | ||||
|     std::vector<CoarseField> src_coarse(Nsrc,evec_coarse[0].Grid()); | ||||
|     std::vector<CoarseField> guess_coarse(Nsrc,evec_coarse[0].Grid());     | ||||
|     //Preporcessing | ||||
|     std::cout << GridLogMessage << "Start BlockProject for loop" << std::endl; | ||||
|     for (int j=0;j<Nsrc;j++) | ||||
|     { | ||||
|     guess_coarse[j] = Zero(); | ||||
|     std::cout << GridLogMessage << "BlockProject iter: " << j << std::endl; | ||||
|     blockProject(src_coarse[j],src[j],subspace); | ||||
|     } | ||||
|     //deflation set up for eigen vector batchsize 1 and source batch size equal number of sources | ||||
|     std::cout << GridLogMessage << "Start ProjectAccum for loop" << std::endl; | ||||
|     for (int i=0;i<Nevec;i++) | ||||
|     { | ||||
|       std::cout << GridLogMessage << "ProjectAccum Nvec: " << i << std::endl; | ||||
|       const CoarseField & tmp = evec_coarse[i]; | ||||
|       for (int j=0;j<Nsrc;j++) | ||||
|       { | ||||
|         axpy(guess_coarse[j],TensorRemove(innerProduct(tmp,src_coarse[j])) / eval_coarse[i],tmp,guess_coarse[j]); | ||||
|       } | ||||
|     } | ||||
|     //postprocessing | ||||
|     std::cout << GridLogMessage << "Start BlockPromote for loop" << std::endl; | ||||
|     for (int j=0;j<Nsrc;j++) | ||||
|     { | ||||
|     std::cout << GridLogMessage << "BlockProject iter: " << j << std::endl; | ||||
|     blockPromote(guess_coarse[j],guess[j],subspace); | ||||
|     guess[j].Checkerboard() = src[j].Checkerboard(); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -147,20 +147,13 @@ public: | ||||
|   RealD                             _coarse_relax_tol; | ||||
|   std::vector<FineField>        &_subspace; | ||||
|    | ||||
|   int _largestEvalIdxForReport; //The convergence of the LCL is based on the evals of the coarse grid operator, not those of the underlying fine grid operator | ||||
|                                 //As a result we do not know what the eval range of the fine operator is until the very end, making tuning the Cheby bounds very difficult | ||||
|                                 //To work around this issue, every restart we separately reconstruct the fine operator eval for the lowest and highest evec and print these | ||||
|                                 //out alongside the evals of the coarse operator. To do so we need to know the index of the largest eval (i.e. Nstop-1) | ||||
|                                 //NOTE: If largestEvalIdxForReport=-1 (default) then this is not performed | ||||
|    | ||||
|   ImplicitlyRestartedLanczosSmoothedTester(LinearFunction<CoarseField>   &Poly, | ||||
| 					   OperatorFunction<FineField>   &smoother, | ||||
| 					   LinearOperatorBase<FineField> &Linop, | ||||
| 					   std::vector<FineField>        &subspace, | ||||
| 					   RealD coarse_relax_tol=5.0e3, | ||||
| 					   int largestEvalIdxForReport=-1)  | ||||
| 					   RealD coarse_relax_tol=5.0e3)  | ||||
|     : _smoother(smoother), _Linop(Linop), _Poly(Poly), _subspace(subspace), | ||||
|       _coarse_relax_tol(coarse_relax_tol), _largestEvalIdxForReport(largestEvalIdxForReport) | ||||
|       _coarse_relax_tol(coarse_relax_tol)   | ||||
|   {    }; | ||||
|  | ||||
|   //evalMaxApprox: approximation of largest eval of the fine Chebyshev operator (suitably wrapped by block projection) | ||||
| @@ -186,12 +179,6 @@ public: | ||||
| 	     <<" |H B[i] - eval[i]B[i]|^2 / evalMaxApprox^2 " << std::setw(25) << vv | ||||
| 	     <<std::endl; | ||||
|  | ||||
|     if(_largestEvalIdxForReport != -1 && (j==0 || j==_largestEvalIdxForReport)){ | ||||
|       std::cout<<GridLogIRL << "Estimating true eval of fine grid operator for eval idx " << j << std::endl; | ||||
|       RealD tmp_eval; | ||||
|       ReconstructEval(j,eresid,B,tmp_eval,1.0); //don't use evalMaxApprox of coarse operator! (cf below) | ||||
|     } | ||||
|      | ||||
|     int conv=0; | ||||
|     if( (vv<eresid*eresid) ) conv = 1; | ||||
|     return conv; | ||||
| @@ -422,7 +409,7 @@ public: | ||||
|     ////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|     Chebyshev<FineField>                                           ChebySmooth(cheby_smooth); //lower order Chebyshev of fine operator on fine grid used to smooth regenerated eigenvectors | ||||
|     ImplicitlyRestartedLanczosSmoothedTester<Fobj,CComplex,nbasis> ChebySmoothTester(ChebyOp,ChebySmooth,_FineOp,subspace,relax,Nstop-1);  | ||||
|     ImplicitlyRestartedLanczosSmoothedTester<Fobj,CComplex,nbasis> ChebySmoothTester(ChebyOp,ChebySmooth,_FineOp,subspace,relax);  | ||||
|  | ||||
|     evals_coarse.resize(Nm); | ||||
|     evec_coarse.resize(Nm,_CoarseGrid); | ||||
|   | ||||
| @@ -4,14 +4,11 @@ NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| /*Allocation types, saying which pointer cache should be used*/ | ||||
| #define Cpu      (0) | ||||
| #define CpuHuge  (1) | ||||
| #define CpuSmall (2) | ||||
| #define Acc      (3) | ||||
| #define AccHuge  (4) | ||||
| #define AccSmall (5) | ||||
| #define Shared   (6) | ||||
| #define SharedHuge  (7) | ||||
| #define SharedSmall (8) | ||||
| #define CpuSmall (1) | ||||
| #define Acc      (2) | ||||
| #define AccSmall (3) | ||||
| #define Shared   (4) | ||||
| #define SharedSmall (5) | ||||
| #undef GRID_MM_VERBOSE  | ||||
| uint64_t total_shared; | ||||
| uint64_t total_device; | ||||
| @@ -38,15 +35,12 @@ void MemoryManager::PrintBytes(void) | ||||
|    | ||||
| } | ||||
|  | ||||
| uint64_t MemoryManager::DeviceCacheBytes() { return CacheBytes[Acc] + CacheBytes[AccHuge] + CacheBytes[AccSmall]; } | ||||
| uint64_t MemoryManager::HostCacheBytes()   { return CacheBytes[Cpu] + CacheBytes[CpuHuge] + CacheBytes[CpuSmall]; } | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////// | ||||
| // Data tables for recently freed pooiniter caches | ||||
| ////////////////////////////////////////////////////////////////////// | ||||
| MemoryManager::AllocationCacheEntry MemoryManager::Entries[MemoryManager::NallocType][MemoryManager::NallocCacheMax]; | ||||
| int MemoryManager::Victim[MemoryManager::NallocType]; | ||||
| int MemoryManager::Ncache[MemoryManager::NallocType] = { 2, 0, 8, 8, 0, 16, 8, 0, 16 }; | ||||
| int MemoryManager::Ncache[MemoryManager::NallocType] = { 2, 8, 2, 8, 2, 8 }; | ||||
| uint64_t MemoryManager::CacheBytes[MemoryManager::NallocType]; | ||||
| ////////////////////////////////////////////////////////////////////// | ||||
| // Actual allocation and deallocation utils | ||||
| @@ -176,16 +170,6 @@ void MemoryManager::Init(void) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   str= getenv("GRID_ALLOC_NCACHE_HUGE"); | ||||
|   if ( str ) { | ||||
|     Nc = atoi(str); | ||||
|     if ( (Nc>=0) && (Nc < NallocCacheMax)) { | ||||
|       Ncache[CpuHuge]=Nc; | ||||
|       Ncache[AccHuge]=Nc; | ||||
|       Ncache[SharedHuge]=Nc; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   str= getenv("GRID_ALLOC_NCACHE_SMALL"); | ||||
|   if ( str ) { | ||||
|     Nc = atoi(str); | ||||
| @@ -206,9 +190,7 @@ void MemoryManager::InitMessage(void) { | ||||
|    | ||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() setting up"<<std::endl; | ||||
| #ifdef ALLOCATION_CACHE | ||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() cache pool for recent host   allocations: SMALL "<<Ncache[CpuSmall]<<" LARGE "<<Ncache[Cpu]<<" HUGE "<<Ncache[CpuHuge]<<std::endl; | ||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() cache pool for recent device allocations: SMALL "<<Ncache[AccSmall]<<" LARGE "<<Ncache[Acc]<<" Huge "<<Ncache[AccHuge]<<std::endl; | ||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() cache pool for recent shared allocations: SMALL "<<Ncache[SharedSmall]<<" LARGE "<<Ncache[Shared]<<" Huge "<<Ncache[SharedHuge]<<std::endl; | ||||
|   std::cout << GridLogMessage<< "MemoryManager::Init() cache pool for recent allocations: SMALL "<<Ncache[CpuSmall]<<" LARGE "<<Ncache[Cpu]<<std::endl; | ||||
| #endif | ||||
|    | ||||
| #ifdef GRID_UVM | ||||
| @@ -240,11 +222,8 @@ void MemoryManager::InitMessage(void) { | ||||
| void *MemoryManager::Insert(void *ptr,size_t bytes,int type)  | ||||
| { | ||||
| #ifdef ALLOCATION_CACHE | ||||
|   int cache; | ||||
|   if      (bytes < GRID_ALLOC_SMALL_LIMIT) cache = type + 2; | ||||
|   else if (bytes >= GRID_ALLOC_HUGE_LIMIT) cache = type + 1; | ||||
|   else                                     cache = type; | ||||
|  | ||||
|   bool small = (bytes < GRID_ALLOC_SMALL_LIMIT); | ||||
|   int cache = type + small; | ||||
|   return Insert(ptr,bytes,Entries[cache],Ncache[cache],Victim[cache],CacheBytes[cache]);   | ||||
| #else | ||||
|   return ptr; | ||||
| @@ -253,12 +232,11 @@ void *MemoryManager::Insert(void *ptr,size_t bytes,int type) | ||||
|  | ||||
| void *MemoryManager::Insert(void *ptr,size_t bytes,AllocationCacheEntry *entries,int ncache,int &victim, uint64_t &cacheBytes)  | ||||
| { | ||||
|   assert(ncache>0); | ||||
| #ifdef GRID_OMP | ||||
|   assert(omp_in_parallel()==0); | ||||
| #endif  | ||||
|  | ||||
|   if (ncache == 0) return ptr; | ||||
|  | ||||
|   void * ret = NULL; | ||||
|   int v = -1; | ||||
|  | ||||
| @@ -293,11 +271,8 @@ void *MemoryManager::Insert(void *ptr,size_t bytes,AllocationCacheEntry *entries | ||||
| void *MemoryManager::Lookup(size_t bytes,int type) | ||||
| { | ||||
| #ifdef ALLOCATION_CACHE | ||||
|   int cache; | ||||
|   if      (bytes < GRID_ALLOC_SMALL_LIMIT) cache = type + 2; | ||||
|   else if (bytes >= GRID_ALLOC_HUGE_LIMIT) cache = type + 1; | ||||
|   else                                     cache = type; | ||||
|  | ||||
|   bool small = (bytes < GRID_ALLOC_SMALL_LIMIT); | ||||
|   int cache = type+small; | ||||
|   return Lookup(bytes,Entries[cache],Ncache[cache],CacheBytes[cache]); | ||||
| #else | ||||
|   return NULL; | ||||
| @@ -306,6 +281,7 @@ void *MemoryManager::Lookup(size_t bytes,int type) | ||||
|  | ||||
| void *MemoryManager::Lookup(size_t bytes,AllocationCacheEntry *entries,int ncache,uint64_t & cacheBytes)  | ||||
| { | ||||
|   assert(ncache>0); | ||||
| #ifdef GRID_OMP | ||||
|   assert(omp_in_parallel()==0); | ||||
| #endif  | ||||
|   | ||||
| @@ -35,12 +35,6 @@ NAMESPACE_BEGIN(Grid); | ||||
| // Move control to configure.ac and Config.h? | ||||
|  | ||||
| #define GRID_ALLOC_SMALL_LIMIT (4096) | ||||
| #define GRID_ALLOC_HUGE_LIMIT  (2147483648) | ||||
|  | ||||
| #define STRINGIFY(x) #x | ||||
| #define TOSTRING(x) STRINGIFY(x) | ||||
| #define FILE_LINE __FILE__ ":" TOSTRING(__LINE__) | ||||
| #define AUDIT(a) MemoryManager::Audit(FILE_LINE) | ||||
|  | ||||
| /*Pinning pages is costly*/ | ||||
| //////////////////////////////////////////////////////////////////////////// | ||||
| @@ -71,21 +65,6 @@ enum ViewMode { | ||||
|   CpuWriteDiscard = 0x10 // same for now | ||||
| }; | ||||
|  | ||||
| struct MemoryStatus { | ||||
|   uint64_t     DeviceBytes; | ||||
|   uint64_t     DeviceLRUBytes; | ||||
|   uint64_t     DeviceMaxBytes; | ||||
|   uint64_t     HostToDeviceBytes; | ||||
|   uint64_t     DeviceToHostBytes; | ||||
|   uint64_t     HostToDeviceXfer; | ||||
|   uint64_t     DeviceToHostXfer; | ||||
|   uint64_t     DeviceEvictions; | ||||
|   uint64_t     DeviceDestroy; | ||||
|   uint64_t     DeviceAllocCacheBytes; | ||||
|   uint64_t     HostAllocCacheBytes; | ||||
| }; | ||||
|  | ||||
|  | ||||
| class MemoryManager { | ||||
| private: | ||||
|  | ||||
| @@ -99,7 +78,7 @@ private: | ||||
|   } AllocationCacheEntry; | ||||
|  | ||||
|   static const int NallocCacheMax=128;  | ||||
|   static const int NallocType=9; | ||||
|   static const int NallocType=6; | ||||
|   static AllocationCacheEntry Entries[NallocType][NallocCacheMax]; | ||||
|   static int Victim[NallocType]; | ||||
|   static int Ncache[NallocType]; | ||||
| @@ -113,9 +92,8 @@ private: | ||||
|   static void *Insert(void *ptr,size_t bytes,AllocationCacheEntry *entries,int ncache,int &victim,uint64_t &cbytes) ; | ||||
|   static void *Lookup(size_t bytes,AllocationCacheEntry *entries,int ncache,uint64_t &cbytes) ; | ||||
|  | ||||
|  public: | ||||
|   static void PrintBytes(void); | ||||
|   static void Audit(std::string s); | ||||
|  public: | ||||
|   static void Init(void); | ||||
|   static void InitMessage(void); | ||||
|   static void *AcceleratorAllocate(size_t bytes); | ||||
| @@ -135,27 +113,6 @@ private: | ||||
|   static uint64_t     DeviceToHostBytes; | ||||
|   static uint64_t     HostToDeviceXfer; | ||||
|   static uint64_t     DeviceToHostXfer; | ||||
|   static uint64_t     DeviceEvictions; | ||||
|   static uint64_t     DeviceDestroy; | ||||
|    | ||||
|   static uint64_t     DeviceCacheBytes(); | ||||
|   static uint64_t     HostCacheBytes(); | ||||
|  | ||||
|   static MemoryStatus GetFootprint(void) { | ||||
|     MemoryStatus stat; | ||||
|     stat.DeviceBytes       = DeviceBytes; | ||||
|     stat.DeviceLRUBytes    = DeviceLRUBytes; | ||||
|     stat.DeviceMaxBytes    = DeviceMaxBytes; | ||||
|     stat.HostToDeviceBytes = HostToDeviceBytes; | ||||
|     stat.DeviceToHostBytes = DeviceToHostBytes; | ||||
|     stat.HostToDeviceXfer  = HostToDeviceXfer; | ||||
|     stat.DeviceToHostXfer  = DeviceToHostXfer; | ||||
|     stat.DeviceEvictions   = DeviceEvictions; | ||||
|     stat.DeviceDestroy     = DeviceDestroy; | ||||
|     stat.DeviceAllocCacheBytes = DeviceCacheBytes(); | ||||
|     stat.HostAllocCacheBytes   = HostCacheBytes(); | ||||
|     return stat; | ||||
|   }; | ||||
|   | ||||
|  private: | ||||
| #ifndef GRID_UVM | ||||
| @@ -213,7 +170,6 @@ private: | ||||
|  | ||||
|  public: | ||||
|   static void Print(void); | ||||
|   static void PrintAll(void); | ||||
|   static void PrintState( void* CpuPtr); | ||||
|   static int   isOpen   (void* CpuPtr); | ||||
|   static void  ViewClose(void* CpuPtr,ViewMode mode); | ||||
|   | ||||
| @@ -3,13 +3,8 @@ | ||||
|  | ||||
| #warning "Using explicit device memory copies" | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #define MAXLINE 512 | ||||
| static char print_buffer [ MAXLINE ]; | ||||
|  | ||||
| #define mprintf(...) snprintf (print_buffer,MAXLINE, __VA_ARGS__ ); std::cout << GridLogMemory << print_buffer; | ||||
| #define dprintf(...) snprintf (print_buffer,MAXLINE, __VA_ARGS__ ); std::cout << GridLogMemory << print_buffer; | ||||
| //#define dprintf(...)  | ||||
| //#define dprintf(...) printf ( __VA_ARGS__ ); fflush(stdout); | ||||
| #define dprintf(...) | ||||
|  | ||||
|  | ||||
| //////////////////////////////////////////////////////////// | ||||
| @@ -28,8 +23,6 @@ uint64_t  MemoryManager::HostToDeviceBytes; | ||||
| uint64_t  MemoryManager::DeviceToHostBytes; | ||||
| uint64_t  MemoryManager::HostToDeviceXfer; | ||||
| uint64_t  MemoryManager::DeviceToHostXfer; | ||||
| uint64_t  MemoryManager::DeviceEvictions; | ||||
| uint64_t  MemoryManager::DeviceDestroy; | ||||
|  | ||||
| //////////////////////////////////// | ||||
| // Priority ordering for unlocked entries | ||||
| @@ -111,17 +104,15 @@ void MemoryManager::AccDiscard(AcceleratorViewEntry &AccCache) | ||||
|   /////////////////////////////////////////////////////////// | ||||
|   assert(AccCache.state!=Empty); | ||||
|    | ||||
|   mprintf("MemoryManager: Discard(%lx) %lx\n",(uint64_t)AccCache.CpuPtr,(uint64_t)AccCache.AccPtr);  | ||||
|    dprintf("MemoryManager: Discard(%llx) %llx\n",(uint64_t)AccCache.CpuPtr,(uint64_t)AccCache.AccPtr);  | ||||
|   assert(AccCache.accLock==0); | ||||
|   assert(AccCache.cpuLock==0); | ||||
|   assert(AccCache.CpuPtr!=(uint64_t)NULL); | ||||
|   if(AccCache.AccPtr) { | ||||
|     AcceleratorFree((void *)AccCache.AccPtr,AccCache.bytes); | ||||
|     DeviceDestroy++; | ||||
|     DeviceBytes   -=AccCache.bytes; | ||||
|     LRUremove(AccCache); | ||||
|     AccCache.AccPtr=(uint64_t) NULL; | ||||
|     dprintf("MemoryManager: Free(%lx) LRU %ld Total %ld\n",(uint64_t)AccCache.AccPtr,DeviceLRUBytes,DeviceBytes);   | ||||
|     dprintf("MemoryManager: Free(%llx) LRU %lld Total %lld\n",(uint64_t)AccCache.AccPtr,DeviceLRUBytes,DeviceBytes);   | ||||
|   } | ||||
|   uint64_t CpuPtr = AccCache.CpuPtr; | ||||
|   EntryErase(CpuPtr); | ||||
| @@ -130,36 +121,26 @@ void MemoryManager::AccDiscard(AcceleratorViewEntry &AccCache) | ||||
| void MemoryManager::Evict(AcceleratorViewEntry &AccCache) | ||||
| { | ||||
|   /////////////////////////////////////////////////////////////////////////// | ||||
|   // Make CPU consistent, remove from Accelerator, remove from LRU, LEAVE CPU only entry | ||||
|   // Cannot be acclocked. If allocated must be in LRU pool. | ||||
|   // | ||||
|   // Nov 2022... Felix issue: Allocating two CpuPtrs, can have an entry in LRU-q with CPUlock. | ||||
|   //                          and require to evict the AccPtr copy. Eviction was a mistake in CpuViewOpen | ||||
|   //                          but there is a weakness where CpuLock entries are attempted for erase | ||||
|   //                          Take these OUT LRU queue when CPU locked? | ||||
|   //                          Cannot take out the table as cpuLock data is important. | ||||
|   // Make CPU consistent, remove from Accelerator, remove entry | ||||
|   // Cannot be locked. If allocated must be in LRU pool. | ||||
|   /////////////////////////////////////////////////////////////////////////// | ||||
|   assert(AccCache.state!=Empty); | ||||
|    | ||||
|   mprintf("MemoryManager: Evict cpu %lx acc %lx cpuLock %ld accLock %ld\n", | ||||
| 	  (uint64_t)AccCache.CpuPtr,(uint64_t)AccCache.AccPtr, | ||||
| 	  (uint64_t)AccCache.cpuLock,(uint64_t)AccCache.accLock);  | ||||
|   if (AccCache.accLock!=0) return; | ||||
|   if (AccCache.cpuLock!=0) return; | ||||
|   dprintf("MemoryManager: Evict(%llx) %llx\n",(uint64_t)AccCache.CpuPtr,(uint64_t)AccCache.AccPtr);  | ||||
|   assert(AccCache.accLock==0); | ||||
|   assert(AccCache.cpuLock==0); | ||||
|   if(AccCache.state==AccDirty) { | ||||
|     Flush(AccCache); | ||||
|   } | ||||
|   assert(AccCache.CpuPtr!=(uint64_t)NULL); | ||||
|   if(AccCache.AccPtr) { | ||||
|     AcceleratorFree((void *)AccCache.AccPtr,AccCache.bytes); | ||||
|     LRUremove(AccCache); | ||||
|     AccCache.AccPtr=(uint64_t)NULL; | ||||
|     AccCache.state=CpuDirty; // CPU primary now | ||||
|     DeviceBytes   -=AccCache.bytes; | ||||
|     dprintf("MemoryManager: Free(%lx) footprint now %ld \n",(uint64_t)AccCache.AccPtr,DeviceBytes);   | ||||
|     LRUremove(AccCache); | ||||
|     dprintf("MemoryManager: Free(%llx) footprint now %lld \n",(uint64_t)AccCache.AccPtr,DeviceBytes);   | ||||
|   } | ||||
|   //  uint64_t CpuPtr = AccCache.CpuPtr; | ||||
|   DeviceEvictions++; | ||||
|   //  EntryErase(CpuPtr); | ||||
|   uint64_t CpuPtr = AccCache.CpuPtr; | ||||
|   EntryErase(CpuPtr); | ||||
| } | ||||
| void MemoryManager::Flush(AcceleratorViewEntry &AccCache) | ||||
| { | ||||
| @@ -169,7 +150,7 @@ void MemoryManager::Flush(AcceleratorViewEntry &AccCache) | ||||
|   assert(AccCache.AccPtr!=(uint64_t)NULL); | ||||
|   assert(AccCache.CpuPtr!=(uint64_t)NULL); | ||||
|   acceleratorCopyFromDevice((void *)AccCache.AccPtr,(void *)AccCache.CpuPtr,AccCache.bytes); | ||||
|   mprintf("MemoryManager: Flush  %lx -> %lx\n",(uint64_t)AccCache.AccPtr,(uint64_t)AccCache.CpuPtr); fflush(stdout); | ||||
|   dprintf("MemoryManager: Flush  %llx -> %llx\n",(uint64_t)AccCache.AccPtr,(uint64_t)AccCache.CpuPtr); fflush(stdout); | ||||
|   DeviceToHostBytes+=AccCache.bytes; | ||||
|   DeviceToHostXfer++; | ||||
|   AccCache.state=Consistent; | ||||
| @@ -184,7 +165,7 @@ void MemoryManager::Clone(AcceleratorViewEntry &AccCache) | ||||
|     AccCache.AccPtr=(uint64_t)AcceleratorAllocate(AccCache.bytes); | ||||
|     DeviceBytes+=AccCache.bytes; | ||||
|   } | ||||
|   mprintf("MemoryManager: Clone %lx <- %lx\n",(uint64_t)AccCache.AccPtr,(uint64_t)AccCache.CpuPtr); fflush(stdout); | ||||
|   dprintf("MemoryManager: Clone %llx <- %llx\n",(uint64_t)AccCache.AccPtr,(uint64_t)AccCache.CpuPtr); fflush(stdout); | ||||
|   acceleratorCopyToDevice((void *)AccCache.CpuPtr,(void *)AccCache.AccPtr,AccCache.bytes); | ||||
|   HostToDeviceBytes+=AccCache.bytes; | ||||
|   HostToDeviceXfer++; | ||||
| @@ -210,7 +191,6 @@ void MemoryManager::CpuDiscard(AcceleratorViewEntry &AccCache) | ||||
| void MemoryManager::ViewClose(void* Ptr,ViewMode mode) | ||||
| { | ||||
|   if( (mode==AcceleratorRead)||(mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard) ){ | ||||
|     dprintf("AcceleratorViewClose %lx\n",(uint64_t)Ptr); | ||||
|     AcceleratorViewClose((uint64_t)Ptr); | ||||
|   } else if( (mode==CpuRead)||(mode==CpuWrite)){ | ||||
|     CpuViewClose((uint64_t)Ptr); | ||||
| @@ -222,7 +202,6 @@ void *MemoryManager::ViewOpen(void* _CpuPtr,size_t bytes,ViewMode mode,ViewAdvis | ||||
| { | ||||
|   uint64_t CpuPtr = (uint64_t)_CpuPtr; | ||||
|   if( (mode==AcceleratorRead)||(mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard) ){ | ||||
|     dprintf("AcceleratorViewOpen %lx\n",(uint64_t)CpuPtr); | ||||
|     return (void *) AcceleratorViewOpen(CpuPtr,bytes,mode,hint); | ||||
|   } else if( (mode==CpuRead)||(mode==CpuWrite)){ | ||||
|     return (void *)CpuViewOpen(CpuPtr,bytes,mode,hint); | ||||
| @@ -233,16 +212,13 @@ void *MemoryManager::ViewOpen(void* _CpuPtr,size_t bytes,ViewMode mode,ViewAdvis | ||||
| } | ||||
| void  MemoryManager::EvictVictims(uint64_t bytes) | ||||
| { | ||||
|   assert(bytes<DeviceMaxBytes); | ||||
|   while(bytes+DeviceLRUBytes > DeviceMaxBytes){ | ||||
|     if ( DeviceLRUBytes > 0){ | ||||
|       assert(LRU.size()>0); | ||||
|       uint64_t victim = LRU.back(); // From the LRU | ||||
|       uint64_t victim = LRU.back(); | ||||
|       auto AccCacheIterator = EntryLookup(victim); | ||||
|       auto & AccCache = AccCacheIterator->second; | ||||
|       Evict(AccCache); | ||||
|     } else { | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -265,12 +241,11 @@ uint64_t MemoryManager::AcceleratorViewOpen(uint64_t CpuPtr,size_t bytes,ViewMod | ||||
|   assert(AccCache.cpuLock==0);  // Programming error | ||||
|  | ||||
|   if(AccCache.state!=Empty) { | ||||
|     dprintf("ViewOpen found entry %lx %lx : %ld %ld accLock %ld\n", | ||||
|     dprintf("ViewOpen found entry %llx %llx : %lld %lld\n", | ||||
| 		    (uint64_t)AccCache.CpuPtr, | ||||
| 		    (uint64_t)CpuPtr, | ||||
| 		    (uint64_t)AccCache.bytes, | ||||
| 	            (uint64_t)bytes, | ||||
| 		    (uint64_t)AccCache.accLock); | ||||
| 		    (uint64_t)bytes); | ||||
|     assert(AccCache.CpuPtr == CpuPtr); | ||||
|     assert(AccCache.bytes  ==bytes); | ||||
|   } | ||||
| @@ -305,7 +280,6 @@ uint64_t MemoryManager::AcceleratorViewOpen(uint64_t CpuPtr,size_t bytes,ViewMod | ||||
|       AccCache.state  = Consistent; // Empty + AccRead => Consistent | ||||
|     } | ||||
|     AccCache.accLock= 1; | ||||
|     dprintf("Copied Empty entry into device accLock= %d\n",AccCache.accLock); | ||||
|   } else if(AccCache.state==CpuDirty ){ | ||||
|     if(mode==AcceleratorWriteDiscard) { | ||||
|       CpuDiscard(AccCache); | ||||
| @@ -318,30 +292,28 @@ uint64_t MemoryManager::AcceleratorViewOpen(uint64_t CpuPtr,size_t bytes,ViewMod | ||||
|       AccCache.state  = Consistent; // CpuDirty + AccRead => Consistent | ||||
|     } | ||||
|     AccCache.accLock++; | ||||
|     dprintf("CpuDirty entry into device ++accLock= %d\n",AccCache.accLock); | ||||
|     dprintf("Copied CpuDirty entry into device accLock %d\n",AccCache.accLock); | ||||
|   } else if(AccCache.state==Consistent) { | ||||
|     if((mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard)) | ||||
|       AccCache.state  = AccDirty;   // Consistent + AcceleratorWrite=> AccDirty | ||||
|     else | ||||
|       AccCache.state  = Consistent; // Consistent + AccRead => Consistent | ||||
|     AccCache.accLock++; | ||||
|     dprintf("Consistent entry into device ++accLock= %d\n",AccCache.accLock); | ||||
|     dprintf("Consistent entry into device accLock %d\n",AccCache.accLock); | ||||
|   } else if(AccCache.state==AccDirty) { | ||||
|     if((mode==AcceleratorWrite)||(mode==AcceleratorWriteDiscard)) | ||||
|       AccCache.state  = AccDirty; // AccDirty + AcceleratorWrite=> AccDirty | ||||
|     else | ||||
|       AccCache.state  = AccDirty; // AccDirty + AccRead => AccDirty | ||||
|     AccCache.accLock++; | ||||
|     dprintf("AccDirty entry ++accLock= %d\n",AccCache.accLock); | ||||
|     dprintf("AccDirty entry into device accLock %d\n",AccCache.accLock); | ||||
|   } else { | ||||
|     assert(0); | ||||
|   } | ||||
|  | ||||
|   assert(AccCache.accLock>0); | ||||
|   // If view is opened on device must remove from LRU | ||||
|   // If view is opened on device remove from LRU | ||||
|   if(AccCache.LRU_valid==1){ | ||||
|     // must possibly remove from LRU as now locked on GPU | ||||
|     dprintf("AccCache entry removed from LRU \n"); | ||||
|     LRUremove(AccCache); | ||||
|   } | ||||
|  | ||||
| @@ -362,12 +334,10 @@ void MemoryManager::AcceleratorViewClose(uint64_t CpuPtr) | ||||
|   assert(AccCache.accLock>0); | ||||
|  | ||||
|   AccCache.accLock--; | ||||
|  | ||||
|   // Move to LRU queue if not locked and close on device | ||||
|   if(AccCache.accLock==0) { | ||||
|     dprintf("AccleratorViewClose %lx AccLock decremented to %ld move to LRU queue\n",(uint64_t)CpuPtr,(uint64_t)AccCache.accLock); | ||||
|     LRUinsert(AccCache); | ||||
|   } else { | ||||
|     dprintf("AccleratorViewClose %lx AccLock decremented to %ld\n",(uint64_t)CpuPtr,(uint64_t)AccCache.accLock); | ||||
|   } | ||||
| } | ||||
| void MemoryManager::CpuViewClose(uint64_t CpuPtr) | ||||
| @@ -404,10 +374,9 @@ uint64_t MemoryManager::CpuViewOpen(uint64_t CpuPtr,size_t bytes,ViewMode mode,V | ||||
|   auto AccCacheIterator = EntryLookup(CpuPtr); | ||||
|   auto & AccCache = AccCacheIterator->second; | ||||
|  | ||||
|   // CPU doesn't need to free space | ||||
|   //  if (!AccCache.AccPtr) { | ||||
|   //    EvictVictims(bytes); | ||||
|   //  } | ||||
|   if (!AccCache.AccPtr) { | ||||
|      EvictVictims(bytes); | ||||
|   } | ||||
|  | ||||
|   assert((mode==CpuRead)||(mode==CpuWrite)); | ||||
|   assert(AccCache.accLock==0);  // Programming error | ||||
| @@ -461,28 +430,20 @@ void  MemoryManager::NotifyDeletion(void *_ptr) | ||||
| void  MemoryManager::Print(void) | ||||
| { | ||||
|   PrintBytes(); | ||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; | ||||
|   std::cout << GridLogMessage << "Memory Manager                             " << std::endl; | ||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; | ||||
|   std::cout << GridLogMessage << DeviceBytes   << " bytes allocated on device " << std::endl; | ||||
|   std::cout << GridLogMessage << DeviceLRUBytes<< " bytes evictable on device " << std::endl; | ||||
|   std::cout << GridLogMessage << DeviceMaxBytes<< " bytes max on device       " << std::endl; | ||||
|   std::cout << GridLogMessage << HostToDeviceXfer << " transfers        to   device " << std::endl; | ||||
|   std::cout << GridLogMessage << DeviceToHostXfer << " transfers        from device " << std::endl; | ||||
|   std::cout << GridLogMessage << HostToDeviceBytes<< " bytes transfered to   device " << std::endl; | ||||
|   std::cout << GridLogMessage << DeviceToHostBytes<< " bytes transfered from device " << std::endl; | ||||
|   std::cout << GridLogMessage << DeviceEvictions  << " Evictions from device " << std::endl; | ||||
|   std::cout << GridLogMessage << DeviceDestroy    << " Destroyed vectors on device " << std::endl; | ||||
|   std::cout << GridLogMessage << AccViewTable.size()<< " vectors " << LRU.size()<<" evictable"<< std::endl; | ||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; | ||||
| } | ||||
| void  MemoryManager::PrintAll(void) | ||||
| { | ||||
|   Print(); | ||||
|   std::cout << GridLogMessage << std::endl; | ||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; | ||||
|   std::cout << GridLogMessage << "CpuAddr\t\tAccAddr\t\tState\t\tcpuLock\taccLock\tLRU_valid "<<std::endl; | ||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; | ||||
|   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||
|   std::cout << GridLogDebug << "Memory Manager                             " << std::endl; | ||||
|   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||
|   std::cout << GridLogDebug << DeviceBytes   << " bytes allocated on device " << std::endl; | ||||
|   std::cout << GridLogDebug << DeviceLRUBytes<< " bytes evictable on device " << std::endl; | ||||
|   std::cout << GridLogDebug << DeviceMaxBytes<< " bytes max on device       " << std::endl; | ||||
|   std::cout << GridLogDebug << HostToDeviceXfer << " transfers        to   device " << std::endl; | ||||
|   std::cout << GridLogDebug << DeviceToHostXfer << " transfers        from device " << std::endl; | ||||
|   std::cout << GridLogDebug << HostToDeviceBytes<< " bytes transfered to   device " << std::endl; | ||||
|   std::cout << GridLogDebug << DeviceToHostBytes<< " bytes transfered from device " << std::endl; | ||||
|   std::cout << GridLogDebug << AccViewTable.size()<< " vectors " << LRU.size()<<" evictable"<< std::endl; | ||||
|   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||
|   std::cout << GridLogDebug << "CpuAddr\t\tAccAddr\t\tState\t\tcpuLock\taccLock\tLRU_valid "<<std::endl; | ||||
|   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||
|   for(auto it=AccViewTable.begin();it!=AccViewTable.end();it++){ | ||||
|     auto &AccCache = it->second; | ||||
|      | ||||
| @@ -492,13 +453,13 @@ void  MemoryManager::PrintAll(void) | ||||
|     if ( AccCache.state==AccDirty ) str = std::string("AccDirty"); | ||||
|     if ( AccCache.state==Consistent)str = std::string("Consistent"); | ||||
|  | ||||
|     std::cout << GridLogMessage << "0x"<<std::hex<<AccCache.CpuPtr<<std::dec | ||||
|     std::cout << GridLogDebug << "0x"<<std::hex<<AccCache.CpuPtr<<std::dec | ||||
| 	      << "\t0x"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str | ||||
| 	      << "\t" << AccCache.cpuLock | ||||
| 	      << "\t" << AccCache.accLock | ||||
| 	      << "\t" << AccCache.LRU_valid<<std::endl; | ||||
|   } | ||||
|   std::cout << GridLogMessage << "--------------------------------------------" << std::endl; | ||||
|   std::cout << GridLogDebug << "--------------------------------------------" << std::endl; | ||||
|  | ||||
| }; | ||||
| int   MemoryManager::isOpen   (void* _CpuPtr)  | ||||
| @@ -512,64 +473,6 @@ int   MemoryManager::isOpen   (void* _CpuPtr) | ||||
|     return 0; | ||||
|   } | ||||
| } | ||||
| void MemoryManager::Audit(std::string s) | ||||
| { | ||||
|   uint64_t CpuBytes=0; | ||||
|   uint64_t AccBytes=0; | ||||
|   uint64_t LruBytes1=0; | ||||
|   uint64_t LruBytes2=0; | ||||
|   uint64_t LruCnt=0; | ||||
|   uint64_t LockedBytes=0; | ||||
|    | ||||
|   std::cout << " Memory Manager::Audit() from "<<s<<std::endl; | ||||
|   for(auto it=LRU.begin();it!=LRU.end();it++){ | ||||
|     uint64_t cpuPtr = *it; | ||||
|     assert(EntryPresent(cpuPtr)); | ||||
|     auto AccCacheIterator = EntryLookup(cpuPtr); | ||||
|     auto & AccCache = AccCacheIterator->second; | ||||
|     LruBytes2+=AccCache.bytes; | ||||
|     assert(AccCache.LRU_valid==1); | ||||
|     assert(AccCache.LRU_entry==it); | ||||
|   } | ||||
|   std::cout << " Memory Manager::Audit() LRU queue matches table entries "<<std::endl; | ||||
|  | ||||
|   for(auto it=AccViewTable.begin();it!=AccViewTable.end();it++){ | ||||
|     auto &AccCache = it->second; | ||||
|      | ||||
|     std::string str; | ||||
|     if ( AccCache.state==Empty    ) str = std::string("Empty"); | ||||
|     if ( AccCache.state==CpuDirty ) str = std::string("CpuDirty"); | ||||
|     if ( AccCache.state==AccDirty ) str = std::string("AccDirty"); | ||||
|     if ( AccCache.state==Consistent)str = std::string("Consistent"); | ||||
|  | ||||
|     CpuBytes+=AccCache.bytes; | ||||
|     if( AccCache.AccPtr )    AccBytes+=AccCache.bytes; | ||||
|     if( AccCache.LRU_valid ) LruBytes1+=AccCache.bytes; | ||||
|     if( AccCache.LRU_valid ) LruCnt++; | ||||
|      | ||||
|     if ( AccCache.cpuLock || AccCache.accLock ) { | ||||
|       assert(AccCache.LRU_valid==0); | ||||
|  | ||||
|       std::cout << GridLogError << s<< "\n\t 0x"<<std::hex<<AccCache.CpuPtr<<std::dec | ||||
| 		<< "\t0x"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str | ||||
| 		<< "\t cpuLock  " << AccCache.cpuLock | ||||
| 		<< "\t accLock  " << AccCache.accLock | ||||
| 		<< "\t LRUvalid " << AccCache.LRU_valid<<std::endl; | ||||
|     } | ||||
|  | ||||
|     assert( AccCache.cpuLock== 0 ) ; | ||||
|     assert( AccCache.accLock== 0 ) ; | ||||
|   } | ||||
|   std::cout << " Memory Manager::Audit() no locked table entries "<<std::endl; | ||||
|   assert(LruBytes1==LruBytes2); | ||||
|   assert(LruBytes1==DeviceLRUBytes); | ||||
|   std::cout << " Memory Manager::Audit() evictable bytes matches sum over table "<<std::endl; | ||||
|   assert(AccBytes==DeviceBytes); | ||||
|   std::cout << " Memory Manager::Audit() device bytes matches sum over table "<<std::endl; | ||||
|   assert(LruCnt == LRU.size()); | ||||
|   std::cout << " Memory Manager::Audit() LRU entry count matches "<<std::endl; | ||||
|  | ||||
| } | ||||
|  | ||||
| void MemoryManager::PrintState(void* _CpuPtr) | ||||
| { | ||||
| @@ -586,8 +489,8 @@ void MemoryManager::PrintState(void* _CpuPtr) | ||||
|     if ( AccCache.state==EvictNext) str = std::string("EvictNext"); | ||||
|  | ||||
|     std::cout << GridLogMessage << "CpuAddr\t\tAccAddr\t\tState\t\tcpuLock\taccLock\tLRU_valid "<<std::endl; | ||||
|     std::cout << GridLogMessage << "\tx"<<std::hex<<AccCache.CpuPtr<<std::dec | ||||
|     << "\tx"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str | ||||
|     std::cout << GridLogMessage << "0x"<<std::hex<<AccCache.CpuPtr<<std::dec | ||||
|     << "\t0x"<<std::hex<<AccCache.AccPtr<<std::dec<<"\t" <<str | ||||
|     << "\t" << AccCache.cpuLock | ||||
|     << "\t" << AccCache.accLock | ||||
|     << "\t" << AccCache.LRU_valid<<std::endl; | ||||
|   | ||||
| @@ -12,10 +12,7 @@ uint64_t  MemoryManager::HostToDeviceBytes; | ||||
| uint64_t  MemoryManager::DeviceToHostBytes; | ||||
| uint64_t  MemoryManager::HostToDeviceXfer; | ||||
| uint64_t  MemoryManager::DeviceToHostXfer; | ||||
| uint64_t  MemoryManager::DeviceEvictions; | ||||
| uint64_t  MemoryManager::DeviceDestroy; | ||||
|  | ||||
| void  MemoryManager::Audit(std::string s){}; | ||||
| void  MemoryManager::ViewClose(void* AccPtr,ViewMode mode){}; | ||||
| void *MemoryManager::ViewOpen(void* CpuPtr,size_t bytes,ViewMode mode,ViewAdvise hint){ return CpuPtr; }; | ||||
| int   MemoryManager::isOpen   (void* CpuPtr) { return 0;} | ||||
| @@ -24,7 +21,6 @@ void  MemoryManager::PrintState(void* CpuPtr) | ||||
| std::cout << GridLogMessage << "Host<->Device memory movement not currently managed by Grid." << std::endl; | ||||
| }; | ||||
| void  MemoryManager::Print(void){}; | ||||
| void  MemoryManager::PrintAll(void){}; | ||||
| void  MemoryManager::NotifyDeletion(void *ptr){}; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -53,11 +53,10 @@ public: | ||||
|   // Communicator should know nothing of the physics grid, only processor grid. | ||||
|   //////////////////////////////////////////// | ||||
|   int              _Nprocessors;     // How many in all | ||||
|   int              _processor;       // linear processor rank | ||||
|   unsigned long    _ndimension; | ||||
|   Coordinate _shm_processors;  // Which dimensions get relayed out over processors lanes. | ||||
|   Coordinate _processors;      // Which dimensions get relayed out over processors lanes. | ||||
|   int              _processor;       // linear processor rank | ||||
|   Coordinate _processor_coor;  // linear processor coordinate | ||||
|   unsigned long    _ndimension; | ||||
|   static Grid_MPI_Comm      communicator_world; | ||||
|   Grid_MPI_Comm             communicator; | ||||
|   std::vector<Grid_MPI_Comm> communicator_halo; | ||||
| @@ -98,7 +97,6 @@ public: | ||||
|   int                      BossRank(void)          ; | ||||
|   int                      ThisRank(void)          ; | ||||
|   const Coordinate & ThisProcessorCoor(void) ; | ||||
|   const Coordinate & ShmGrid(void)  { return _shm_processors; }  ; | ||||
|   const Coordinate & ProcessorGrid(void)     ; | ||||
|   int                      ProcessorCount(void)    ; | ||||
|  | ||||
| @@ -107,7 +105,6 @@ public: | ||||
|   //////////////////////////////////////////////////////////////////////////////// | ||||
|   static int  RankWorld(void) ; | ||||
|   static void BroadcastWorld(int root,void* data, int bytes); | ||||
|   static void BarrierWorld(void); | ||||
|    | ||||
|   //////////////////////////////////////////////////////////// | ||||
|   // Reduction | ||||
| @@ -131,7 +128,7 @@ public: | ||||
|   template<class obj> void GlobalSum(obj &o){ | ||||
|     typedef typename obj::scalar_type scalar_type; | ||||
|     int words = sizeof(obj)/sizeof(scalar_type); | ||||
|     scalar_type * ptr = (scalar_type *)& o; // Safe alias  | ||||
|     scalar_type * ptr = (scalar_type *)& o; | ||||
|     GlobalSumVector(ptr,words); | ||||
|   } | ||||
|    | ||||
| @@ -145,17 +142,17 @@ public: | ||||
| 		      int bytes); | ||||
|    | ||||
|   double StencilSendToRecvFrom(void *xmit, | ||||
| 			       int xmit_to_rank,int do_xmit, | ||||
| 			       int xmit_to_rank, | ||||
| 			       void *recv, | ||||
| 			       int recv_from_rank,int do_recv, | ||||
| 			       int recv_from_rank, | ||||
| 			       int bytes,int dir); | ||||
|  | ||||
|   double StencilSendToRecvFromBegin(std::vector<CommsRequest_t> &list, | ||||
| 				    void *xmit, | ||||
| 				    int xmit_to_rank,int do_xmit, | ||||
| 				    int xmit_to_rank, | ||||
| 				    void *recv, | ||||
| 				    int recv_from_rank,int do_recv, | ||||
| 				    int xbytes,int rbytes,int dir); | ||||
| 				    int recv_from_rank, | ||||
| 				    int bytes,int dir); | ||||
|    | ||||
|    | ||||
|   void StencilSendToRecvFromComplete(std::vector<CommsRequest_t> &waitall,int i); | ||||
|   | ||||
| @@ -106,7 +106,7 @@ CartesianCommunicator::CartesianCommunicator(const Coordinate &processors) | ||||
|   // Remap using the shared memory optimising routine | ||||
|   // The remap creates a comm which must be freed | ||||
|   //////////////////////////////////////////////////// | ||||
|   GlobalSharedMemory::OptimalCommunicator    (processors,optimal_comm,_shm_processors); | ||||
|   GlobalSharedMemory::OptimalCommunicator    (processors,optimal_comm); | ||||
|   InitFromMPICommunicator(processors,optimal_comm); | ||||
|   SetCommunicator(optimal_comm); | ||||
|   /////////////////////////////////////////////////// | ||||
| @@ -124,13 +124,12 @@ CartesianCommunicator::CartesianCommunicator(const Coordinate &processors,const | ||||
|   int parent_ndimension = parent._ndimension; assert(_ndimension >= parent._ndimension); | ||||
|   Coordinate parent_processor_coor(_ndimension,0); | ||||
|   Coordinate parent_processors    (_ndimension,1); | ||||
|   Coordinate shm_processors       (_ndimension,1); | ||||
|  | ||||
|   // Can make 5d grid from 4d etc... | ||||
|   int pad = _ndimension-parent_ndimension; | ||||
|   for(int d=0;d<parent_ndimension;d++){ | ||||
|     parent_processor_coor[pad+d]=parent._processor_coor[d]; | ||||
|     parent_processors    [pad+d]=parent._processors[d]; | ||||
|     shm_processors       [pad+d]=parent._shm_processors[d]; | ||||
|   } | ||||
|  | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -155,7 +154,6 @@ CartesianCommunicator::CartesianCommunicator(const Coordinate &processors,const | ||||
|     ccoor[d] = parent_processor_coor[d] % processors[d]; | ||||
|     scoor[d] = parent_processor_coor[d] / processors[d]; | ||||
|     ssize[d] = parent_processors[d]     / processors[d]; | ||||
|     if ( processors[d] < shm_processors[d] ) shm_processors[d] = processors[d]; // subnode splitting. | ||||
|   } | ||||
|  | ||||
|   // rank within subcomm ; srank is rank of subcomm within blocks of subcomms | ||||
| @@ -337,23 +335,23 @@ void CartesianCommunicator::SendToRecvFrom(void *xmit, | ||||
| } | ||||
| // Basic Halo comms primitive | ||||
| double CartesianCommunicator::StencilSendToRecvFrom( void *xmit, | ||||
| 						     int dest, int dox, | ||||
| 						     int dest, | ||||
| 						     void *recv, | ||||
| 						     int from, int dor, | ||||
| 						     int from, | ||||
| 						     int bytes,int dir) | ||||
| { | ||||
|   std::vector<CommsRequest_t> list; | ||||
|   double offbytes = StencilSendToRecvFromBegin(list,xmit,dest,dox,recv,from,dor,bytes,bytes,dir); | ||||
|   double offbytes = StencilSendToRecvFromBegin(list,xmit,dest,recv,from,bytes,dir); | ||||
|   StencilSendToRecvFromComplete(list,dir); | ||||
|   return offbytes; | ||||
| } | ||||
|  | ||||
| double CartesianCommunicator::StencilSendToRecvFromBegin(std::vector<CommsRequest_t> &list, | ||||
| 							 void *xmit, | ||||
| 							 int dest,int dox, | ||||
| 							 int dest, | ||||
| 							 void *recv, | ||||
| 							 int from,int dor, | ||||
| 							 int xbytes,int rbytes,int dir) | ||||
| 							 int from, | ||||
| 							 int bytes,int dir) | ||||
| { | ||||
|   int ncomm  =communicator_halo.size(); | ||||
|   int commdir=dir%ncomm; | ||||
| @@ -372,34 +370,39 @@ double CartesianCommunicator::StencilSendToRecvFromBegin(std::vector<CommsReques | ||||
|   double off_node_bytes=0.0; | ||||
|   int tag; | ||||
|  | ||||
|   if ( dor ) { | ||||
|   if ( (gfrom ==MPI_UNDEFINED) || Stencil_force_mpi ) { | ||||
|     tag= dir+from*32; | ||||
|       ierr=MPI_Irecv(recv, rbytes, MPI_CHAR,from,tag,communicator_halo[commdir],&rrq); | ||||
|     ierr=MPI_Irecv(recv, bytes, MPI_CHAR,from,tag,communicator_halo[commdir],&rrq); | ||||
|     assert(ierr==0); | ||||
|     list.push_back(rrq); | ||||
|       off_node_bytes+=rbytes; | ||||
|     } | ||||
|     off_node_bytes+=bytes; | ||||
|   } | ||||
|  | ||||
|   if (dox) { | ||||
|   if ( (gdest == MPI_UNDEFINED) || Stencil_force_mpi ) { | ||||
|     tag= dir+_processor*32; | ||||
|       ierr =MPI_Isend(xmit, xbytes, MPI_CHAR,dest,tag,communicator_halo[commdir],&xrq); | ||||
|     ierr =MPI_Isend(xmit, bytes, MPI_CHAR,dest,tag,communicator_halo[commdir],&xrq); | ||||
|     assert(ierr==0); | ||||
|     list.push_back(xrq); | ||||
|       off_node_bytes+=xbytes; | ||||
|     off_node_bytes+=bytes; | ||||
|   } else { | ||||
|     // TODO : make a OMP loop on CPU, call threaded bcopy | ||||
|     void *shm = (void *) this->ShmBufferTranslate(dest,recv); | ||||
|     assert(shm!=NULL); | ||||
|       acceleratorCopyDeviceToDeviceAsynch(xmit,shm,xbytes); | ||||
|     //    std::cout <<"acceleratorCopyDeviceToDeviceAsynch"<< std::endl; | ||||
|     acceleratorCopyDeviceToDeviceAsynch(xmit,shm,bytes); | ||||
|   } | ||||
|  | ||||
|   if ( CommunicatorPolicy == CommunicatorPolicySequential ) { | ||||
|     this->StencilSendToRecvFromComplete(list,dir); | ||||
|   } | ||||
|  | ||||
|   return off_node_bytes; | ||||
| } | ||||
| void CartesianCommunicator::StencilSendToRecvFromComplete(std::vector<CommsRequest_t> &list,int dir) | ||||
| { | ||||
|   //   std::cout << "Copy Synchronised\n"<<std::endl; | ||||
|   acceleratorCopySynchronise(); | ||||
|  | ||||
|   int nreq=list.size(); | ||||
|  | ||||
|   if (nreq==0) return; | ||||
| @@ -435,10 +438,6 @@ int CartesianCommunicator::RankWorld(void){ | ||||
|   MPI_Comm_rank(communicator_world,&r); | ||||
|   return r; | ||||
| } | ||||
| void CartesianCommunicator::BarrierWorld(void){ | ||||
|   int ierr = MPI_Barrier(communicator_world); | ||||
|   assert(ierr==0); | ||||
| } | ||||
| void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes) | ||||
| { | ||||
|   int ierr= MPI_Bcast(data, | ||||
|   | ||||
| @@ -45,14 +45,12 @@ void CartesianCommunicator::Init(int *argc, char *** arv) | ||||
| CartesianCommunicator::CartesianCommunicator(const Coordinate &processors,const CartesianCommunicator &parent,int &srank)  | ||||
|   : CartesianCommunicator(processors)  | ||||
| { | ||||
|   _shm_processors = Coordinate(processors.size(),1); | ||||
|   srank=0; | ||||
|   SetCommunicator(communicator_world); | ||||
| } | ||||
|  | ||||
| CartesianCommunicator::CartesianCommunicator(const Coordinate &processors) | ||||
| { | ||||
|   _shm_processors = Coordinate(processors.size(),1); | ||||
|   _processors = processors; | ||||
|   _ndimension = processors.size();  assert(_ndimension>=1); | ||||
|   _processor_coor.resize(_ndimension); | ||||
| @@ -104,7 +102,6 @@ int  CartesianCommunicator::RankWorld(void){return 0;} | ||||
| void CartesianCommunicator::Barrier(void){} | ||||
| void CartesianCommunicator::Broadcast(int root,void* data, int bytes) {} | ||||
| void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes) { } | ||||
| void CartesianCommunicator::BarrierWorld(void) { } | ||||
| int  CartesianCommunicator::RankFromProcessorCoor(Coordinate &coor) {  return 0;} | ||||
| void CartesianCommunicator::ProcessorCoorFromRank(int rank, Coordinate &coor){  coor = _processor_coor; } | ||||
| void CartesianCommunicator::ShiftedRanks(int dim,int shift,int &source,int &dest) | ||||
| @@ -114,21 +111,21 @@ void CartesianCommunicator::ShiftedRanks(int dim,int shift,int &source,int &dest | ||||
| } | ||||
|  | ||||
| double CartesianCommunicator::StencilSendToRecvFrom( void *xmit, | ||||
| 						     int xmit_to_rank,int dox, | ||||
| 						     int xmit_to_rank, | ||||
| 						     void *recv, | ||||
| 						     int recv_from_rank,int dor, | ||||
| 						     int recv_from_rank, | ||||
| 						     int bytes, int dir) | ||||
| { | ||||
|   return 2.0*bytes; | ||||
| } | ||||
| double CartesianCommunicator::StencilSendToRecvFromBegin(std::vector<CommsRequest_t> &list, | ||||
| 							 void *xmit, | ||||
| 							 int xmit_to_rank,int dox, | ||||
| 							 int xmit_to_rank, | ||||
| 							 void *recv, | ||||
| 							 int recv_from_rank,int dor, | ||||
| 							 int xbytes,int rbytes, int dir) | ||||
| 							 int recv_from_rank, | ||||
| 							 int bytes, int dir) | ||||
| { | ||||
|   return xbytes+rbytes; | ||||
|   return 2.0*bytes; | ||||
| } | ||||
| void CartesianCommunicator::StencilSendToRecvFromComplete(std::vector<CommsRequest_t> &waitall,int dir) | ||||
| { | ||||
|   | ||||
| @@ -91,59 +91,6 @@ void *SharedMemory::ShmBufferSelf(void) | ||||
|   //std::cerr << "ShmBufferSelf "<<ShmRank<<" "<<std::hex<< ShmCommBufs[ShmRank] <<std::dec<<std::endl; | ||||
|   return ShmCommBufs[ShmRank]; | ||||
| } | ||||
| static inline int divides(int a,int b) | ||||
| { | ||||
|   return ( b == ( (b/a)*a ) ); | ||||
| } | ||||
| void GlobalSharedMemory::GetShmDims(const Coordinate &WorldDims,Coordinate &ShmDims) | ||||
| { | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Allow user to configure through environment variable | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   char* str = getenv(("GRID_SHM_DIMS_" + std::to_string(ShmDims.size())).c_str()); | ||||
|   if ( str ) { | ||||
|     std::vector<int> IntShmDims; | ||||
|     GridCmdOptionIntVector(std::string(str),IntShmDims); | ||||
|     assert(IntShmDims.size() == WorldDims.size()); | ||||
|     long ShmSize = 1; | ||||
|     for (int dim=0;dim<WorldDims.size();dim++) { | ||||
|       ShmSize *= (ShmDims[dim] = IntShmDims[dim]); | ||||
|       assert(divides(ShmDims[dim],WorldDims[dim])); | ||||
|     } | ||||
|     assert(ShmSize == WorldShmSize); | ||||
|     return; | ||||
|   } | ||||
|    | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Powers of 2,3,5 only in prime decomposition for now | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   int ndimension = WorldDims.size(); | ||||
|   ShmDims=Coordinate(ndimension,1); | ||||
|  | ||||
|   std::vector<int> primes({2,3,5}); | ||||
|  | ||||
|   int dim = 0; | ||||
|   int last_dim = ndimension - 1; | ||||
|   int AutoShmSize = 1; | ||||
|   while(AutoShmSize != WorldShmSize) { | ||||
|     int p; | ||||
|     for(p=0;p<primes.size();p++) { | ||||
|       int prime=primes[p]; | ||||
|       if ( divides(prime,WorldDims[dim]/ShmDims[dim]) | ||||
|         && divides(prime,WorldShmSize/AutoShmSize)  ) { | ||||
|   AutoShmSize*=prime; | ||||
|   ShmDims[dim]*=prime; | ||||
|   last_dim = dim; | ||||
|   break; | ||||
|       } | ||||
|     } | ||||
|     if (p == primes.size() && last_dim == dim) { | ||||
|       std::cerr << "GlobalSharedMemory::GetShmDims failed" << std::endl; | ||||
|       exit(EXIT_FAILURE); | ||||
|     } | ||||
|     dim=(dim+1) %ndimension; | ||||
|   } | ||||
| } | ||||
|  | ||||
| NAMESPACE_END(Grid);  | ||||
|  | ||||
|   | ||||
| @@ -93,10 +93,9 @@ public: | ||||
|   // Create an optimal reordered communicator that makes MPI_Cart_create get it right | ||||
|   ////////////////////////////////////////////////////////////////////////////////////// | ||||
|   static void Init(Grid_MPI_Comm comm); // Typically MPI_COMM_WORLD | ||||
|   // Turns MPI_COMM_WORLD into right layout for Cartesian | ||||
|   static void OptimalCommunicator            (const Coordinate &processors,Grid_MPI_Comm & optimal_comm,Coordinate &ShmDims);  | ||||
|   static void OptimalCommunicatorHypercube   (const Coordinate &processors,Grid_MPI_Comm & optimal_comm,Coordinate &ShmDims);  | ||||
|   static void OptimalCommunicatorSharedMemory(const Coordinate &processors,Grid_MPI_Comm & optimal_comm,Coordinate &ShmDims);  | ||||
|   static void OptimalCommunicator            (const Coordinate &processors,Grid_MPI_Comm & optimal_comm);  // Turns MPI_COMM_WORLD into right layout for Cartesian | ||||
|   static void OptimalCommunicatorHypercube   (const Coordinate &processors,Grid_MPI_Comm & optimal_comm);  // Turns MPI_COMM_WORLD into right layout for Cartesian | ||||
|   static void OptimalCommunicatorSharedMemory(const Coordinate &processors,Grid_MPI_Comm & optimal_comm);  // Turns MPI_COMM_WORLD into right layout for Cartesian | ||||
|   static void GetShmDims(const Coordinate &WorldDims,Coordinate &ShmDims); | ||||
|   /////////////////////////////////////////////////// | ||||
|   // Provide shared memory facilities off comm world | ||||
|   | ||||
| @@ -29,7 +29,6 @@ Author: Christoph Lehner <christoph@lhnr.de> | ||||
|  | ||||
| #include <Grid/GridCore.h> | ||||
| #include <pwd.h> | ||||
| #include <syscall.h> | ||||
|  | ||||
| #ifdef GRID_CUDA | ||||
| #include <cuda_runtime_api.h> | ||||
| @@ -37,10 +36,9 @@ Author: Christoph Lehner <christoph@lhnr.de> | ||||
| #ifdef GRID_HIP | ||||
| #include <hip/hip_runtime_api.h> | ||||
| #endif | ||||
| #ifdef GRID_SYCL | ||||
| #define GRID_SYCL_LEVEL_ZERO_IPC | ||||
| #endif | ||||
| #ifdef GRID_SYCl | ||||
|  | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid);  | ||||
| #define header "SharedMemoryMpi: " | ||||
| @@ -154,7 +152,7 @@ int Log2Size(int TwoToPower,int MAXLOG2) | ||||
|   } | ||||
|   return log2size; | ||||
| } | ||||
| void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_MPI_Comm & optimal_comm,Coordinate &SHM) | ||||
| void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_MPI_Comm & optimal_comm) | ||||
| { | ||||
|   ////////////////////////////////////////////////////////////////////////////// | ||||
|   // Look and see if it looks like an HPE 8600 based on hostname conventions | ||||
| @@ -167,14 +165,63 @@ void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_M | ||||
|   gethostname(name,namelen); | ||||
|   int nscan = sscanf(name,"r%di%dn%d",&R,&I,&N) ; | ||||
|  | ||||
|   if(nscan==3 && HPEhypercube ) OptimalCommunicatorHypercube(processors,optimal_comm,SHM); | ||||
|   else                          OptimalCommunicatorSharedMemory(processors,optimal_comm,SHM); | ||||
|   if(nscan==3 && HPEhypercube ) OptimalCommunicatorHypercube(processors,optimal_comm); | ||||
|   else                          OptimalCommunicatorSharedMemory(processors,optimal_comm); | ||||
| } | ||||
| static inline int divides(int a,int b) | ||||
| { | ||||
|   return ( b == ( (b/a)*a ) ); | ||||
| } | ||||
| void GlobalSharedMemory::OptimalCommunicatorHypercube(const Coordinate &processors,Grid_MPI_Comm & optimal_comm,Coordinate &SHM) | ||||
| void GlobalSharedMemory::GetShmDims(const Coordinate &WorldDims,Coordinate &ShmDims) | ||||
| { | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Allow user to configure through environment variable | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   char* str = getenv(("GRID_SHM_DIMS_" + std::to_string(ShmDims.size())).c_str()); | ||||
|   if ( str ) { | ||||
|     std::vector<int> IntShmDims; | ||||
|     GridCmdOptionIntVector(std::string(str),IntShmDims); | ||||
|     assert(IntShmDims.size() == WorldDims.size()); | ||||
|     long ShmSize = 1; | ||||
|     for (int dim=0;dim<WorldDims.size();dim++) { | ||||
|       ShmSize *= (ShmDims[dim] = IntShmDims[dim]); | ||||
|       assert(divides(ShmDims[dim],WorldDims[dim])); | ||||
|     } | ||||
|     assert(ShmSize == WorldShmSize); | ||||
|     return; | ||||
|   } | ||||
|    | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Powers of 2,3,5 only in prime decomposition for now | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   int ndimension = WorldDims.size(); | ||||
|   ShmDims=Coordinate(ndimension,1); | ||||
|  | ||||
|   std::vector<int> primes({2,3,5}); | ||||
|  | ||||
|   int dim = 0; | ||||
|   int last_dim = ndimension - 1; | ||||
|   int AutoShmSize = 1; | ||||
|   while(AutoShmSize != WorldShmSize) { | ||||
|     int p; | ||||
|     for(p=0;p<primes.size();p++) { | ||||
|       int prime=primes[p]; | ||||
|       if ( divides(prime,WorldDims[dim]/ShmDims[dim]) | ||||
|         && divides(prime,WorldShmSize/AutoShmSize)  ) { | ||||
| 	AutoShmSize*=prime; | ||||
| 	ShmDims[dim]*=prime; | ||||
| 	last_dim = dim; | ||||
| 	break; | ||||
|       } | ||||
|     } | ||||
|     if (p == primes.size() && last_dim == dim) { | ||||
|       std::cerr << "GlobalSharedMemory::GetShmDims failed" << std::endl; | ||||
|       exit(EXIT_FAILURE); | ||||
|     } | ||||
|     dim=(dim+1) %ndimension; | ||||
|   } | ||||
| } | ||||
| void GlobalSharedMemory::OptimalCommunicatorHypercube(const Coordinate &processors,Grid_MPI_Comm & optimal_comm) | ||||
| { | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Assert power of two shm_size. | ||||
| @@ -247,7 +294,6 @@ void GlobalSharedMemory::OptimalCommunicatorHypercube(const Coordinate &processo | ||||
|   Coordinate HyperCoor(ndimension); | ||||
|  | ||||
|   GetShmDims(WorldDims,ShmDims); | ||||
|   SHM = ShmDims; | ||||
|  | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Establish torus of processes and nodes with sub-blockings | ||||
| @@ -295,7 +341,7 @@ void GlobalSharedMemory::OptimalCommunicatorHypercube(const Coordinate &processo | ||||
|   int ierr= MPI_Comm_split(WorldComm,0,rank,&optimal_comm); | ||||
|   assert(ierr==0); | ||||
| } | ||||
| void GlobalSharedMemory::OptimalCommunicatorSharedMemory(const Coordinate &processors,Grid_MPI_Comm & optimal_comm,Coordinate &SHM) | ||||
| void GlobalSharedMemory::OptimalCommunicatorSharedMemory(const Coordinate &processors,Grid_MPI_Comm & optimal_comm) | ||||
| { | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Identify subblock of ranks on node spreading across dims | ||||
| @@ -307,8 +353,6 @@ void GlobalSharedMemory::OptimalCommunicatorSharedMemory(const Coordinate &proce | ||||
|   Coordinate ShmCoor(ndimension);    Coordinate NodeCoor(ndimension);   Coordinate WorldCoor(ndimension); | ||||
|  | ||||
|   GetShmDims(WorldDims,ShmDims); | ||||
|   SHM=ShmDims; | ||||
|  | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Establish torus of processes and nodes with sub-blockings | ||||
|   //////////////////////////////////////////////////////////////// | ||||
| @@ -476,7 +520,7 @@ void GlobalSharedMemory::SharedMemoryAllocate(uint64_t bytes, int flags) | ||||
|   } | ||||
|   if ( WorldRank == 0 ){ | ||||
|     std::cout << WorldRank << header " SharedMemoryMPI.cc acceleratorAllocDevice "<< bytes  | ||||
| 	      << "bytes at "<< std::hex<< ShmCommBuf << " - "<<(bytes-1+(uint64_t)ShmCommBuf) <<std::dec<<" for comms buffers " <<std::endl; | ||||
| 	      << "bytes at "<< std::hex<< ShmCommBuf <<std::dec<<" for comms buffers " <<std::endl; | ||||
|   } | ||||
|   SharedMemoryZero(ShmCommBuf,bytes); | ||||
|   std::cout<< "Setting up IPC"<<std::endl; | ||||
|   | ||||
| @@ -48,10 +48,9 @@ void GlobalSharedMemory::Init(Grid_MPI_Comm comm) | ||||
|   _ShmSetup=1; | ||||
| } | ||||
|  | ||||
| void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_MPI_Comm & optimal_comm,Coordinate &SHM) | ||||
| void GlobalSharedMemory::OptimalCommunicator(const Coordinate &processors,Grid_MPI_Comm & optimal_comm) | ||||
| { | ||||
|   optimal_comm = WorldComm; | ||||
|   SHM = Coordinate(processors.size(),1); | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -297,30 +297,6 @@ template<class vobj> void Scatter_plane_merge(Lattice<vobj> &rhs,ExtractPointerA | ||||
|   } | ||||
| } | ||||
|  | ||||
| #if (defined(GRID_CUDA) || defined(GRID_HIP)) && defined(ACCELERATOR_CSHIFT) | ||||
|  | ||||
| template <typename T> | ||||
| T iDivUp(T a, T b) // Round a / b to nearest higher integer value | ||||
| { return (a % b != 0) ? (a / b + 1) : (a / b); } | ||||
|  | ||||
| template <typename T> | ||||
| __global__ void populate_Cshift_table(T* vector, T lo, T ro, T e1, T e2, T stride) | ||||
| { | ||||
|     int idx = blockIdx.x*blockDim.x + threadIdx.x; | ||||
|     if (idx >= e1*e2) return; | ||||
|  | ||||
|     int n, b, o; | ||||
|  | ||||
|     n = idx / e2; | ||||
|     b = idx % e2; | ||||
|     o = n*stride + b; | ||||
|  | ||||
|     vector[2*idx + 0] = lo + o; | ||||
|     vector[2*idx + 1] = ro + o; | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| ////////////////////////////////////////////////////// | ||||
| // local to node block strided copies | ||||
| ////////////////////////////////////////////////////// | ||||
| @@ -345,20 +321,12 @@ template<class vobj> void Copy_plane(Lattice<vobj>& lhs,const Lattice<vobj> &rhs | ||||
|   int ent=0; | ||||
|  | ||||
|   if(cbmask == 0x3 ){ | ||||
| #if (defined(GRID_CUDA) || defined(GRID_HIP)) && defined(ACCELERATOR_CSHIFT) | ||||
|     ent = e1*e2; | ||||
|     dim3 blockSize(acceleratorThreads()); | ||||
|     dim3 gridSize(iDivUp((unsigned int)ent, blockSize.x)); | ||||
|     populate_Cshift_table<<<gridSize, blockSize>>>(&Cshift_table[0].first, lo, ro, e1, e2, stride); | ||||
|     accelerator_barrier(); | ||||
| #else | ||||
|     for(int n=0;n<e1;n++){ | ||||
|       for(int b=0;b<e2;b++){ | ||||
|         int o =n*stride+b; | ||||
| 	Cshift_table[ent++] = std::pair<int,int>(lo+o,ro+o); | ||||
|       } | ||||
|     } | ||||
| #endif | ||||
|   } else {  | ||||
|     for(int n=0;n<e1;n++){ | ||||
|       for(int b=0;b<e2;b++){ | ||||
| @@ -409,19 +377,11 @@ template<class vobj> void Copy_plane_permute(Lattice<vobj>& lhs,const Lattice<vo | ||||
|   int ent=0; | ||||
|  | ||||
|   if ( cbmask == 0x3 ) { | ||||
| #if (defined(GRID_CUDA) || defined(GRID_HIP)) && defined(ACCELERATOR_CSHIFT) | ||||
|     ent = e1*e2; | ||||
|     dim3 blockSize(acceleratorThreads()); | ||||
|     dim3 gridSize(iDivUp((unsigned int)ent, blockSize.x)); | ||||
|     populate_Cshift_table<<<gridSize, blockSize>>>(&Cshift_table[0].first, lo, ro, e1, e2, stride); | ||||
|     accelerator_barrier(); | ||||
| #else | ||||
|     for(int n=0;n<e1;n++){ | ||||
|     for(int b=0;b<e2;b++){ | ||||
|       int o  =n*stride; | ||||
|       Cshift_table[ent++] = std::pair<int,int>(lo+o+b,ro+o+b); | ||||
|     }} | ||||
| #endif | ||||
|   } else { | ||||
|     for(int n=0;n<e1;n++){ | ||||
|     for(int b=0;b<e2;b++){ | ||||
|   | ||||
							
								
								
									
										23405
									
								
								Grid/json/json.hpp
									
									
									
									
									
								
							
							
						
						
									
										23405
									
								
								Grid/json/json.hpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -63,7 +63,7 @@ accelerator_inline vobj predicatedWhere(const iobj &predicate, | ||||
|   typename std::remove_const<vobj>::type ret; | ||||
|  | ||||
|   typedef typename vobj::scalar_object scalar_object; | ||||
|   //  typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|  | ||||
|   const int Nsimd = vobj::vector_type::Nsimd(); | ||||
|   | ||||
| @@ -36,7 +36,6 @@ NAMESPACE_BEGIN(Grid); | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void mult(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const Lattice<obj3> &rhs){ | ||||
|   GRID_TRACE("mult"); | ||||
|   ret.Checkerboard() = lhs.Checkerboard(); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
|   autoView( lhs_v , lhs, AcceleratorRead); | ||||
| @@ -54,7 +53,6 @@ void mult(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const Lattice<obj3> &rhs){ | ||||
|    | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void mac(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const Lattice<obj3> &rhs){ | ||||
|   GRID_TRACE("mac"); | ||||
|   ret.Checkerboard() = lhs.Checkerboard(); | ||||
|   conformable(ret,rhs); | ||||
|   conformable(lhs,rhs); | ||||
| @@ -72,7 +70,6 @@ void mac(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const Lattice<obj3> &rhs){ | ||||
|    | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void sub(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const Lattice<obj3> &rhs){ | ||||
|   GRID_TRACE("sub"); | ||||
|   ret.Checkerboard() = lhs.Checkerboard(); | ||||
|   conformable(ret,rhs); | ||||
|   conformable(lhs,rhs); | ||||
| @@ -89,7 +86,6 @@ void sub(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const Lattice<obj3> &rhs){ | ||||
| } | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void add(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const Lattice<obj3> &rhs){ | ||||
|   GRID_TRACE("add"); | ||||
|   ret.Checkerboard() = lhs.Checkerboard(); | ||||
|   conformable(ret,rhs); | ||||
|   conformable(lhs,rhs); | ||||
| @@ -110,7 +106,6 @@ void add(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const Lattice<obj3> &rhs){ | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void mult(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const obj3 &rhs){ | ||||
|   GRID_TRACE("mult"); | ||||
|   ret.Checkerboard() = lhs.Checkerboard(); | ||||
|   conformable(lhs,ret); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
| @@ -124,7 +119,6 @@ void mult(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const obj3 &rhs){ | ||||
|    | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void mac(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const obj3 &rhs){ | ||||
|   GRID_TRACE("mac"); | ||||
|   ret.Checkerboard() = lhs.Checkerboard(); | ||||
|   conformable(ret,lhs); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
| @@ -139,7 +133,6 @@ void mac(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const obj3 &rhs){ | ||||
|    | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void sub(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const obj3 &rhs){ | ||||
|   GRID_TRACE("sub"); | ||||
|   ret.Checkerboard() = lhs.Checkerboard(); | ||||
|   conformable(ret,lhs); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
| @@ -153,7 +146,6 @@ void sub(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const obj3 &rhs){ | ||||
| } | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void add(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const obj3 &rhs){ | ||||
|   GRID_TRACE("add"); | ||||
|   ret.Checkerboard() = lhs.Checkerboard(); | ||||
|   conformable(lhs,ret); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
| @@ -171,7 +163,6 @@ void add(Lattice<obj1> &ret,const Lattice<obj2> &lhs,const obj3 &rhs){ | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void mult(Lattice<obj1> &ret,const obj2 &lhs,const Lattice<obj3> &rhs){ | ||||
|   GRID_TRACE("mult"); | ||||
|   ret.Checkerboard() = rhs.Checkerboard(); | ||||
|   conformable(ret,rhs); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
| @@ -186,7 +177,6 @@ void mult(Lattice<obj1> &ret,const obj2 &lhs,const Lattice<obj3> &rhs){ | ||||
|    | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void mac(Lattice<obj1> &ret,const obj2 &lhs,const Lattice<obj3> &rhs){ | ||||
|   GRID_TRACE("mac"); | ||||
|   ret.Checkerboard() = rhs.Checkerboard(); | ||||
|   conformable(ret,rhs); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
| @@ -201,7 +191,6 @@ void mac(Lattice<obj1> &ret,const obj2 &lhs,const Lattice<obj3> &rhs){ | ||||
|    | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void sub(Lattice<obj1> &ret,const obj2 &lhs,const Lattice<obj3> &rhs){ | ||||
|   GRID_TRACE("sub"); | ||||
|   ret.Checkerboard() = rhs.Checkerboard(); | ||||
|   conformable(ret,rhs); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
| @@ -215,7 +204,6 @@ void sub(Lattice<obj1> &ret,const obj2 &lhs,const Lattice<obj3> &rhs){ | ||||
| } | ||||
| template<class obj1,class obj2,class obj3> inline | ||||
| void add(Lattice<obj1> &ret,const obj2 &lhs,const Lattice<obj3> &rhs){ | ||||
|   GRID_TRACE("add"); | ||||
|   ret.Checkerboard() = rhs.Checkerboard(); | ||||
|   conformable(ret,rhs); | ||||
|   autoView( ret_v , ret, AcceleratorWrite); | ||||
| @@ -230,7 +218,6 @@ void add(Lattice<obj1> &ret,const obj2 &lhs,const Lattice<obj3> &rhs){ | ||||
|    | ||||
| template<class sobj,class vobj> inline | ||||
| void axpy(Lattice<vobj> &ret,sobj a,const Lattice<vobj> &x,const Lattice<vobj> &y){ | ||||
|   GRID_TRACE("axpy"); | ||||
|   ret.Checkerboard() = x.Checkerboard(); | ||||
|   conformable(ret,x); | ||||
|   conformable(x,y); | ||||
| @@ -244,7 +231,6 @@ void axpy(Lattice<vobj> &ret,sobj a,const Lattice<vobj> &x,const Lattice<vobj> & | ||||
| } | ||||
| template<class sobj,class vobj> inline | ||||
| void axpby(Lattice<vobj> &ret,sobj a,sobj b,const Lattice<vobj> &x,const Lattice<vobj> &y){ | ||||
|   GRID_TRACE("axpby"); | ||||
|   ret.Checkerboard() = x.Checkerboard(); | ||||
|   conformable(ret,x); | ||||
|   conformable(x,y); | ||||
| @@ -260,13 +246,11 @@ void axpby(Lattice<vobj> &ret,sobj a,sobj b,const Lattice<vobj> &x,const Lattice | ||||
| template<class sobj,class vobj> inline | ||||
| RealD axpy_norm(Lattice<vobj> &ret,sobj a,const Lattice<vobj> &x,const Lattice<vobj> &y) | ||||
| { | ||||
|   GRID_TRACE("axpy_norm"); | ||||
|     return axpy_norm_fast(ret,a,x,y); | ||||
| } | ||||
| template<class sobj,class vobj> inline | ||||
| RealD axpby_norm(Lattice<vobj> &ret,sobj a,sobj b,const Lattice<vobj> &x,const Lattice<vobj> &y) | ||||
| { | ||||
|   GRID_TRACE("axpby_norm"); | ||||
|     return axpby_norm_fast(ret,a,b,x,y); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -117,7 +117,6 @@ public: | ||||
|   //////////////////////////////////////////////////////////////////////////////// | ||||
|   template <typename Op, typename T1> inline Lattice<vobj> & operator=(const LatticeUnaryExpression<Op,T1> &expr) | ||||
|   { | ||||
|     GRID_TRACE("ExpressionTemplateEval"); | ||||
|     GridBase *egrid(nullptr); | ||||
|     GridFromExpression(egrid,expr); | ||||
|     assert(egrid!=nullptr); | ||||
| @@ -141,7 +140,6 @@ public: | ||||
|   } | ||||
|   template <typename Op, typename T1,typename T2> inline Lattice<vobj> & operator=(const LatticeBinaryExpression<Op,T1,T2> &expr) | ||||
|   { | ||||
|     GRID_TRACE("ExpressionTemplateEval"); | ||||
|     GridBase *egrid(nullptr); | ||||
|     GridFromExpression(egrid,expr); | ||||
|     assert(egrid!=nullptr); | ||||
| @@ -165,7 +163,6 @@ public: | ||||
|   } | ||||
|   template <typename Op, typename T1,typename T2,typename T3> inline Lattice<vobj> & operator=(const LatticeTrinaryExpression<Op,T1,T2,T3> &expr) | ||||
|   { | ||||
|     GRID_TRACE("ExpressionTemplateEval"); | ||||
|     GridBase *egrid(nullptr); | ||||
|     GridFromExpression(egrid,expr); | ||||
|     assert(egrid!=nullptr); | ||||
| @@ -291,8 +288,8 @@ public: | ||||
|     typename std::enable_if<!std::is_same<robj,vobj>::value,int>::type i=0; | ||||
|     conformable(*this,r); | ||||
|     this->checkerboard = r.Checkerboard(); | ||||
|     auto him= r.View(AcceleratorRead); | ||||
|     auto me =   View(AcceleratorWriteDiscard); | ||||
|     auto him= r.View(AcceleratorRead); | ||||
|     accelerator_for(ss,me.size(),vobj::Nsimd(),{ | ||||
|       coalescedWrite(me[ss],him(ss)); | ||||
|     }); | ||||
| @@ -306,8 +303,8 @@ public: | ||||
|   inline Lattice<vobj> & operator = (const Lattice<vobj> & r){ | ||||
|     this->checkerboard = r.Checkerboard(); | ||||
|     conformable(*this,r); | ||||
|     auto him= r.View(AcceleratorRead); | ||||
|     auto me =   View(AcceleratorWriteDiscard); | ||||
|     auto him= r.View(AcceleratorRead); | ||||
|     accelerator_for(ss,me.size(),vobj::Nsimd(),{ | ||||
|       coalescedWrite(me[ss],him(ss)); | ||||
|     }); | ||||
|   | ||||
| @@ -29,19 +29,6 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| template<class vobj> void DumpSliceNorm(std::string s,Lattice<vobj> &f,int mu=-1) | ||||
| { | ||||
|   auto ff = localNorm2(f); | ||||
|   if ( mu==-1 ) mu = f.Grid()->Nd()-1; | ||||
|   typedef typename vobj::tensor_reduced normtype; | ||||
|   typedef typename normtype::scalar_object scalar; | ||||
|   std::vector<scalar> sff; | ||||
|   sliceSum(ff,sff,mu); | ||||
|   for(int t=0;t<sff.size();t++){ | ||||
|     std::cout << s<<" "<<t<<" "<<sff[t]<<std::endl; | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<class vobj> uint32_t crc(Lattice<vobj> & buf) | ||||
| { | ||||
|   autoView( buf_v , buf, CpuRead); | ||||
|   | ||||
| @@ -32,6 +32,7 @@ template<class vobj> | ||||
| static void sliceMaddMatrix (Lattice<vobj> &R,Eigen::MatrixXcd &aa,const Lattice<vobj> &X,const Lattice<vobj> &Y,int Orthog,RealD scale=1.0)  | ||||
| {     | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|  | ||||
|   int Nblock = X.Grid()->GlobalDimensions()[Orthog]; | ||||
| @@ -81,6 +82,7 @@ template<class vobj> | ||||
| static void sliceMulMatrix (Lattice<vobj> &R,Eigen::MatrixXcd &aa,const Lattice<vobj> &X,int Orthog,RealD scale=1.0)  | ||||
| {     | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|  | ||||
|   int Nblock = X.Grid()->GlobalDimensions()[Orthog]; | ||||
| @@ -128,6 +130,7 @@ template<class vobj> | ||||
| static void sliceInnerProductMatrix(  Eigen::MatrixXcd &mat, const Lattice<vobj> &lhs,const Lattice<vobj> &rhs,int Orthog)  | ||||
| { | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|    | ||||
|   GridBase *FullGrid  = lhs.Grid(); | ||||
|   | ||||
| @@ -96,6 +96,9 @@ void pokeSite(const sobj &s,Lattice<vobj> &l,const Coordinate &site){ | ||||
|  | ||||
|   GridBase *grid=l.Grid(); | ||||
|  | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|  | ||||
|   int Nsimd = grid->Nsimd(); | ||||
|  | ||||
|   assert( l.Checkerboard()== l.Grid()->CheckerBoard(site)); | ||||
| @@ -122,17 +125,14 @@ void pokeSite(const sobj &s,Lattice<vobj> &l,const Coordinate &site){ | ||||
| ////////////////////////////////////////////////////////// | ||||
| // Peek a scalar object from the SIMD array | ||||
| ////////////////////////////////////////////////////////// | ||||
| template<class vobj> | ||||
| typename vobj::scalar_object peekSite(const Lattice<vobj> &l,const Coordinate &site){ | ||||
|   typename vobj::scalar_object s; | ||||
|   peekSite(s,l,site); | ||||
|   return s; | ||||
| }         | ||||
| template<class vobj,class sobj> | ||||
| void peekSite(sobj &s,const Lattice<vobj> &l,const Coordinate &site){ | ||||
|          | ||||
|   GridBase *grid=l.Grid(); | ||||
|  | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|  | ||||
|   int Nsimd = grid->Nsimd(); | ||||
|  | ||||
|   assert( l.Checkerboard() == l.Grid()->CheckerBoard(site)); | ||||
| @@ -173,11 +173,11 @@ inline void peekLocalSite(sobj &s,const LatticeView<vobj> &l,Coordinate &site) | ||||
|   idx= grid->iIndex(site); | ||||
|   odx= grid->oIndex(site); | ||||
|    | ||||
|   const vector_type *vp = (const vector_type *) &l[odx]; | ||||
|   scalar_type * vp = (scalar_type *)&l[odx]; | ||||
|   scalar_type * pt = (scalar_type *)&s; | ||||
|        | ||||
|   for(int w=0;w<words;w++){ | ||||
|     pt[w] = getlane(vp[w],idx); | ||||
|     pt[w] = vp[idx+w*Nsimd]; | ||||
|   } | ||||
|        | ||||
|   return; | ||||
| @@ -210,10 +210,10 @@ inline void pokeLocalSite(const sobj &s,LatticeView<vobj> &l,Coordinate &site) | ||||
|   idx= grid->iIndex(site); | ||||
|   odx= grid->oIndex(site); | ||||
|  | ||||
|   vector_type * vp = (vector_type *)&l[odx]; | ||||
|   scalar_type * vp = (scalar_type *)&l[odx]; | ||||
|   scalar_type * pt = (scalar_type *)&s; | ||||
|   for(int w=0;w<words;w++){ | ||||
|     putlane(vp[w],pt[w],idx); | ||||
|     vp[idx+w*Nsimd] = pt[w]; | ||||
|   } | ||||
|   return; | ||||
| }; | ||||
|   | ||||
| @@ -28,9 +28,6 @@ Author: Christoph Lehner <christoph@lhnr.de> | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP) | ||||
| #include <Grid/lattice/Lattice_reduction_gpu.h> | ||||
| #endif | ||||
| #if defined(GRID_SYCL) | ||||
| #include <Grid/lattice/Lattice_reduction_sycl.h> | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| @@ -94,7 +91,10 @@ inline typename vobj::scalar_objectD sumD_cpu(const vobj *arg, Integer osites) | ||||
|   for(int i=0;i<nthread;i++){ | ||||
|     ssum = ssum+sumarray[i]; | ||||
|   }  | ||||
|   return ssum; | ||||
|    | ||||
|   typedef typename vobj::scalar_object ssobj; | ||||
|   ssobj ret = ssum; | ||||
|   return ret; | ||||
| } | ||||
| /* | ||||
| Threaded max, don't use for now | ||||
| @@ -127,7 +127,7 @@ inline Double max(const Double *arg, Integer osites) | ||||
| template<class vobj> | ||||
| inline typename vobj::scalar_object sum(const vobj *arg, Integer osites) | ||||
| { | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP) | ||||
|   return sum_gpu(arg,osites); | ||||
| #else | ||||
|   return sum_cpu(arg,osites); | ||||
| @@ -136,61 +136,25 @@ inline typename vobj::scalar_object sum(const vobj *arg, Integer osites) | ||||
| template<class vobj> | ||||
| inline typename vobj::scalar_objectD sumD(const vobj *arg, Integer osites) | ||||
| { | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP) | ||||
|   return sumD_gpu(arg,osites); | ||||
| #else | ||||
|   return sumD_cpu(arg,osites); | ||||
| #endif   | ||||
| } | ||||
| template<class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_large(const vobj *arg, Integer osites) | ||||
| { | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) | ||||
|   return sumD_gpu_large(arg,osites); | ||||
| #else | ||||
|   return sumD_cpu(arg,osites); | ||||
| #endif   | ||||
| } | ||||
|  | ||||
| template<class vobj> | ||||
| inline typename vobj::scalar_object rankSum(const Lattice<vobj> &arg) | ||||
| { | ||||
|   Integer osites = arg.Grid()->oSites(); | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) | ||||
|   autoView( arg_v, arg, AcceleratorRead); | ||||
|   return sum_gpu(&arg_v[0],osites); | ||||
| #else | ||||
|   autoView(arg_v, arg, CpuRead); | ||||
|   return sum_cpu(&arg_v[0],osites); | ||||
| #endif   | ||||
| } | ||||
|  | ||||
| template<class vobj> | ||||
| inline typename vobj::scalar_object sum(const Lattice<vobj> &arg) | ||||
| { | ||||
|   auto ssum = rankSum(arg); | ||||
|   arg.Grid()->GlobalSum(ssum); | ||||
|   return ssum; | ||||
| } | ||||
|  | ||||
| template<class vobj> | ||||
| inline typename vobj::scalar_object rankSumLarge(const Lattice<vobj> &arg) | ||||
| { | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP)||defined(GRID_SYCL) | ||||
| #if defined(GRID_CUDA)||defined(GRID_HIP) | ||||
|   autoView( arg_v, arg, AcceleratorRead); | ||||
|   Integer osites = arg.Grid()->oSites(); | ||||
|   return sum_gpu_large(&arg_v[0],osites); | ||||
|   auto ssum= sum_gpu(&arg_v[0],osites); | ||||
| #else | ||||
|   autoView(arg_v, arg, CpuRead); | ||||
|   Integer osites = arg.Grid()->oSites(); | ||||
|   return sum_cpu(&arg_v[0],osites); | ||||
|   auto ssum= sum_cpu(&arg_v[0],osites); | ||||
| #endif   | ||||
| } | ||||
|  | ||||
| template<class vobj> | ||||
| inline typename vobj::scalar_object sum_large(const Lattice<vobj> &arg) | ||||
| { | ||||
|   auto ssum = rankSumLarge(arg); | ||||
|   arg.Grid()->GlobalSum(ssum); | ||||
|   return ssum; | ||||
| } | ||||
| @@ -233,6 +197,7 @@ template<class vobj> inline RealD maxLocalNorm2(const Lattice<vobj> &arg) | ||||
| template<class vobj> | ||||
| inline ComplexD rankInnerProduct(const Lattice<vobj> &left,const Lattice<vobj> &right) | ||||
| { | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_typeD vector_type; | ||||
|   ComplexD  nrm; | ||||
|    | ||||
| @@ -242,40 +207,24 @@ inline ComplexD rankInnerProduct(const Lattice<vobj> &left,const Lattice<vobj> & | ||||
|   const uint64_t sites = grid->oSites(); | ||||
|    | ||||
|   // Might make all code paths go this way. | ||||
| #if 0 | ||||
|   typedef decltype(innerProductD(vobj(),vobj())) inner_t; | ||||
|   Vector<inner_t> inner_tmp(sites); | ||||
|   auto inner_tmp_v = &inner_tmp[0]; | ||||
|   { | ||||
|     autoView( left_v , left, AcceleratorRead); | ||||
|     autoView( right_v,right, AcceleratorRead); | ||||
|     // This code could read coalesce | ||||
|     // GPU - SIMT lane compliance... | ||||
|     accelerator_for( ss, sites, nsimd,{ | ||||
| 	auto x_l = left_v(ss); | ||||
| 	auto y_l = right_v(ss); | ||||
| 	coalescedWrite(inner_tmp_v[ss],innerProductD(x_l,y_l)); | ||||
|     }); | ||||
|   } | ||||
| #else | ||||
|   typedef decltype(innerProduct(vobj(),vobj())) inner_t; | ||||
|   Vector<inner_t> inner_tmp(sites); | ||||
|   auto inner_tmp_v = &inner_tmp[0]; | ||||
|      | ||||
|   { | ||||
|     autoView( left_v , left, AcceleratorRead); | ||||
|     autoView( right_v,right, AcceleratorRead); | ||||
|  | ||||
|     // GPU - SIMT lane compliance... | ||||
|     accelerator_for( ss, sites, nsimd,{ | ||||
| 	auto x_l = left_v(ss); | ||||
| 	auto y_l = right_v(ss); | ||||
| 	coalescedWrite(inner_tmp_v[ss],innerProduct(x_l,y_l)); | ||||
|     accelerator_for( ss, sites, 1,{ | ||||
| 	auto x_l = left_v[ss]; | ||||
| 	auto y_l = right_v[ss]; | ||||
| 	inner_tmp_v[ss]=innerProductD(x_l,y_l); | ||||
|     }); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   // This is in single precision and fails some tests | ||||
|   auto anrm = sumD(inner_tmp_v,sites);   | ||||
|   auto anrm = sum(inner_tmp_v,sites);   | ||||
|   nrm = anrm; | ||||
|   return nrm; | ||||
| } | ||||
| @@ -308,7 +257,8 @@ axpby_norm_fast(Lattice<vobj> &z,sobj a,sobj b,const Lattice<vobj> &x,const Latt | ||||
|   conformable(z,x); | ||||
|   conformable(x,y); | ||||
|  | ||||
|   //  typedef typename vobj::vector_typeD vector_type; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_typeD vector_type; | ||||
|   RealD  nrm; | ||||
|    | ||||
|   GridBase *grid = x.Grid(); | ||||
| @@ -320,29 +270,17 @@ axpby_norm_fast(Lattice<vobj> &z,sobj a,sobj b,const Lattice<vobj> &x,const Latt | ||||
|   autoView( x_v, x, AcceleratorRead); | ||||
|   autoView( y_v, y, AcceleratorRead); | ||||
|   autoView( z_v, z, AcceleratorWrite); | ||||
| #if 0 | ||||
|  | ||||
|   typedef decltype(innerProductD(x_v[0],y_v[0])) inner_t; | ||||
|   Vector<inner_t> inner_tmp(sites); | ||||
|   auto inner_tmp_v = &inner_tmp[0]; | ||||
|  | ||||
|   accelerator_for( ss, sites, nsimd,{ | ||||
|       auto tmp = a*x_v(ss)+b*y_v(ss); | ||||
|       coalescedWrite(inner_tmp_v[ss],innerProductD(tmp,tmp)); | ||||
|       coalescedWrite(z_v[ss],tmp); | ||||
|   accelerator_for( ss, sites, 1,{ | ||||
|       auto tmp = a*x_v[ss]+b*y_v[ss]; | ||||
|       inner_tmp_v[ss]=innerProductD(tmp,tmp); | ||||
|       z_v[ss]=tmp; | ||||
|   }); | ||||
|   nrm = real(TensorRemove(sum(inner_tmp_v,sites))); | ||||
| #else | ||||
|   typedef decltype(innerProduct(x_v[0],y_v[0])) inner_t; | ||||
|   Vector<inner_t> inner_tmp(sites); | ||||
|   auto inner_tmp_v = &inner_tmp[0]; | ||||
|  | ||||
|   accelerator_for( ss, sites, nsimd,{ | ||||
|       auto tmp = a*x_v(ss)+b*y_v(ss); | ||||
|       coalescedWrite(inner_tmp_v[ss],innerProduct(tmp,tmp)); | ||||
|       coalescedWrite(z_v[ss],tmp); | ||||
|   }); | ||||
|   nrm = real(TensorRemove(sumD(inner_tmp_v,sites))); | ||||
| #endif | ||||
|   grid->GlobalSum(nrm); | ||||
|   return nrm;  | ||||
| } | ||||
| @@ -352,6 +290,7 @@ innerProductNorm(ComplexD& ip, RealD &nrm, const Lattice<vobj> &left,const Latti | ||||
| { | ||||
|   conformable(left,right); | ||||
|  | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_typeD vector_type; | ||||
|   Vector<ComplexD> tmp(2); | ||||
|  | ||||
| @@ -495,14 +434,6 @@ template<class vobj> inline void sliceSum(const Lattice<vobj> &Data,std::vector< | ||||
|   int words = fd*sizeof(sobj)/sizeof(scalar_type); | ||||
|   grid->GlobalSumVector(ptr, words); | ||||
| } | ||||
| template<class vobj> inline | ||||
| std::vector<typename vobj::scalar_object>  | ||||
| sliceSum(const Lattice<vobj> &Data,int orthogdim) | ||||
| { | ||||
|   std::vector<typename vobj::scalar_object> result; | ||||
|   sliceSum(Data,result,orthogdim); | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| template<class vobj> | ||||
| static void sliceInnerProductVector( std::vector<ComplexD> & result, const Lattice<vobj> &lhs,const Lattice<vobj> &rhs,int orthogdim)  | ||||
| @@ -608,7 +539,6 @@ template<class vobj> | ||||
| static void sliceMaddVector(Lattice<vobj> &R,std::vector<RealD> &a,const Lattice<vobj> &X,const Lattice<vobj> &Y, | ||||
| 			    int orthogdim,RealD scale=1.0)  | ||||
| {     | ||||
|   // perhaps easier to just promote A to a field and use regular madd | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
| @@ -639,7 +569,8 @@ static void sliceMaddVector(Lattice<vobj> &R,std::vector<RealD> &a,const Lattice | ||||
|     for(int l=0;l<Nsimd;l++){ | ||||
|       grid->iCoorFromIindex(icoor,l); | ||||
|       int ldx =r+icoor[orthogdim]*rd; | ||||
|       av.putlane(scalar_type(a[ldx])*zscale,l); | ||||
|       scalar_type *as =(scalar_type *)&av; | ||||
|       as[l] = scalar_type(a[ldx])*zscale; | ||||
|     } | ||||
|  | ||||
|     tensor_reduced at; at=av; | ||||
| @@ -679,6 +610,7 @@ template<class vobj> | ||||
| static void sliceMaddMatrix (Lattice<vobj> &R,Eigen::MatrixXcd &aa,const Lattice<vobj> &X,const Lattice<vobj> &Y,int Orthog,RealD scale=1.0)  | ||||
| {     | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|  | ||||
|   int Nblock = X.Grid()->GlobalDimensions()[Orthog]; | ||||
| @@ -732,6 +664,7 @@ template<class vobj> | ||||
| static void sliceMulMatrix (Lattice<vobj> &R,Eigen::MatrixXcd &aa,const Lattice<vobj> &X,int Orthog,RealD scale=1.0)  | ||||
| {     | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|  | ||||
|   int Nblock = X.Grid()->GlobalDimensions()[Orthog]; | ||||
| @@ -785,6 +718,7 @@ template<class vobj> | ||||
| static void sliceInnerProductMatrix(  Eigen::MatrixXcd &mat, const Lattice<vobj> &lhs,const Lattice<vobj> &rhs,int Orthog)  | ||||
| { | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   typedef typename vobj::scalar_type scalar_type; | ||||
|   typedef typename vobj::vector_type vector_type; | ||||
|    | ||||
|   GridBase *FullGrid  = lhs.Grid(); | ||||
|   | ||||
| @@ -23,7 +23,7 @@ unsigned int nextPow2(Iterator x) { | ||||
| } | ||||
|  | ||||
| template <class Iterator> | ||||
| int getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator &threads, Iterator &blocks) { | ||||
| void getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator &threads, Iterator &blocks) { | ||||
|    | ||||
|   int device; | ||||
| #ifdef GRID_CUDA | ||||
| @@ -37,13 +37,13 @@ int getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator & | ||||
|   Iterator sharedMemPerBlock   = gpu_props[device].sharedMemPerBlock; | ||||
|   Iterator maxThreadsPerBlock  = gpu_props[device].maxThreadsPerBlock; | ||||
|   Iterator multiProcessorCount = gpu_props[device].multiProcessorCount; | ||||
|   /*   | ||||
|    | ||||
|   std::cout << GridLogDebug << "GPU has:" << std::endl; | ||||
|   std::cout << GridLogDebug << "\twarpSize            = " << warpSize << std::endl; | ||||
|   std::cout << GridLogDebug << "\tsharedMemPerBlock   = " << sharedMemPerBlock << std::endl; | ||||
|   std::cout << GridLogDebug << "\tmaxThreadsPerBlock  = " << maxThreadsPerBlock << std::endl; | ||||
|   std::cout << GridLogDebug << "\tmultiProcessorCount = " << multiProcessorCount << std::endl; | ||||
|   */   | ||||
|    | ||||
|   if (warpSize != WARP_SIZE) { | ||||
|     std::cout << GridLogError << "The warp size of the GPU in use does not match the warp size set when compiling Grid." << std::endl; | ||||
|     exit(EXIT_FAILURE); | ||||
| @@ -53,12 +53,12 @@ int getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator & | ||||
|   threads = warpSize; | ||||
|   if ( threads*sizeofsobj > sharedMemPerBlock ) { | ||||
|     std::cout << GridLogError << "The object is too large for the shared memory." << std::endl; | ||||
|     return 0; | ||||
|     exit(EXIT_FAILURE); | ||||
|   } | ||||
|   while( 2*threads*sizeofsobj < sharedMemPerBlock && 2*threads <= maxThreadsPerBlock ) threads *= 2; | ||||
|   // keep all the streaming multiprocessors busy | ||||
|   blocks = nextPow2(multiProcessorCount); | ||||
|   return 1; | ||||
|    | ||||
| } | ||||
|  | ||||
| template <class sobj, class Iterator> | ||||
| @@ -198,7 +198,7 @@ __global__ void reduceKernel(const vobj *lat, sobj *buffer, Iterator n) { | ||||
| // Possibly promote to double and sum | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_gpu_small(const vobj *lat, Integer osites)  | ||||
| inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites)  | ||||
| { | ||||
|   typedef typename vobj::scalar_objectD sobj; | ||||
|   typedef decltype(lat) Iterator; | ||||
| @@ -207,77 +207,17 @@ inline typename vobj::scalar_objectD sumD_gpu_small(const vobj *lat, Integer osi | ||||
|   Integer size = osites*nsimd; | ||||
|  | ||||
|   Integer numThreads, numBlocks; | ||||
|   int ok = getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks); | ||||
|   assert(ok); | ||||
|  | ||||
|   getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks); | ||||
|   Integer smemSize = numThreads * sizeof(sobj); | ||||
|   // Move out of UVM | ||||
|   // Turns out I had messed up the synchronise after move to compute stream | ||||
|   // as running this on the default stream fools the synchronise | ||||
| #undef UVM_BLOCK_BUFFER   | ||||
| #ifndef UVM_BLOCK_BUFFER   | ||||
|   commVector<sobj> buffer(numBlocks); | ||||
|   sobj *buffer_v = &buffer[0]; | ||||
|   sobj result; | ||||
|   reduceKernel<<< numBlocks, numThreads, smemSize, computeStream >>>(lat, buffer_v, size); | ||||
|   accelerator_barrier(); | ||||
|   acceleratorCopyFromDevice(buffer_v,&result,sizeof(result)); | ||||
| #else | ||||
|  | ||||
|   Vector<sobj> buffer(numBlocks); | ||||
|   sobj *buffer_v = &buffer[0]; | ||||
|   sobj result; | ||||
|   reduceKernel<<< numBlocks, numThreads, smemSize, computeStream >>>(lat, buffer_v, size); | ||||
|    | ||||
|   reduceKernel<<< numBlocks, numThreads, smemSize >>>(lat, buffer_v, size); | ||||
|   accelerator_barrier(); | ||||
|   result = *buffer_v; | ||||
| #endif | ||||
|   auto result = buffer_v[0]; | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_gpu_large(const vobj *lat, Integer osites) | ||||
| { | ||||
|   typedef typename vobj::vector_type  vector; | ||||
|   typedef typename vobj::scalar_typeD scalarD; | ||||
|   typedef typename vobj::scalar_objectD sobj; | ||||
|   sobj ret; | ||||
|   scalarD *ret_p = (scalarD *)&ret; | ||||
|    | ||||
|   const int words = sizeof(vobj)/sizeof(vector); | ||||
|  | ||||
|   Vector<vector> buffer(osites); | ||||
|   vector *dat = (vector *)lat; | ||||
|   vector *buf = &buffer[0]; | ||||
|   iScalar<vector> *tbuf =(iScalar<vector> *)  &buffer[0]; | ||||
|   for(int w=0;w<words;w++) { | ||||
|  | ||||
|     accelerator_for(ss,osites,1,{ | ||||
| 	buf[ss] = dat[ss*words+w]; | ||||
|       }); | ||||
|        | ||||
|     ret_p[w] = sumD_gpu_small(tbuf,osites); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites) | ||||
| { | ||||
|   typedef typename vobj::scalar_objectD sobj; | ||||
|   sobj ret; | ||||
|    | ||||
|   Integer nsimd= vobj::Nsimd(); | ||||
|   Integer size = osites*nsimd; | ||||
|   Integer numThreads, numBlocks; | ||||
|   int ok = getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks); | ||||
|    | ||||
|   if ( ok ) { | ||||
|     ret = sumD_gpu_small(lat,osites); | ||||
|   } else { | ||||
|     ret = sumD_gpu_large(lat,osites); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Return as same precision as input performing reduction in double precision though | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -290,13 +230,6 @@ inline typename vobj::scalar_object sum_gpu(const vobj *lat, Integer osites) | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_object sum_gpu_large(const vobj *lat, Integer osites) | ||||
| { | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   sobj result; | ||||
|   result = sumD_gpu_large(lat,osites); | ||||
|   return result; | ||||
| } | ||||
|  | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -1,125 +0,0 @@ | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Possibly promote to double and sum | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_gpu_tensor(const vobj *lat, Integer osites)  | ||||
| { | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   typedef typename vobj::scalar_objectD sobjD; | ||||
|   sobj *mysum =(sobj *) malloc_shared(sizeof(sobj),*theGridAccelerator); | ||||
|   sobj identity; zeroit(identity); | ||||
|   sobj ret ;  | ||||
|  | ||||
|   Integer nsimd= vobj::Nsimd(); | ||||
|    | ||||
|   theGridAccelerator->submit([&](cl::sycl::handler &cgh) { | ||||
|      auto Reduction = cl::sycl::reduction(mysum,identity,std::plus<>()); | ||||
|      cgh.parallel_for(cl::sycl::range<1>{osites}, | ||||
| 		      Reduction, | ||||
| 		      [=] (cl::sycl::id<1> item, auto &sum) { | ||||
|       auto osite   = item[0]; | ||||
|       sum +=Reduce(lat[osite]); | ||||
|      }); | ||||
|    }); | ||||
|   theGridAccelerator->wait(); | ||||
|   ret = mysum[0]; | ||||
|   free(mysum,*theGridAccelerator); | ||||
|   sobjD dret; convertType(dret,ret); | ||||
|   return dret; | ||||
| } | ||||
|  | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_gpu_large(const vobj *lat, Integer osites) | ||||
| { | ||||
|   return sumD_gpu_tensor(lat,osites); | ||||
| } | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_gpu_small(const vobj *lat, Integer osites) | ||||
| { | ||||
|   return sumD_gpu_large(lat,osites); | ||||
| } | ||||
|  | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites) | ||||
| { | ||||
|   return sumD_gpu_large(lat,osites); | ||||
| } | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // Return as same precision as input performing reduction in double precision though | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_object sum_gpu(const vobj *lat, Integer osites)  | ||||
| { | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   sobj result; | ||||
|   result = sumD_gpu(lat,osites); | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_object sum_gpu_large(const vobj *lat, Integer osites) | ||||
| { | ||||
|   typedef typename vobj::scalar_object sobj; | ||||
|   sobj result; | ||||
|   result = sumD_gpu_large(lat,osites); | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|  | ||||
| /* | ||||
| template<class Double> Double svm_reduce(Double *vec,uint64_t L) | ||||
| { | ||||
|   Double sumResult; zeroit(sumResult); | ||||
|   Double *d_sum =(Double *)cl::sycl::malloc_shared(sizeof(Double),*theGridAccelerator); | ||||
|   Double identity;  zeroit(identity); | ||||
|   theGridAccelerator->submit([&](cl::sycl::handler &cgh) { | ||||
|      auto Reduction = cl::sycl::reduction(d_sum,identity,std::plus<>()); | ||||
|      cgh.parallel_for(cl::sycl::range<1>{L}, | ||||
| 		      Reduction, | ||||
| 		      [=] (cl::sycl::id<1> index, auto &sum) { | ||||
| 	 sum +=vec[index]; | ||||
|      }); | ||||
|    }); | ||||
|   theGridAccelerator->wait(); | ||||
|   Double ret = d_sum[0]; | ||||
|   free(d_sum,*theGridAccelerator); | ||||
|   std::cout << " svm_reduce finished "<<L<<" sites sum = " << ret <<std::endl; | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| template <class vobj> | ||||
| inline typename vobj::scalar_objectD sumD_gpu_repack(const vobj *lat, Integer osites) | ||||
| { | ||||
|   typedef typename vobj::vector_type  vector; | ||||
|   typedef typename vobj::scalar_type  scalar; | ||||
|  | ||||
|   typedef typename vobj::scalar_typeD scalarD; | ||||
|   typedef typename vobj::scalar_objectD sobjD; | ||||
|  | ||||
|   sobjD ret; | ||||
|   scalarD *ret_p = (scalarD *)&ret; | ||||
|    | ||||
|   const int nsimd = vobj::Nsimd(); | ||||
|   const int words = sizeof(vobj)/sizeof(vector); | ||||
|  | ||||
|   Vector<scalar> buffer(osites*nsimd); | ||||
|   scalar *buf = &buffer[0]; | ||||
|   vector *dat = (vector *)lat; | ||||
|  | ||||
|   for(int w=0;w<words;w++) { | ||||
|  | ||||
|     accelerator_for(ss,osites,nsimd,{ | ||||
| 	int lane = acceleratorSIMTlane(nsimd); | ||||
| 	buf[ss*nsimd+lane] = dat[ss*words+w].getlane(lane); | ||||
|     }); | ||||
|     //Precision change at this point is to late to gain precision | ||||
|     ret_p[w] = svm_reduce(buf,nsimd*osites); | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
| */ | ||||
| @@ -32,8 +32,9 @@ | ||||
| #include <random> | ||||
|  | ||||
| #ifdef RNG_SITMO | ||||
| #include <Grid/sitmo_rng/sitmo_prng_engine.hpp> | ||||
| #include <Grid/random/sitmo_prng_engine.hpp> | ||||
| #endif  | ||||
| #include <Grid/random/gaussian.h> | ||||
|  | ||||
| #if defined(RNG_SITMO) | ||||
| #define RNG_FAST_DISCARD | ||||
| @@ -142,8 +143,8 @@ public: | ||||
|  | ||||
|   std::vector<RngEngine>                             _generators; | ||||
|   std::vector<std::uniform_real_distribution<RealD> > _uniform; | ||||
|   std::vector<std::normal_distribution<RealD> >       _gaussian; | ||||
|   std::vector<std::discrete_distribution<int32_t> >   _bernoulli; | ||||
|   std::vector<Grid::gaussian_distribution<RealD> >       _gaussian; | ||||
|   //  std::vector<std::discrete_distribution<int32_t> >   _bernoulli; | ||||
|   std::vector<std::uniform_int_distribution<uint32_t> > _uid; | ||||
|  | ||||
|   /////////////////////// | ||||
| @@ -243,8 +244,8 @@ public: | ||||
|   GridSerialRNG() : GridRNGbase() { | ||||
|     _generators.resize(1); | ||||
|     _uniform.resize(1,std::uniform_real_distribution<RealD>{0,1}); | ||||
|     _gaussian.resize(1,std::normal_distribution<RealD>(0.0,1.0) ); | ||||
|     _bernoulli.resize(1,std::discrete_distribution<int32_t>{1,1}); | ||||
|     _gaussian.resize(1,gaussian_distribution<RealD>(0.0,1.0) ); | ||||
|     //    _bernoulli.resize(1,std::discrete_distribution<int32_t>{1,1}); | ||||
|     _uid.resize(1,std::uniform_int_distribution<uint32_t>() ); | ||||
|   } | ||||
|  | ||||
| @@ -357,8 +358,8 @@ public: | ||||
|  | ||||
|     _generators.resize(_vol); | ||||
|     _uniform.resize(_vol,std::uniform_real_distribution<RealD>{0,1}); | ||||
|     _gaussian.resize(_vol,std::normal_distribution<RealD>(0.0,1.0) ); | ||||
|     _bernoulli.resize(_vol,std::discrete_distribution<int32_t>{1,1}); | ||||
|     _gaussian.resize(_vol,gaussian_distribution<RealD>(0.0,1.0) ); | ||||
|     //    _bernoulli.resize(_vol,std::discrete_distribution<int32_t>{1,1}); | ||||
|     _uid.resize(_vol,std::uniform_int_distribution<uint32_t>() ); | ||||
|   } | ||||
|  | ||||
| @@ -424,33 +425,9 @@ public: | ||||
|     // MT implementation does not implement fast discard even though | ||||
|     // in principle this is possible | ||||
|     //////////////////////////////////////////////// | ||||
| #if 1 | ||||
|     thread_for( lidx, _grid->lSites(), { | ||||
|  | ||||
| 	int gidx; | ||||
| 	int o_idx; | ||||
| 	int i_idx; | ||||
| 	int rank; | ||||
| 	Coordinate pcoor; | ||||
| 	Coordinate lcoor; | ||||
| 	Coordinate gcoor; | ||||
| 	_grid->LocalIndexToLocalCoor(lidx,lcoor); | ||||
| 	pcoor=_grid->ThisProcessorCoor(); | ||||
| 	_grid->ProcessorCoorLocalCoorToGlobalCoor(pcoor,lcoor,gcoor); | ||||
| 	_grid->GlobalCoorToGlobalIndex(gcoor,gidx); | ||||
|  | ||||
| 	_grid->GlobalCoorToRankIndex(rank,o_idx,i_idx,gcoor); | ||||
|  | ||||
| 	assert(rank == _grid->ThisRank() ); | ||||
| 	 | ||||
| 	int l_idx=generator_idx(o_idx,i_idx); | ||||
| 	_generators[l_idx] = master_engine; | ||||
| 	Skip(_generators[l_idx],gidx); // Skip to next RNG sequence | ||||
|     }); | ||||
| #else | ||||
|     // Everybody loops over global volume. | ||||
|     thread_for( gidx, _grid->_gsites, { | ||||
|  | ||||
| 	// Where is it? | ||||
| 	int rank; | ||||
| 	int o_idx; | ||||
| @@ -467,7 +444,6 @@ public: | ||||
| 	  Skip(_generators[l_idx],gidx); // Skip to next RNG sequence | ||||
| 	} | ||||
|     }); | ||||
| #endif | ||||
| #else  | ||||
|     //////////////////////////////////////////////////////////////// | ||||
|     // Machine and thread decomposition dependent seeding is efficient | ||||
| @@ -540,11 +516,11 @@ public: | ||||
|  | ||||
| template <class vobj> inline void random(GridParallelRNG &rng,Lattice<vobj> &l)   { rng.fill(l,rng._uniform);  } | ||||
| template <class vobj> inline void gaussian(GridParallelRNG &rng,Lattice<vobj> &l) { rng.fill(l,rng._gaussian); } | ||||
| template <class vobj> inline void bernoulli(GridParallelRNG &rng,Lattice<vobj> &l){ rng.fill(l,rng._bernoulli);} | ||||
| //template <class vobj> inline void bernoulli(GridParallelRNG &rng,Lattice<vobj> &l){ rng.fill(l,rng._bernoulli);} | ||||
|  | ||||
| template <class sobj> inline void random(GridSerialRNG &rng,sobj &l)   { rng.fill(l,rng._uniform  ); } | ||||
| template <class sobj> inline void gaussian(GridSerialRNG &rng,sobj &l) { rng.fill(l,rng._gaussian ); } | ||||
| template <class sobj> inline void bernoulli(GridSerialRNG &rng,sobj &l){ rng.fill(l,rng._bernoulli); } | ||||
| //template <class sobj> inline void bernoulli(GridSerialRNG &rng,sobj &l){ rng.fill(l,rng._bernoulli); } | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| #endif | ||||
|   | ||||
| @@ -194,11 +194,11 @@ accelerator_inline void convertType(vComplexD2 & out, const ComplexD & in) { | ||||
| #endif | ||||
|  | ||||
| accelerator_inline void convertType(vComplexF & out, const vComplexD2 & in) { | ||||
|   precisionChange(out,in); | ||||
|   out.v = Optimization::PrecisionChange::DtoS(in._internal[0].v,in._internal[1].v); | ||||
| } | ||||
|  | ||||
| accelerator_inline void convertType(vComplexD2 & out, const vComplexF & in) { | ||||
|   precisionChange(out,in); | ||||
|   Optimization::PrecisionChange::StoD(in.v,out._internal[0].v,out._internal[1].v); | ||||
| } | ||||
|  | ||||
| template<typename T1,typename T2> | ||||
| @@ -288,36 +288,7 @@ inline void blockProject(Lattice<iVector<CComplex,nbasis > > &coarseData, | ||||
|     blockZAXPY(fineDataRed,ip,Basis[v],fineDataRed);  | ||||
|   } | ||||
| } | ||||
| template<class vobj,class CComplex,int nbasis,class VLattice> | ||||
| inline void batchBlockProject(std::vector<Lattice<iVector<CComplex,nbasis>>> &coarseData, | ||||
|                                const std::vector<Lattice<vobj>> &fineData, | ||||
|                                const VLattice &Basis) | ||||
| { | ||||
|   int NBatch = fineData.size(); | ||||
|   assert(coarseData.size() == NBatch); | ||||
|  | ||||
|   GridBase * fine  = fineData[0].Grid(); | ||||
|   GridBase * coarse= coarseData[0].Grid(); | ||||
|  | ||||
|   Lattice<iScalar<CComplex>> ip(coarse); | ||||
|   std::vector<Lattice<vobj>> fineDataCopy = fineData; | ||||
|  | ||||
|   autoView(ip_, ip, AcceleratorWrite); | ||||
|   for(int v=0;v<nbasis;v++) { | ||||
|     for (int k=0; k<NBatch; k++) { | ||||
|       autoView( coarseData_ , coarseData[k], AcceleratorWrite); | ||||
|       blockInnerProductD(ip,Basis[v],fineDataCopy[k]); // ip = <basis|fine> | ||||
|       accelerator_for( sc, coarse->oSites(), vobj::Nsimd(), { | ||||
|         convertType(coarseData_[sc](v),ip_[sc]); | ||||
|       }); | ||||
|  | ||||
|       // improve numerical stability of projection | ||||
|       // |fine> = |fine> - <basis|fine> |basis> | ||||
|       ip=-ip; | ||||
|       blockZAXPY(fineDataCopy[k],ip,Basis[v],fineDataCopy[k]);  | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<class vobj,class vobj2,class CComplex> | ||||
|   inline void blockZAXPY(Lattice<vobj> &fineZ, | ||||
| @@ -619,26 +590,6 @@ inline void blockPromote(const Lattice<iVector<CComplex,nbasis > > &coarseData, | ||||
| } | ||||
| #endif | ||||
|  | ||||
| template<class vobj,class CComplex,int nbasis,class VLattice> | ||||
| inline void batchBlockPromote(const std::vector<Lattice<iVector<CComplex,nbasis>>> &coarseData, | ||||
|                                std::vector<Lattice<vobj>> &fineData, | ||||
|                                const VLattice &Basis) | ||||
| { | ||||
|   int NBatch = coarseData.size(); | ||||
|   assert(fineData.size() == NBatch); | ||||
|  | ||||
|   GridBase * fine   = fineData[0].Grid(); | ||||
|   GridBase * coarse = coarseData[0].Grid(); | ||||
|   for (int k=0; k<NBatch; k++) | ||||
|     fineData[k]=Zero(); | ||||
|   for (int i=0;i<nbasis;i++) { | ||||
|     for (int k=0; k<NBatch; k++) { | ||||
|       Lattice<iScalar<CComplex>> ip = PeekIndex<0>(coarseData[k],i); | ||||
|       blockZAXPY(fineData[k],ip,Basis[i],fineData[k]); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Useful for precision conversion, or indeed anything where an operator= does a conversion on scalars. | ||||
| // Simd layouts need not match since we use peek/poke Local | ||||
| template<class vobj,class vvobj> | ||||
| @@ -726,10 +677,10 @@ void localCopyRegion(const Lattice<vobj> &From,Lattice<vobj> & To,Coordinate Fro | ||||
|       Integer idx_t = 0; for(int d=0;d<nd;d++) idx_t+=ist[d]*(Tcoor[d]/rdt[d]); | ||||
|       Integer odx_f = 0; for(int d=0;d<nd;d++) odx_f+=osf[d]*(Fcoor[d]%rdf[d]); | ||||
|       Integer odx_t = 0; for(int d=0;d<nd;d++) odx_t+=ost[d]*(Tcoor[d]%rdt[d]); | ||||
|       vector_type * fp = (vector_type *)&f_v[odx_f]; | ||||
|       vector_type * tp = (vector_type *)&t_v[odx_t]; | ||||
|       scalar_type * fp = (scalar_type *)&f_v[odx_f]; | ||||
|       scalar_type * tp = (scalar_type *)&t_v[odx_t]; | ||||
|       for(int w=0;w<words;w++){ | ||||
| 	tp[w].putlane(fp[w].getlane(idx_f),idx_t); | ||||
| 	tp[idx_t+w*Nsimd] = fp[idx_f+w*Nsimd];  // FIXME IF RRII layout, type pun no worke | ||||
|       } | ||||
|     } | ||||
|   }); | ||||
| @@ -1129,80 +1080,11 @@ vectorizeFromRevLexOrdArray( std::vector<sobj> &in, Lattice<vobj> &out) | ||||
|   }); | ||||
| } | ||||
|  | ||||
| //Very fast precision change. Requires in/out objects to reside on same Grid (e.g. by using double2 for the double-precision field) | ||||
| template<class VobjOut, class VobjIn> | ||||
| void precisionChangeFast(Lattice<VobjOut> &out, const Lattice<VobjIn> &in) | ||||
| { | ||||
|   typedef typename VobjOut::vector_type Vout; | ||||
|   typedef typename VobjIn::vector_type Vin; | ||||
|   const int N = sizeof(VobjOut)/sizeof(Vout); | ||||
|   conformable(out.Grid(),in.Grid()); | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   int nsimd = out.Grid()->Nsimd(); | ||||
|   autoView( out_v  , out, AcceleratorWrite); | ||||
|   autoView(  in_v ,   in, AcceleratorRead); | ||||
|   accelerator_for(idx,out.Grid()->oSites(),1,{ | ||||
|       Vout *vout = (Vout *)&out_v[idx]; | ||||
|       Vin  *vin  = (Vin  *)&in_v[idx]; | ||||
|       precisionChange(vout,vin,N); | ||||
|   }); | ||||
| } | ||||
| //Convert a Lattice from one precision to another (original, slow implementation) | ||||
| template<class VobjOut, class VobjIn> | ||||
| void precisionChangeOrig(Lattice<VobjOut> &out, const Lattice<VobjIn> &in) | ||||
| { | ||||
|   assert(out.Grid()->Nd() == in.Grid()->Nd()); | ||||
|   for(int d=0;d<out.Grid()->Nd();d++){ | ||||
|     assert(out.Grid()->FullDimensions()[d] == in.Grid()->FullDimensions()[d]); | ||||
|   } | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   GridBase *in_grid=in.Grid(); | ||||
|   GridBase *out_grid = out.Grid(); | ||||
|  | ||||
|   typedef typename VobjOut::scalar_object SobjOut; | ||||
|   typedef typename VobjIn::scalar_object SobjIn; | ||||
|  | ||||
|   int ndim = out.Grid()->Nd(); | ||||
|   int out_nsimd = out_grid->Nsimd(); | ||||
|   int in_nsimd = in_grid->Nsimd(); | ||||
|   std::vector<Coordinate > out_icoor(out_nsimd); | ||||
|        | ||||
|   for(int lane=0; lane < out_nsimd; lane++){ | ||||
|     out_icoor[lane].resize(ndim); | ||||
|     out_grid->iCoorFromIindex(out_icoor[lane], lane); | ||||
|   } | ||||
|          | ||||
|   std::vector<SobjOut> in_slex_conv(in_grid->lSites()); | ||||
|   unvectorizeToLexOrdArray(in_slex_conv, in); | ||||
|      | ||||
|   autoView( out_v , out, CpuWrite); | ||||
|   thread_for(out_oidx,out_grid->oSites(),{ | ||||
|     Coordinate out_ocoor(ndim); | ||||
|     out_grid->oCoorFromOindex(out_ocoor, out_oidx); | ||||
|  | ||||
|     ExtractPointerArray<SobjOut> ptrs(out_nsimd);       | ||||
|  | ||||
|     Coordinate lcoor(out_grid->Nd()); | ||||
|        | ||||
|     for(int lane=0; lane < out_nsimd; lane++){ | ||||
|       for(int mu=0;mu<ndim;mu++) | ||||
| 	lcoor[mu] = out_ocoor[mu] + out_grid->_rdimensions[mu]*out_icoor[lane][mu]; | ||||
| 	 | ||||
|       int llex; Lexicographic::IndexFromCoor(lcoor, llex, out_grid->_ldimensions); | ||||
|       ptrs[lane] = &in_slex_conv[llex]; | ||||
|     } | ||||
|     merge(out_v[out_oidx], ptrs, 0); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| //The workspace for a precision change operation allowing for the reuse of the mapping to save time on subsequent calls | ||||
| class precisionChangeWorkspace{ | ||||
|   std::pair<Integer,Integer>* fmap_device; //device pointer | ||||
|   //maintain grids for checking | ||||
|   GridBase* _out_grid; | ||||
|   GridBase* _in_grid; | ||||
| public: | ||||
|   precisionChangeWorkspace(GridBase *out_grid, GridBase *in_grid): _out_grid(out_grid), _in_grid(in_grid){ | ||||
|   precisionChangeWorkspace(GridBase *out_grid, GridBase *in_grid){ | ||||
|     //Build a map between the sites and lanes of the output field and the input field as we cannot use the Grids on the device | ||||
|     assert(out_grid->Nd() == in_grid->Nd()); | ||||
|     for(int d=0;d<out_grid->Nd();d++){ | ||||
| @@ -1249,46 +1131,20 @@ public: | ||||
|    | ||||
|   std::pair<Integer,Integer> const* getMap() const{ return fmap_device; } | ||||
|  | ||||
|   void checkGrids(GridBase* out, GridBase* in) const{ | ||||
|     conformable(out, _out_grid); | ||||
|     conformable(in, _in_grid); | ||||
|   } | ||||
|    | ||||
|   ~precisionChangeWorkspace(){ | ||||
|     acceleratorFreeDevice(fmap_device); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|  | ||||
| //We would like to use precisionChangeFast when possible. However usage of this requires the Grids to be the same (runtime check) | ||||
| //*and* the precisionChange(VobjOut::vector_type, VobjIn, int) function to be defined for the types; this requires an extra compile-time check which we do using some SFINAE trickery | ||||
| template<class VobjOut, class VobjIn> | ||||
| auto _precisionChangeFastWrap(Lattice<VobjOut> &out, const Lattice<VobjIn> &in, int dummy)->decltype( precisionChange( ((typename VobjOut::vector_type*)0), ((typename VobjIn::vector_type*)0), 1), int()){ | ||||
|   if(out.Grid() == in.Grid()){ | ||||
|     precisionChangeFast(out,in); | ||||
|     return 1; | ||||
|   }else{ | ||||
|     return 0; | ||||
|   } | ||||
| } | ||||
| template<class VobjOut, class VobjIn> | ||||
| int _precisionChangeFastWrap(Lattice<VobjOut> &out, const Lattice<VobjIn> &in, long dummy){ //note long here is intentional; it means the above is preferred if available | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| //Convert a lattice of one precision to another. Much faster than original implementation but requires a pregenerated workspace | ||||
| //which contains the mapping data. | ||||
| //Convert a lattice of one precision to another. The input workspace contains the mapping data. | ||||
| template<class VobjOut, class VobjIn> | ||||
| void precisionChange(Lattice<VobjOut> &out, const Lattice<VobjIn> &in, const precisionChangeWorkspace &workspace){ | ||||
|   if(_precisionChangeFastWrap(out,in,0)) return; | ||||
|    | ||||
|   static_assert( std::is_same<typename VobjOut::scalar_typeD, typename VobjIn::scalar_typeD>::value == 1, "precisionChange: tensor types must be the same" ); //if tensor types are same the DoublePrecision type must be the same | ||||
|   static_assert( std::is_same<typename VobjOut::DoublePrecision, typename VobjIn::DoublePrecision>::value == 1, "copyLane: tensor types must be the same" ); //if tensor types are same the DoublePrecision type must be the same | ||||
|  | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   constexpr int Nsimd_out = VobjOut::Nsimd(); | ||||
|  | ||||
|   workspace.checkGrids(out.Grid(),in.Grid()); | ||||
|   std::pair<Integer,Integer> const* fmap_device = workspace.getMap(); | ||||
|  | ||||
|   //Do the copy/precision change | ||||
| @@ -1305,18 +1161,15 @@ void precisionChange(Lattice<VobjOut> &out, const Lattice<VobjIn> &in, const pre | ||||
|     }); | ||||
| } | ||||
|  | ||||
| //Convert a Lattice from one precision to another. Much faster than original implementation but slower than precisionChangeFast | ||||
| //or precisionChange called with pregenerated workspace, as it needs to internally generate the workspace on the host and copy to device | ||||
| //Convert a Lattice from one precision to another | ||||
| //Generate the workspace in place; if multiple calls with the same mapping are performed, consider pregenerating the workspace and reusing | ||||
| template<class VobjOut, class VobjIn> | ||||
| void precisionChange(Lattice<VobjOut> &out, const Lattice<VobjIn> &in){ | ||||
|   if(_precisionChangeFastWrap(out,in,0)) return;    | ||||
|   precisionChangeWorkspace workspace(out.Grid(), in.Grid()); | ||||
|   precisionChange(out, in, workspace); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // Communicate between grids | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -65,38 +65,30 @@ GridLogger GridLogSolver (1, "Solver", GridLogColours, "NORMAL"); | ||||
| GridLogger GridLogError  (1, "Error" , GridLogColours, "RED"); | ||||
| GridLogger GridLogWarning(1, "Warning", GridLogColours, "YELLOW"); | ||||
| GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL"); | ||||
| GridLogger GridLogMemory (1, "Memory", GridLogColours, "NORMAL"); | ||||
| GridLogger GridLogTracing(1, "Tracing", GridLogColours, "NORMAL"); | ||||
| GridLogger GridLogDebug  (1, "Debug", GridLogColours, "PURPLE"); | ||||
| GridLogger GridLogPerformance(1, "Performance", GridLogColours, "GREEN"); | ||||
| GridLogger GridLogDslash     (1, "Dslash", GridLogColours, "BLUE"); | ||||
| GridLogger GridLogIterative  (1, "Iterative", GridLogColours, "BLUE"); | ||||
| GridLogger GridLogIntegrator (1, "Integrator", GridLogColours, "BLUE"); | ||||
| GridLogger GridLogHMC (1, "HMC", GridLogColours, "BLUE"); | ||||
|  | ||||
| void GridLogConfigure(std::vector<std::string> &logstreams) { | ||||
|   GridLogError.Active(1); | ||||
|   GridLogError.Active(0); | ||||
|   GridLogWarning.Active(0); | ||||
|   GridLogMessage.Active(1); // at least the messages should be always on | ||||
|   GridLogMemory.Active(0);  | ||||
|   GridLogTracing.Active(0);  | ||||
|   GridLogIterative.Active(0); | ||||
|   GridLogDebug.Active(0); | ||||
|   GridLogPerformance.Active(0); | ||||
|   GridLogDslash.Active(0); | ||||
|   GridLogIntegrator.Active(1); | ||||
|   GridLogColours.Active(0); | ||||
|   GridLogHMC.Active(1); | ||||
|  | ||||
|   for (int i = 0; i < logstreams.size(); i++) { | ||||
|     if (logstreams[i] == std::string("Tracing"))     GridLogTracing.Active(1); | ||||
|     if (logstreams[i] == std::string("Memory"))      GridLogMemory.Active(1); | ||||
|     if (logstreams[i] == std::string("Error"))       GridLogError.Active(1); | ||||
|     if (logstreams[i] == std::string("Warning"))     GridLogWarning.Active(1); | ||||
|     if (logstreams[i] == std::string("NoMessage"))   GridLogMessage.Active(0); | ||||
|     if (logstreams[i] == std::string("Iterative"))   GridLogIterative.Active(1); | ||||
|     if (logstreams[i] == std::string("Debug"))       GridLogDebug.Active(1); | ||||
|     if (logstreams[i] == std::string("Performance")) GridLogPerformance.Active(1); | ||||
|     if (logstreams[i] == std::string("Dslash"))      GridLogDslash.Active(1); | ||||
|     if (logstreams[i] == std::string("NoIntegrator"))  GridLogIntegrator.Active(0); | ||||
|     if (logstreams[i] == std::string("NoHMC"))         GridLogHMC.Active(0); | ||||
|     if (logstreams[i] == std::string("Colours"))     GridLogColours.Active(1); | ||||
|   | ||||
| @@ -138,8 +138,7 @@ public: | ||||
|         stream << std::setw(log.topWidth); | ||||
|       } | ||||
|       stream << log.topName << log.background()<< " : "; | ||||
|       //      stream << log.colour() <<  std::left; | ||||
|       stream <<  std::left; | ||||
|       stream << log.colour() <<  std::left; | ||||
|       if (log.chanWidth > 0) | ||||
|       { | ||||
|         stream << std::setw(log.chanWidth); | ||||
| @@ -154,9 +153,9 @@ public: | ||||
| 	stream << log.evidence() | ||||
| 	       << now	       << log.background() << " : " ; | ||||
|       } | ||||
|       //      stream << log.colour(); | ||||
|       stream <<  std::right; | ||||
|       stream << log.colour(); | ||||
|       stream.flags(f); | ||||
|  | ||||
|       return stream; | ||||
|     } else {  | ||||
|       return devnull; | ||||
| @@ -181,12 +180,9 @@ extern GridLogger GridLogWarning; | ||||
| extern GridLogger GridLogMessage; | ||||
| extern GridLogger GridLogDebug  ; | ||||
| extern GridLogger GridLogPerformance; | ||||
| extern GridLogger GridLogDslash; | ||||
| extern GridLogger GridLogIterative  ; | ||||
| extern GridLogger GridLogIntegrator  ; | ||||
| extern GridLogger GridLogHMC; | ||||
| extern GridLogger GridLogMemory; | ||||
| extern GridLogger GridLogTracing; | ||||
| extern Colours    GridLogColours; | ||||
|  | ||||
| std::string demangle(const char* name) ; | ||||
|   | ||||
| @@ -31,7 +31,6 @@ directory | ||||
| #include <fstream> | ||||
| #include <iomanip> | ||||
| #include <iostream> | ||||
| #include <string> | ||||
| #include <map> | ||||
|  | ||||
| #include <pwd.h> | ||||
| @@ -655,8 +654,7 @@ class IldgWriter : public ScidacWriter { | ||||
|     // Fill ILDG header data struct | ||||
|     ////////////////////////////////////////////////////// | ||||
|     ildgFormat ildgfmt ; | ||||
|     const std::string stNC = std::to_string( Nc ) ; | ||||
|     ildgfmt.field          = std::string("su"+stNC+"gauge"); | ||||
|     ildgfmt.field     = std::string("su3gauge"); | ||||
|  | ||||
|     if ( format == std::string("IEEE32BIG") ) {  | ||||
|       ildgfmt.precision = 32; | ||||
| @@ -873,8 +871,7 @@ class IldgReader : public GridLimeReader { | ||||
|     } else {  | ||||
|  | ||||
|       assert(found_ildgFormat); | ||||
|       const std::string stNC = std::to_string( Nc ) ; | ||||
|       assert ( ildgFormat_.field == std::string("su"+stNC+"gauge") ); | ||||
|       assert ( ildgFormat_.field == std::string("su3gauge") ); | ||||
|  | ||||
|       /////////////////////////////////////////////////////////////////////////////////////// | ||||
|       // Populate our Grid metadata as best we can | ||||
| @@ -882,7 +879,7 @@ class IldgReader : public GridLimeReader { | ||||
|  | ||||
|       std::ostringstream vers; vers << ildgFormat_.version; | ||||
|       FieldMetaData_.hdr_version = vers.str(); | ||||
|       FieldMetaData_.data_type = std::string("4D_SU"+stNC+"_GAUGE_"+stNC+"x"+stNC); | ||||
|       FieldMetaData_.data_type = std::string("4D_SU3_GAUGE_3X3"); | ||||
|  | ||||
|       FieldMetaData_.nd=4; | ||||
|       FieldMetaData_.dimension.resize(4); | ||||
|   | ||||
| @@ -6,8 +6,8 @@ | ||||
|  | ||||
|     Copyright (C) 2015 | ||||
|  | ||||
|  | ||||
|     Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: Jamie Hudspith <renwick.james.hudspth@gmail.com> | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
| @@ -203,24 +203,20 @@ template<> inline void PrepareMetaData<vLorentzColourMatrixD>(Lattice<vLorentzCo | ||||
| ////////////////////////////////////////////////////////////////////// | ||||
| inline void reconstruct3(LorentzColourMatrix & cm) | ||||
| { | ||||
|   assert( Nc < 4 && Nc > 1 ) ; | ||||
|   const int x=0; | ||||
|   const int y=1; | ||||
|   const int z=2; | ||||
|   for(int mu=0;mu<Nd;mu++){ | ||||
|     #if Nc == 2 | ||||
|       cm(mu)()(1,0) = -adj(cm(mu)()(0,y)) ; | ||||
|       cm(mu)()(1,1) =  adj(cm(mu)()(0,x)) ; | ||||
|     #else | ||||
|       const int x=0 , y=1 , z=2 ; // a little disinenuous labelling | ||||
|     cm(mu)()(2,x) = adj(cm(mu)()(0,y)*cm(mu)()(1,z)-cm(mu)()(0,z)*cm(mu)()(1,y)); //x= yz-zy | ||||
|     cm(mu)()(2,y) = adj(cm(mu)()(0,z)*cm(mu)()(1,x)-cm(mu)()(0,x)*cm(mu)()(1,z)); //y= zx-xz | ||||
|     cm(mu)()(2,z) = adj(cm(mu)()(0,x)*cm(mu)()(1,y)-cm(mu)()(0,y)*cm(mu)()(1,x)); //z= xy-yx | ||||
|     #endif | ||||
|   } | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // Some data types for intermediate storage | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| template<typename vtype> using iLorentzColour2x3 = iVector<iVector<iVector<vtype, Nc>, Nc-1>, Nd >; | ||||
| template<typename vtype> using iLorentzColour2x3 = iVector<iVector<iVector<vtype, Nc>, 2>, Nd >; | ||||
|  | ||||
| typedef iLorentzColour2x3<Complex>  LorentzColour2x3; | ||||
| typedef iLorentzColour2x3<ComplexF> LorentzColour2x3F; | ||||
| @@ -282,6 +278,7 @@ struct GaugeSimpleMunger{ | ||||
|  | ||||
| template <class fobj, class sobj> | ||||
| struct GaugeSimpleUnmunger { | ||||
|  | ||||
|   void operator()(sobj &in, fobj &out) { | ||||
|     for (int mu = 0; mu < Nd; mu++) { | ||||
|       for (int i = 0; i < Nc; i++) { | ||||
| @@ -320,8 +317,8 @@ template<class fobj,class sobj> | ||||
| struct Gauge3x2munger{ | ||||
|   void operator() (fobj &in,sobj &out){ | ||||
|     for(int mu=0;mu<Nd;mu++){ | ||||
|       for(int i=0;i<Nc-1;i++){ | ||||
| 	for(int j=0;j<Nc;j++){ | ||||
|       for(int i=0;i<2;i++){ | ||||
| 	for(int j=0;j<3;j++){ | ||||
| 	  out(mu)()(i,j) = in(mu)(i)(j); | ||||
| 	}} | ||||
|     } | ||||
| @@ -333,8 +330,8 @@ template<class fobj,class sobj> | ||||
| struct Gauge3x2unmunger{ | ||||
|   void operator() (sobj &in,fobj &out){ | ||||
|     for(int mu=0;mu<Nd;mu++){ | ||||
|       for(int i=0;i<Nc-1;i++){ | ||||
| 	for(int j=0;j<Nc;j++){ | ||||
|       for(int i=0;i<2;i++){ | ||||
| 	for(int j=0;j<3;j++){ | ||||
| 	  out(mu)(i)(j) = in(mu)()(i,j); | ||||
| 	}} | ||||
|     } | ||||
|   | ||||
| @@ -9,7 +9,6 @@ | ||||
|     Author: Matt Spraggs <matthew.spraggs@gmail.com> | ||||
|     Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: Jamie Hudspith <renwick.james.hudspth@gmail.com> | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
| @@ -31,8 +30,6 @@ | ||||
| #ifndef GRID_NERSC_IO_H | ||||
| #define GRID_NERSC_IO_H | ||||
|  | ||||
| #include <string> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| using namespace Grid; | ||||
| @@ -150,17 +147,15 @@ public: | ||||
|  | ||||
|     std::string format(header.floating_point); | ||||
|  | ||||
|     const int ieee32big = (format == std::string("IEEE32BIG")); | ||||
|     const int ieee32    = (format == std::string("IEEE32")); | ||||
|     const int ieee64big = (format == std::string("IEEE64BIG")); | ||||
|     const int ieee64    = (format == std::string("IEEE64") || \ | ||||
| 			   format == std::string("IEEE64LITTLE")); | ||||
|     int ieee32big = (format == std::string("IEEE32BIG")); | ||||
|     int ieee32    = (format == std::string("IEEE32")); | ||||
|     int ieee64big = (format == std::string("IEEE64BIG")); | ||||
|     int ieee64    = (format == std::string("IEEE64") || format == std::string("IEEE64LITTLE")); | ||||
|  | ||||
|     uint32_t nersc_csum,scidac_csuma,scidac_csumb; | ||||
|     // depending on datatype, set up munger; | ||||
|     // munger is a function of <floating point, Real, data_type> | ||||
|     const std::string stNC = std::to_string( Nc ) ; | ||||
|     if ( header.data_type == std::string("4D_SU"+stNC+"_GAUGE") ) { | ||||
|     if ( header.data_type == std::string("4D_SU3_GAUGE") ) { | ||||
|       if ( ieee32 || ieee32big ) { | ||||
| 	BinaryIO::readLatticeObject<vLorentzColourMatrixD, LorentzColour2x3F>  | ||||
| 	  (Umu,file,Gauge3x2munger<LorentzColour2x3F,LorentzColourMatrix>(), offset,format, | ||||
| @@ -171,7 +166,7 @@ public: | ||||
| 	  (Umu,file,Gauge3x2munger<LorentzColour2x3D,LorentzColourMatrix>(),offset,format, | ||||
| 	   nersc_csum,scidac_csuma,scidac_csumb); | ||||
|       } | ||||
|     } else if ( header.data_type == std::string("4D_SU"+stNC+"_GAUGE_"+stNC+"x"+stNC) ) { | ||||
|     } else if ( header.data_type == std::string("4D_SU3_GAUGE_3x3") ) { | ||||
|       if ( ieee32 || ieee32big ) { | ||||
| 	BinaryIO::readLatticeObject<vLorentzColourMatrixD,LorentzColourMatrixF> | ||||
| 	  (Umu,file,GaugeSimpleMunger<LorentzColourMatrixF,LorentzColourMatrix>(),offset,format, | ||||
| @@ -216,29 +211,27 @@ public: | ||||
|   template<class GaugeStats=PeriodicGaugeStatistics> | ||||
|   static inline void writeConfiguration(Lattice<vLorentzColourMatrixD > &Umu, | ||||
| 					std::string file,  | ||||
| 					std::string ens_label = std::string("DWF"), | ||||
| 					std::string ens_id = std::string("UKQCD"), | ||||
| 					unsigned int sequence_number = 1) | ||||
| 					std::string ens_label = std::string("DWF")) | ||||
|   { | ||||
|     writeConfiguration(Umu,file,0,1,ens_label,ens_id,sequence_number); | ||||
|     writeConfiguration(Umu,file,0,1,ens_label); | ||||
|   } | ||||
|   template<class GaugeStats=PeriodicGaugeStatistics> | ||||
|   static inline void writeConfiguration(Lattice<vLorentzColourMatrixD > &Umu, | ||||
| 					std::string file,  | ||||
| 					int two_row, | ||||
| 					int bits32, | ||||
| 					std::string ens_label = std::string("DWF"), | ||||
| 					std::string ens_id = std::string("UKQCD"), | ||||
| 					unsigned int sequence_number = 1) | ||||
| 					std::string ens_label = std::string("DWF")) | ||||
|   { | ||||
|     typedef vLorentzColourMatrixD vobj; | ||||
|     typedef typename vobj::scalar_object sobj; | ||||
|  | ||||
|     FieldMetaData header; | ||||
|     header.sequence_number = sequence_number; | ||||
|     header.ensemble_id     = ens_id; | ||||
|     /////////////////////////////////////////// | ||||
|     // Following should become arguments | ||||
|     /////////////////////////////////////////// | ||||
|     header.sequence_number = 1; | ||||
|     header.ensemble_id     = std::string("UKQCD"); | ||||
|     header.ensemble_label  = ens_label; | ||||
|     header.hdr_version     = "1.0" ; | ||||
|  | ||||
|     typedef LorentzColourMatrixD fobj3D; | ||||
|     typedef LorentzColour2x3D    fobj2D; | ||||
| @@ -252,14 +245,10 @@ public: | ||||
|  | ||||
|     uint64_t offset; | ||||
|  | ||||
|     // Sod it -- always write NcxNc double | ||||
|     // Sod it -- always write 3x3 double | ||||
|     header.floating_point = std::string("IEEE64BIG"); | ||||
|     const std::string stNC = std::to_string( Nc ) ; | ||||
|     if( two_row ) { | ||||
|       header.data_type = std::string("4D_SU" + stNC + "_GAUGE" ); | ||||
|     } else { | ||||
|       header.data_type = std::string("4D_SU" + stNC + "_GAUGE_" + stNC + "x" + stNC ); | ||||
|     } | ||||
|     header.data_type      = std::string("4D_SU3_GAUGE_3x3"); | ||||
|     GaugeSimpleUnmunger<fobj3D,sobj> munge; | ||||
|     if ( grid->IsBoss() ) {  | ||||
|       truncate(file); | ||||
|       offset = writeHeader(header,file); | ||||
| @@ -267,15 +256,8 @@ public: | ||||
|     grid->Broadcast(0,(void *)&offset,sizeof(offset)); | ||||
|  | ||||
|     uint32_t nersc_csum,scidac_csuma,scidac_csumb; | ||||
|     if( two_row ) { | ||||
|       Gauge3x2unmunger<fobj2D,sobj> munge; | ||||
|       BinaryIO::writeLatticeObject<vobj,fobj2D>(Umu,file,munge,offset,header.floating_point, | ||||
| 						nersc_csum,scidac_csuma,scidac_csumb); | ||||
|     } else { | ||||
|       GaugeSimpleUnmunger<fobj3D,sobj> munge; | ||||
|     BinaryIO::writeLatticeObject<vobj,fobj3D>(Umu,file,munge,offset,header.floating_point, | ||||
| 					      nersc_csum,scidac_csuma,scidac_csumb); | ||||
|     } | ||||
|     header.checksum = nersc_csum; | ||||
|     if ( grid->IsBoss() ) {  | ||||
|       writeHeader(header,file); | ||||
| @@ -308,6 +290,7 @@ public: | ||||
|     MachineCharacteristics(header); | ||||
|  | ||||
| 	uint64_t offset; | ||||
|    | ||||
| #ifdef RNG_RANLUX | ||||
|     header.floating_point = std::string("UINT64"); | ||||
|     header.data_type      = std::string("RANLUX48"); | ||||
|   | ||||
| @@ -27,12 +27,9 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #include <Grid/GridCore.h> | ||||
|  | ||||
| #include <Grid/perfmon/Timer.h> | ||||
| #include <Grid/perfmon/PerfCount.h> | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| GridTimePoint theProgramStart = GridClock::now(); | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #define CacheControl(L,O,R) ((PERF_COUNT_HW_CACHE_##L)|(PERF_COUNT_HW_CACHE_OP_##O<<8)| (PERF_COUNT_HW_CACHE_RESULT_##R<<16)) | ||||
| #define RawConfig(A,B) (A<<8|B) | ||||
|   | ||||
| @@ -30,12 +30,6 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| #ifndef GRID_PERFCOUNT_H | ||||
| #define GRID_PERFCOUNT_H | ||||
|  | ||||
|  | ||||
| #ifndef __SSC_START | ||||
| #define __SSC_START | ||||
| #define __SSC_STOP | ||||
| #endif | ||||
|  | ||||
| #include <sys/time.h> | ||||
| #include <ctime> | ||||
| #include <chrono> | ||||
| @@ -78,9 +72,17 @@ static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, | ||||
| inline uint64_t cyclecount(void){  | ||||
|   return 0; | ||||
| } | ||||
| #define __SSC_MARK(mark) __asm__ __volatile__ ("movl %0, %%ebx; .byte 0x64, 0x67, 0x90 " ::"i"(mark):"%ebx") | ||||
| #define __SSC_STOP  __SSC_MARK(0x110) | ||||
| #define __SSC_START __SSC_MARK(0x111) | ||||
|  | ||||
|  | ||||
| #else | ||||
|  | ||||
| #define __SSC_MARK(mark)  | ||||
| #define __SSC_STOP   | ||||
| #define __SSC_START  | ||||
|  | ||||
| /* | ||||
|  * cycle counters arch dependent | ||||
|  */ | ||||
|   | ||||
| @@ -35,8 +35,17 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid) | ||||
|  | ||||
| //typedef  std::chrono::system_clock          GridClock; | ||||
| typedef  std::chrono::high_resolution_clock   GridClock; | ||||
| // Dress the output; use std::chrono | ||||
| // C++11 time facilities better? | ||||
| inline double usecond(void) { | ||||
|   struct timeval tv; | ||||
| #ifdef TIMERS_ON | ||||
|   gettimeofday(&tv,NULL); | ||||
| #endif | ||||
|   return 1.0*tv.tv_usec + 1.0e6*tv.tv_sec; | ||||
| } | ||||
|  | ||||
| typedef  std::chrono::system_clock          GridClock; | ||||
| typedef  std::chrono::time_point<GridClock> GridTimePoint; | ||||
|  | ||||
| typedef  std::chrono::seconds               GridSecs; | ||||
| @@ -44,15 +53,6 @@ typedef  std::chrono::milliseconds          GridMillisecs; | ||||
| typedef  std::chrono::microseconds          GridUsecs; | ||||
| typedef  std::chrono::microseconds          GridTime; | ||||
|  | ||||
| extern GridTimePoint theProgramStart; | ||||
| // Dress the output; use std::chrono | ||||
| // C++11 time facilities better? | ||||
| inline double usecond(void) { | ||||
|   auto usecs = std::chrono::duration_cast<GridUsecs>(GridClock::now()-theProgramStart);  | ||||
|   return 1.0*usecs.count(); | ||||
| } | ||||
|  | ||||
|  | ||||
| inline std::ostream& operator<< (std::ostream & stream, const GridSecs & time) | ||||
| { | ||||
|   stream << time.count()<<" s"; | ||||
|   | ||||
| @@ -1,70 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #ifdef GRID_TRACING_NVTX | ||||
| #include <nvToolsExt.h> | ||||
| class GridTracer { | ||||
| public: | ||||
|   GridTracer(const char* name) { | ||||
|     nvtxRangePushA(name); | ||||
|   } | ||||
|   ~GridTracer() { | ||||
|     nvtxRangePop(); | ||||
|   } | ||||
| }; | ||||
| inline void tracePush(const char *name) { nvtxRangePushA(name); } | ||||
| inline void tracePop(const char *name) { nvtxRangePop(); } | ||||
| inline int  traceStart(const char *name) {  } | ||||
| inline void traceStop(int ID) {  } | ||||
| #endif | ||||
|  | ||||
| #ifdef GRID_TRACING_ROCTX | ||||
| #include <roctracer/roctx.h> | ||||
| class GridTracer { | ||||
|  public: | ||||
|   GridTracer(const char* name) { | ||||
|     roctxRangePushA(name); | ||||
|     std::cout << "roctxRangePush "<<name<<std::endl; | ||||
|   } | ||||
|   ~GridTracer() { | ||||
|     roctxRangePop(); | ||||
|     std::cout << "roctxRangePop "<<std::endl; | ||||
|   } | ||||
| }; | ||||
| inline void tracePush(const char *name) { roctxRangePushA(name); } | ||||
| inline void tracePop(const char *name) { roctxRangePop(); } | ||||
| inline int  traceStart(const char *name) { roctxRangeStart(name); } | ||||
| inline void traceStop(int ID) { roctxRangeStop(ID); } | ||||
| #endif | ||||
|  | ||||
| #ifdef GRID_TRACING_TIMER | ||||
| class GridTracer { | ||||
|  public: | ||||
|   const char *name; | ||||
|   double elapsed; | ||||
|   GridTracer(const char* _name) { | ||||
|     name = _name; | ||||
|     elapsed=-usecond(); | ||||
|   } | ||||
|   ~GridTracer() { | ||||
|     elapsed+=usecond(); | ||||
|     std::cout << GridLogTracing << name << " took " <<elapsed<< " us" <<std::endl; | ||||
|   } | ||||
| }; | ||||
| inline void tracePush(const char *name) {  } | ||||
| inline void tracePop(const char *name) {  } | ||||
| inline int  traceStart(const char *name) { return 0; } | ||||
| inline void traceStop(int ID) {  } | ||||
| #endif | ||||
|  | ||||
| #ifdef GRID_TRACING_NONE | ||||
| #define GRID_TRACE(name)  | ||||
| inline void tracePush(const char *name) {  } | ||||
| inline void tracePop(const char *name) {  } | ||||
| inline int  traceStart(const char *name) { return 0;  } | ||||
| inline void traceStop(int ID) {  } | ||||
| #else | ||||
| #define GRID_TRACE(name) GridTracer uniq_name_using_macros##__COUNTER__(name); | ||||
| #endif | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -16,12 +16,8 @@ | ||||
|  | ||||
| #ifdef __NVCC__ | ||||
| #pragma push | ||||
| #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ | ||||
| #pragma nv_diag_suppress declared_but_not_referenced // suppress "function was declared but never referenced warning" | ||||
| #else | ||||
| #pragma diag_suppress declared_but_not_referenced // suppress "function was declared but never referenced warning" | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #include "pugixml.h" | ||||
|  | ||||
|   | ||||
| @@ -126,7 +126,6 @@ typedef iSpinMatrix<ComplexD >          SpinMatrixD; | ||||
| typedef iSpinMatrix<vComplex >          vSpinMatrix; | ||||
| typedef iSpinMatrix<vComplexF>          vSpinMatrixF; | ||||
| typedef iSpinMatrix<vComplexD>          vSpinMatrixD; | ||||
| typedef iSpinMatrix<vComplexD2>         vSpinMatrixD2; | ||||
|  | ||||
| // Colour Matrix | ||||
| typedef iColourMatrix<Complex  >        ColourMatrix; | ||||
| @@ -136,7 +135,6 @@ typedef iColourMatrix<ComplexD >        ColourMatrixD; | ||||
| typedef iColourMatrix<vComplex >        vColourMatrix; | ||||
| typedef iColourMatrix<vComplexF>        vColourMatrixF; | ||||
| typedef iColourMatrix<vComplexD>        vColourMatrixD; | ||||
| typedef iColourMatrix<vComplexD2>       vColourMatrixD2; | ||||
|  | ||||
| // SpinColour matrix | ||||
| typedef iSpinColourMatrix<Complex  >    SpinColourMatrix; | ||||
| @@ -146,7 +144,6 @@ typedef iSpinColourMatrix<ComplexD >    SpinColourMatrixD; | ||||
| typedef iSpinColourMatrix<vComplex >    vSpinColourMatrix; | ||||
| typedef iSpinColourMatrix<vComplexF>    vSpinColourMatrixF; | ||||
| typedef iSpinColourMatrix<vComplexD>    vSpinColourMatrixD; | ||||
| typedef iSpinColourMatrix<vComplexD2>   vSpinColourMatrixD2; | ||||
|  | ||||
| // SpinColourSpinColour matrix | ||||
| typedef iSpinColourSpinColourMatrix<Complex  >    SpinColourSpinColourMatrix; | ||||
| @@ -156,7 +153,6 @@ typedef iSpinColourSpinColourMatrix<ComplexD >    SpinColourSpinColourMatrixD; | ||||
| typedef iSpinColourSpinColourMatrix<vComplex >    vSpinColourSpinColourMatrix; | ||||
| typedef iSpinColourSpinColourMatrix<vComplexF>    vSpinColourSpinColourMatrixF; | ||||
| typedef iSpinColourSpinColourMatrix<vComplexD>    vSpinColourSpinColourMatrixD; | ||||
| typedef iSpinColourSpinColourMatrix<vComplexD2>   vSpinColourSpinColourMatrixD2; | ||||
|  | ||||
| // SpinColourSpinColour matrix | ||||
| typedef iSpinColourSpinColourMatrix<Complex  >    SpinColourSpinColourMatrix; | ||||
| @@ -166,7 +162,6 @@ typedef iSpinColourSpinColourMatrix<ComplexD >    SpinColourSpinColourMatrixD; | ||||
| typedef iSpinColourSpinColourMatrix<vComplex >    vSpinColourSpinColourMatrix; | ||||
| typedef iSpinColourSpinColourMatrix<vComplexF>    vSpinColourSpinColourMatrixF; | ||||
| typedef iSpinColourSpinColourMatrix<vComplexD>    vSpinColourSpinColourMatrixD; | ||||
| typedef iSpinColourSpinColourMatrix<vComplexD2>   vSpinColourSpinColourMatrixD2; | ||||
|  | ||||
| // LorentzColour | ||||
| typedef iLorentzColourMatrix<Complex  > LorentzColourMatrix; | ||||
| @@ -176,7 +171,6 @@ typedef iLorentzColourMatrix<ComplexD > LorentzColourMatrixD; | ||||
| typedef iLorentzColourMatrix<vComplex > vLorentzColourMatrix; | ||||
| typedef iLorentzColourMatrix<vComplexF> vLorentzColourMatrixF; | ||||
| typedef iLorentzColourMatrix<vComplexD> vLorentzColourMatrixD; | ||||
| typedef iLorentzColourMatrix<vComplexD2> vLorentzColourMatrixD2; | ||||
|  | ||||
| // DoubleStored gauge field | ||||
| typedef iDoubleStoredColourMatrix<Complex  > DoubleStoredColourMatrix; | ||||
| @@ -186,7 +180,6 @@ typedef iDoubleStoredColourMatrix<ComplexD > DoubleStoredColourMatrixD; | ||||
| typedef iDoubleStoredColourMatrix<vComplex > vDoubleStoredColourMatrix; | ||||
| typedef iDoubleStoredColourMatrix<vComplexF> vDoubleStoredColourMatrixF; | ||||
| typedef iDoubleStoredColourMatrix<vComplexD> vDoubleStoredColourMatrixD; | ||||
| typedef iDoubleStoredColourMatrix<vComplexD2> vDoubleStoredColourMatrixD2; | ||||
|  | ||||
| //G-parity flavour matrix | ||||
| typedef iGparityFlavourMatrix<Complex> GparityFlavourMatrix; | ||||
| @@ -196,7 +189,6 @@ typedef iGparityFlavourMatrix<ComplexD> GparityFlavourMatrixD; | ||||
| typedef iGparityFlavourMatrix<vComplex> vGparityFlavourMatrix; | ||||
| typedef iGparityFlavourMatrix<vComplexF> vGparityFlavourMatrixF; | ||||
| typedef iGparityFlavourMatrix<vComplexD> vGparityFlavourMatrixD; | ||||
| typedef iGparityFlavourMatrix<vComplexD2> vGparityFlavourMatrixD2; | ||||
|  | ||||
|  | ||||
| // Spin vector | ||||
| @@ -207,7 +199,6 @@ typedef iSpinVector<ComplexD>           SpinVectorD; | ||||
| typedef iSpinVector<vComplex >           vSpinVector; | ||||
| typedef iSpinVector<vComplexF>           vSpinVectorF; | ||||
| typedef iSpinVector<vComplexD>           vSpinVectorD; | ||||
| typedef iSpinVector<vComplexD2>          vSpinVectorD2; | ||||
|  | ||||
| // Colour vector | ||||
| typedef iColourVector<Complex >         ColourVector; | ||||
| @@ -217,7 +208,6 @@ typedef iColourVector<ComplexD>         ColourVectorD; | ||||
| typedef iColourVector<vComplex >         vColourVector; | ||||
| typedef iColourVector<vComplexF>         vColourVectorF; | ||||
| typedef iColourVector<vComplexD>         vColourVectorD; | ||||
| typedef iColourVector<vComplexD2>        vColourVectorD2; | ||||
|  | ||||
| // SpinColourVector | ||||
| typedef iSpinColourVector<Complex >     SpinColourVector; | ||||
| @@ -227,7 +217,6 @@ typedef iSpinColourVector<ComplexD>     SpinColourVectorD; | ||||
| typedef iSpinColourVector<vComplex >     vSpinColourVector; | ||||
| typedef iSpinColourVector<vComplexF>     vSpinColourVectorF; | ||||
| typedef iSpinColourVector<vComplexD>     vSpinColourVectorD; | ||||
| typedef iSpinColourVector<vComplexD2>    vSpinColourVectorD2; | ||||
|  | ||||
| // HalfSpin vector | ||||
| typedef iHalfSpinVector<Complex >       HalfSpinVector; | ||||
| @@ -237,7 +226,6 @@ typedef iHalfSpinVector<ComplexD>       HalfSpinVectorD; | ||||
| typedef iHalfSpinVector<vComplex >       vHalfSpinVector; | ||||
| typedef iHalfSpinVector<vComplexF>       vHalfSpinVectorF; | ||||
| typedef iHalfSpinVector<vComplexD>       vHalfSpinVectorD; | ||||
| typedef iHalfSpinVector<vComplexD2>      vHalfSpinVectorD2; | ||||
|  | ||||
| // HalfSpinColour vector | ||||
| typedef iHalfSpinColourVector<Complex > HalfSpinColourVector; | ||||
| @@ -247,7 +235,6 @@ typedef iHalfSpinColourVector<ComplexD> HalfSpinColourVectorD; | ||||
| typedef iHalfSpinColourVector<vComplex > vHalfSpinColourVector; | ||||
| typedef iHalfSpinColourVector<vComplexF> vHalfSpinColourVectorF; | ||||
| typedef iHalfSpinColourVector<vComplexD> vHalfSpinColourVectorD; | ||||
| typedef iHalfSpinColourVector<vComplexD2> vHalfSpinColourVectorD2; | ||||
|  | ||||
| //G-parity flavour vector | ||||
| typedef iGparityFlavourVector<Complex >         GparityFlavourVector; | ||||
| @@ -257,7 +244,7 @@ typedef iGparityFlavourVector<ComplexD>         GparityFlavourVectorD; | ||||
| typedef iGparityFlavourVector<vComplex >         vGparityFlavourVector; | ||||
| typedef iGparityFlavourVector<vComplexF>         vGparityFlavourVectorF; | ||||
| typedef iGparityFlavourVector<vComplexD>         vGparityFlavourVectorD; | ||||
| typedef iGparityFlavourVector<vComplexD2>        vGparityFlavourVectorD2; | ||||
|  | ||||
|      | ||||
| // singlets | ||||
| typedef iSinglet<Complex >         TComplex;     // FIXME This is painful. Tensor singlet complex type. | ||||
| @@ -267,7 +254,6 @@ typedef iSinglet<ComplexD>         TComplexD;    // FIXME This is painful. Tenso | ||||
| typedef iSinglet<vComplex >        vTComplex ;   // what if we don't know the tensor structure | ||||
| typedef iSinglet<vComplexF>        vTComplexF;   // what if we don't know the tensor structure | ||||
| typedef iSinglet<vComplexD>        vTComplexD;   // what if we don't know the tensor structure | ||||
| typedef iSinglet<vComplexD2>       vTComplexD2;   // what if we don't know the tensor structure | ||||
|  | ||||
| typedef iSinglet<Real >            TReal;        // Shouldn't need these; can I make it work without? | ||||
| typedef iSinglet<RealF>            TRealF;       // Shouldn't need these; can I make it work without? | ||||
| @@ -285,58 +271,47 @@ typedef iSinglet<Integer >         TInteger; | ||||
| typedef Lattice<vColourMatrix>          LatticeColourMatrix; | ||||
| typedef Lattice<vColourMatrixF>         LatticeColourMatrixF; | ||||
| typedef Lattice<vColourMatrixD>         LatticeColourMatrixD; | ||||
| typedef Lattice<vColourMatrixD2>        LatticeColourMatrixD2; | ||||
|  | ||||
| typedef Lattice<vSpinMatrix>            LatticeSpinMatrix; | ||||
| typedef Lattice<vSpinMatrixF>           LatticeSpinMatrixF; | ||||
| typedef Lattice<vSpinMatrixD>           LatticeSpinMatrixD; | ||||
| typedef Lattice<vSpinMatrixD2>          LatticeSpinMatrixD2; | ||||
|  | ||||
| typedef Lattice<vSpinColourMatrix>      LatticeSpinColourMatrix; | ||||
| typedef Lattice<vSpinColourMatrixF>     LatticeSpinColourMatrixF; | ||||
| typedef Lattice<vSpinColourMatrixD>     LatticeSpinColourMatrixD; | ||||
| typedef Lattice<vSpinColourMatrixD2>    LatticeSpinColourMatrixD2; | ||||
|  | ||||
| typedef Lattice<vSpinColourSpinColourMatrix>      LatticeSpinColourSpinColourMatrix; | ||||
| typedef Lattice<vSpinColourSpinColourMatrixF>     LatticeSpinColourSpinColourMatrixF; | ||||
| typedef Lattice<vSpinColourSpinColourMatrixD>     LatticeSpinColourSpinColourMatrixD; | ||||
| typedef Lattice<vSpinColourSpinColourMatrixD2>    LatticeSpinColourSpinColourMatrixD2; | ||||
|  | ||||
| typedef Lattice<vLorentzColourMatrix>  LatticeLorentzColourMatrix; | ||||
| typedef Lattice<vLorentzColourMatrixF> LatticeLorentzColourMatrixF; | ||||
| typedef Lattice<vLorentzColourMatrixD> LatticeLorentzColourMatrixD; | ||||
| typedef Lattice<vLorentzColourMatrixD2> LatticeLorentzColourMatrixD2; | ||||
|  | ||||
| // DoubleStored gauge field | ||||
| typedef Lattice<vDoubleStoredColourMatrix>  LatticeDoubleStoredColourMatrix; | ||||
| typedef Lattice<vDoubleStoredColourMatrixF> LatticeDoubleStoredColourMatrixF; | ||||
| typedef Lattice<vDoubleStoredColourMatrixD> LatticeDoubleStoredColourMatrixD; | ||||
| typedef Lattice<vDoubleStoredColourMatrixD2> LatticeDoubleStoredColourMatrixD2; | ||||
|  | ||||
| typedef Lattice<vSpinVector>            LatticeSpinVector; | ||||
| typedef Lattice<vSpinVectorF>           LatticeSpinVectorF; | ||||
| typedef Lattice<vSpinVectorD>           LatticeSpinVectorD; | ||||
| typedef Lattice<vSpinVectorD2>          LatticeSpinVectorD2; | ||||
|  | ||||
| typedef Lattice<vColourVector>          LatticeColourVector; | ||||
| typedef Lattice<vColourVectorF>         LatticeColourVectorF; | ||||
| typedef Lattice<vColourVectorD>         LatticeColourVectorD; | ||||
| typedef Lattice<vColourVectorD2>        LatticeColourVectorD2; | ||||
|  | ||||
| typedef Lattice<vSpinColourVector>      LatticeSpinColourVector; | ||||
| typedef Lattice<vSpinColourVectorF>     LatticeSpinColourVectorF; | ||||
| typedef Lattice<vSpinColourVectorD>     LatticeSpinColourVectorD; | ||||
| typedef Lattice<vSpinColourVectorD2>    LatticeSpinColourVectorD2; | ||||
|  | ||||
| typedef Lattice<vHalfSpinVector>        LatticeHalfSpinVector; | ||||
| typedef Lattice<vHalfSpinVectorF>       LatticeHalfSpinVectorF; | ||||
| typedef Lattice<vHalfSpinVectorD>       LatticeHalfSpinVectorD; | ||||
| typedef Lattice<vHalfSpinVectorD2>      LatticeHalfSpinVectorD2; | ||||
|  | ||||
| typedef Lattice<vHalfSpinColourVector>  LatticeHalfSpinColourVector; | ||||
| typedef Lattice<vHalfSpinColourVectorF> LatticeHalfSpinColourVectorF; | ||||
| typedef Lattice<vHalfSpinColourVectorD> LatticeHalfSpinColourVectorD; | ||||
| typedef Lattice<vHalfSpinColourVectorD2> LatticeHalfSpinColourVectorD2; | ||||
|  | ||||
| typedef Lattice<vTReal>            LatticeReal; | ||||
| typedef Lattice<vTRealF>           LatticeRealF; | ||||
| @@ -345,7 +320,6 @@ typedef Lattice<vTRealD>           LatticeRealD; | ||||
| typedef Lattice<vTComplex>         LatticeComplex; | ||||
| typedef Lattice<vTComplexF>        LatticeComplexF; | ||||
| typedef Lattice<vTComplexD>        LatticeComplexD; | ||||
| typedef Lattice<vTComplexD2>       LatticeComplexD2; | ||||
|  | ||||
| typedef Lattice<vTInteger>         LatticeInteger; // Predicates for "where" | ||||
|  | ||||
| @@ -355,40 +329,35 @@ typedef Lattice<vTInteger>         LatticeInteger; // Predicates for "where" | ||||
| /////////////////////////////////////////// | ||||
| typedef LatticeHalfSpinColourVector  LatticeHalfFermion; | ||||
| typedef LatticeHalfSpinColourVectorF LatticeHalfFermionF; | ||||
| typedef LatticeHalfSpinColourVectorD  LatticeHalfFermionD; | ||||
| typedef LatticeHalfSpinColourVectorD2 LatticeHalfFermionD2; | ||||
| typedef LatticeHalfSpinColourVectorF LatticeHalfFermionD; | ||||
|  | ||||
| typedef LatticeSpinColourVector      LatticeFermion; | ||||
| typedef LatticeSpinColourVectorF     LatticeFermionF; | ||||
| typedef LatticeSpinColourVectorD     LatticeFermionD; | ||||
| typedef LatticeSpinColourVectorD2    LatticeFermionD2; | ||||
|  | ||||
| typedef LatticeSpinColourMatrix                LatticePropagator; | ||||
| typedef LatticeSpinColourMatrixF               LatticePropagatorF; | ||||
| typedef LatticeSpinColourMatrixD               LatticePropagatorD; | ||||
| typedef LatticeSpinColourMatrixD2              LatticePropagatorD2; | ||||
|  | ||||
| typedef LatticeLorentzColourMatrix             LatticeGaugeField; | ||||
| typedef LatticeLorentzColourMatrixF            LatticeGaugeFieldF; | ||||
| typedef LatticeLorentzColourMatrixD            LatticeGaugeFieldD; | ||||
| typedef LatticeLorentzColourMatrixD2           LatticeGaugeFieldD2; | ||||
|  | ||||
| typedef LatticeDoubleStoredColourMatrix        LatticeDoubledGaugeField; | ||||
| typedef LatticeDoubleStoredColourMatrixF       LatticeDoubledGaugeFieldF; | ||||
| typedef LatticeDoubleStoredColourMatrixD       LatticeDoubledGaugeFieldD; | ||||
| typedef LatticeDoubleStoredColourMatrixD2      LatticeDoubledGaugeFieldD2; | ||||
|  | ||||
| template<class GF> using LorentzScalar = Lattice<iScalar<typename GF::vector_object::element> >; | ||||
|  | ||||
| // Uhgg... typing this hurt  ;) | ||||
| // (my keyboard got burning hot when I typed this, must be the anti-Fermion) | ||||
| typedef Lattice<vColourVector>          LatticeStaggeredFermion;     | ||||
| typedef Lattice<vColourVectorF>         LatticeStaggeredFermionF;     | ||||
| typedef Lattice<vColourVectorD>         LatticeStaggeredFermionD;     | ||||
| typedef Lattice<vColourVectorD2>        LatticeStaggeredFermionD2;     | ||||
|  | ||||
| typedef Lattice<vColourMatrix>          LatticeStaggeredPropagator;  | ||||
| typedef Lattice<vColourMatrixF>         LatticeStaggeredPropagatorF;  | ||||
| typedef Lattice<vColourMatrixD>         LatticeStaggeredPropagatorD;  | ||||
| typedef Lattice<vColourMatrixD2>        LatticeStaggeredPropagatorD2;  | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // Peek and Poke named after physics attributes | ||||
| @@ -507,20 +476,9 @@ template<class vobj> void pokeLorentz(vobj &lhs,const decltype(peekIndex<Lorentz | ||||
| // Fermion <-> propagator assignements | ||||
| ////////////////////////////////////////////// | ||||
| //template <class Prop, class Ferm> | ||||
| #define FAST_FERM_TO_PROP | ||||
| template <class Fimpl> | ||||
| void FermToProp(typename Fimpl::PropagatorField &p, const typename Fimpl::FermionField &f, const int s, const int c) | ||||
| { | ||||
| #ifdef FAST_FERM_TO_PROP | ||||
|   autoView(p_v,p,CpuWrite); | ||||
|   autoView(f_v,f,CpuRead); | ||||
|   thread_for(idx,p_v.oSites(),{ | ||||
|       for(int ss = 0; ss < Ns; ++ss) { | ||||
|       for(int cc = 0; cc < Fimpl::Dimension; ++cc) { | ||||
| 	p_v[idx]()(ss,s)(cc,c) = f_v[idx]()(ss)(cc); // Propagator sink index is LEFT, suitable for left mult by gauge link (e.g.) | ||||
|       }} | ||||
|     }); | ||||
| #else | ||||
|   for(int j = 0; j < Ns; ++j) | ||||
|     { | ||||
|       auto pjs = peekSpin(p, j, s); | ||||
| @@ -532,23 +490,12 @@ void FermToProp(typename Fimpl::PropagatorField &p, const typename Fimpl::Fermio | ||||
| 	} | ||||
|       pokeSpin(p, pjs, j, s); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|      | ||||
| //template <class Prop, class Ferm> | ||||
| template <class Fimpl> | ||||
| void PropToFerm(typename Fimpl::FermionField &f, const typename Fimpl::PropagatorField &p, const int s, const int c) | ||||
| { | ||||
| #ifdef FAST_FERM_TO_PROP | ||||
|   autoView(p_v,p,CpuRead); | ||||
|   autoView(f_v,f,CpuWrite); | ||||
|   thread_for(idx,p_v.oSites(),{ | ||||
|       for(int ss = 0; ss < Ns; ++ss) { | ||||
|       for(int cc = 0; cc < Fimpl::Dimension; ++cc) { | ||||
| 	f_v[idx]()(ss)(cc) = p_v[idx]()(ss,s)(cc,c); // LEFT index is copied across for s,c right index | ||||
|       }} | ||||
|     }); | ||||
| #else | ||||
|   for(int j = 0; j < Ns; ++j) | ||||
|     { | ||||
|       auto pjs = peekSpin(p, j, s); | ||||
| @@ -560,7 +507,6 @@ void PropToFerm(typename Fimpl::FermionField &f, const typename Fimpl::Propagato | ||||
| 	} | ||||
|       pokeSpin(f, fj, j); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|      | ||||
| ////////////////////////////////////////////// | ||||
|   | ||||
| @@ -40,47 +40,9 @@ class Action | ||||
|  | ||||
| public: | ||||
|   bool is_smeared = false; | ||||
|   RealD deriv_norm_sum; | ||||
|   RealD deriv_max_sum; | ||||
|   RealD Fdt_norm_sum; | ||||
|   RealD Fdt_max_sum; | ||||
|   int   deriv_num; | ||||
|   RealD deriv_us; | ||||
|   RealD S_us; | ||||
|   RealD refresh_us; | ||||
|   void  reset_timer(void)        { | ||||
|     deriv_us = S_us = refresh_us = 0.0; | ||||
|     deriv_norm_sum = deriv_max_sum=0.0; | ||||
|     Fdt_max_sum =  Fdt_norm_sum = 0.0; | ||||
|     deriv_num=0; | ||||
|   } | ||||
|   void  deriv_log(RealD nrm, RealD max,RealD Fdt_nrm,RealD Fdt_max) { | ||||
|     if ( max > deriv_max_sum ) { | ||||
|       deriv_max_sum=max; | ||||
|     } | ||||
|     deriv_norm_sum+=nrm; | ||||
|     if ( Fdt_max > Fdt_max_sum ) { | ||||
|       Fdt_max_sum=Fdt_max; | ||||
|     } | ||||
|     Fdt_norm_sum+=Fdt_nrm; deriv_num++; | ||||
|   } | ||||
|   RealD deriv_max_average(void)       { return deriv_max_sum; }; | ||||
|   RealD deriv_norm_average(void)      { return deriv_norm_sum/deriv_num; }; | ||||
|   RealD Fdt_max_average(void)         { return Fdt_max_sum; }; | ||||
|   RealD Fdt_norm_average(void)        { return Fdt_norm_sum/deriv_num; }; | ||||
|   RealD deriv_timer(void)        { return deriv_us; }; | ||||
|   RealD S_timer(void)            { return S_us; }; | ||||
|   RealD refresh_timer(void)      { return refresh_us; }; | ||||
|   void deriv_timer_start(void)   { deriv_us-=usecond(); } | ||||
|   void deriv_timer_stop(void)    { deriv_us+=usecond(); } | ||||
|   void refresh_timer_start(void) { refresh_us-=usecond(); } | ||||
|   void refresh_timer_stop(void)  { refresh_us+=usecond(); } | ||||
|   void S_timer_start(void)       { S_us-=usecond(); } | ||||
|   void S_timer_stop(void)        { S_us+=usecond(); } | ||||
|   // Heatbath? | ||||
|   virtual void refresh(const GaugeField& U, GridSerialRNG &sRNG, GridParallelRNG& pRNG) = 0; // refresh pseudofermions | ||||
|   virtual RealD S(const GaugeField& U) = 0;                             // evaluate the action | ||||
|   virtual RealD Sinitial(const GaugeField& U) { return this->S(U); } ;  // if the refresh computes the action, can cache it. Alternately refreshAndAction() ? | ||||
|   virtual void deriv(const GaugeField& U, GaugeField& dSdU) = 0;        // evaluate the action derivative | ||||
|   virtual std::string action_name()    = 0;                             // return the action name | ||||
|   virtual std::string LogParameters()  = 0;                             // prints action parameters | ||||
|   | ||||
| @@ -37,10 +37,6 @@ NAMESPACE_CHECK(ActionSet); | ||||
| #include <Grid/qcd/action/ActionParams.h> | ||||
| NAMESPACE_CHECK(ActionParams); | ||||
|  | ||||
| #include <Grid/qcd/action/filters/MomentumFilter.h> | ||||
| #include <Grid/qcd/action/filters/DirichletFilter.h> | ||||
| #include <Grid/qcd/action/filters/DDHMCFilter.h> | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| // Gauge Actions | ||||
| //////////////////////////////////////////// | ||||
|   | ||||
| @@ -34,45 +34,28 @@ directory | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
|  | ||||
| // These can move into a params header and be given MacroMagic serialisation | ||||
| struct GparityWilsonImplParams { | ||||
|   Coordinate twists; | ||||
|   Coordinate twists; //Here the first Nd-1 directions are treated as "spatial", and a twist value of 1 indicates G-parity BCs in that direction.  | ||||
|                      //mu=Nd-1 is assumed to be the time direction and a twist value of 1 indicates antiperiodic BCs | ||||
|   Coordinate dirichlet; // Blocksize of dirichlet BCs | ||||
|   int  partialDirichlet; | ||||
|   GparityWilsonImplParams() : twists(Nd, 0) { | ||||
|     dirichlet.resize(0); | ||||
|     partialDirichlet=0; | ||||
|   }; | ||||
|   GparityWilsonImplParams() : twists(Nd, 0) {}; | ||||
| }; | ||||
|    | ||||
| struct WilsonImplParams { | ||||
|   bool overlapCommsCompute; | ||||
|   Coordinate dirichlet; // Blocksize of dirichlet BCs | ||||
|   int  partialDirichlet; | ||||
|   AcceleratorVector<Real,Nd> twist_n_2pi_L; | ||||
|   AcceleratorVector<Complex,Nd> boundary_phases; | ||||
|   WilsonImplParams()  { | ||||
|     dirichlet.resize(0); | ||||
|     partialDirichlet=0; | ||||
|     boundary_phases.resize(Nd, 1.0); | ||||
|       twist_n_2pi_L.resize(Nd, 0.0); | ||||
|   }; | ||||
|   WilsonImplParams(const AcceleratorVector<Complex,Nd> phi) : boundary_phases(phi), overlapCommsCompute(false) { | ||||
|     twist_n_2pi_L.resize(Nd, 0.0); | ||||
|     partialDirichlet=0; | ||||
|     dirichlet.resize(0); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| struct StaggeredImplParams { | ||||
|   Coordinate dirichlet; // Blocksize of dirichlet BCs | ||||
|   int  partialDirichlet; | ||||
|   StaggeredImplParams() | ||||
|   { | ||||
|     partialDirichlet=0; | ||||
|     dirichlet.resize(0); | ||||
|   }; | ||||
|   StaggeredImplParams()  {}; | ||||
| }; | ||||
|    | ||||
|   struct OneFlavourRationalParams : Serializable { | ||||
| @@ -81,7 +64,6 @@ struct StaggeredImplParams { | ||||
| 				    RealD, hi,  | ||||
| 				    int,   MaxIter,  | ||||
| 				    RealD, tolerance,  | ||||
| 				    RealD, mdtolerance,  | ||||
| 				    int,   degree,  | ||||
| 				    int,   precision, | ||||
| 				    int,   BoundsCheckFreq, | ||||
| @@ -97,19 +79,18 @@ struct StaggeredImplParams { | ||||
|                            	int _degree    = 10, | ||||
| 				int _precision = 64, | ||||
| 				int _BoundsCheckFreq=20, | ||||
| 				RealD mdtol    = 1.0e-6, | ||||
| 				double _BoundsCheckTol=1e-6) | ||||
|       : lo(_lo), | ||||
| 	hi(_hi), | ||||
| 	MaxIter(_maxit), | ||||
| 	tolerance(tol), | ||||
|         mdtolerance(mdtol), | ||||
| 	degree(_degree), | ||||
|         precision(_precision), | ||||
|         BoundsCheckFreq(_BoundsCheckFreq), | ||||
|         BoundsCheckTol(_BoundsCheckTol){}; | ||||
|   }; | ||||
|  | ||||
|  | ||||
|   /*Action parameters for the generalized rational action | ||||
|     The approximation is for (M^dag M)^{1/inv_pow} | ||||
|     where inv_pow is the denominator of the fractional power. | ||||
| @@ -152,6 +133,7 @@ struct StaggeredImplParams { | ||||
|   }; | ||||
|  | ||||
|  | ||||
|    | ||||
| NAMESPACE_END(Grid); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -68,17 +68,9 @@ public: | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Support for MADWF tricks | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   RealD Mass(void) { return (mass_plus + mass_minus) / 2.0; }; | ||||
|   RealD MassPlus(void) { return mass_plus; }; | ||||
|   RealD MassMinus(void) { return mass_minus; }; | ||||
|  | ||||
|   RealD Mass(void) { return mass; }; | ||||
|   void  SetMass(RealD _mass) {  | ||||
|     mass_plus=mass_minus=_mass;  | ||||
|     SetCoefficientsInternal(_zolo_hi,_gamma,_b,_c);  // Reset coeffs | ||||
|   } ; | ||||
|   void  SetMass(RealD _mass_plus, RealD _mass_minus) {  | ||||
|     mass_plus=_mass_plus; | ||||
|     mass_minus=_mass_minus; | ||||
|     mass=_mass;  | ||||
|     SetCoefficientsInternal(_zolo_hi,_gamma,_b,_c);  // Reset coeffs | ||||
|   } ; | ||||
|   void  P(const FermionField &psi, FermionField &chi); | ||||
| @@ -116,7 +108,7 @@ public: | ||||
|   void   MeooeDag5D    (const FermionField &in, FermionField &out); | ||||
|  | ||||
|   //    protected: | ||||
|   RealD mass_plus, mass_minus; | ||||
|   RealD mass; | ||||
|  | ||||
|   // Save arguments to SetCoefficientsInternal | ||||
|   Vector<Coeff_t> _gamma; | ||||
| @@ -183,6 +175,16 @@ public: | ||||
| 		  GridRedBlackCartesian &FourDimRedBlackGrid, | ||||
| 		  RealD _mass,RealD _M5,const ImplParams &p= ImplParams()); | ||||
|  | ||||
|   void CayleyReport(void); | ||||
|   void CayleyZeroCounters(void); | ||||
|  | ||||
|   double M5Dflops; | ||||
|   double M5Dcalls; | ||||
|   double M5Dtime; | ||||
|  | ||||
|   double MooeeInvFlops; | ||||
|   double MooeeInvCalls; | ||||
|   double MooeeInvTime; | ||||
|  | ||||
| protected: | ||||
|   virtual void SetCoefficientsZolotarev(RealD zolohi,Approx::zolotarev_data *zdata,RealD b,RealD c); | ||||
|   | ||||
| @@ -1,334 +0,0 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
|     Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
|     Source file: ./lib/qcd/action/fermion/WilsonCloverFermionImplementation.h | ||||
|  | ||||
|     Copyright (C) 2017 - 2022 | ||||
|  | ||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|     Author: Mattia Bruno <mattia.bruno@cern.ch> | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License along | ||||
|     with this program; if not, write to the Free Software Foundation, Inc., | ||||
|     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
|     See the full license in the file "LICENSE" in the top level distribution directory | ||||
|     *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <Grid/Grid.h> | ||||
| #include <Grid/qcd/spin/Dirac.h> | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| // Standard Clover | ||||
| //   (4+m0) + csw * clover_term | ||||
| // Exp Clover | ||||
| //   (4+m0) * exp(csw/(4+m0) clover_term) | ||||
| //   = (4+m0) + csw * clover_term + ... | ||||
| //////////////////////////////////////////// | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
|  | ||||
| ////////////////////////////////// | ||||
| // Generic Standard Clover | ||||
| ////////////////////////////////// | ||||
|  | ||||
| template<class Impl> | ||||
| class CloverHelpers: public WilsonCloverHelpers<Impl> { | ||||
| public: | ||||
|  | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|   INHERIT_CLOVER_TYPES(Impl); | ||||
|  | ||||
|   typedef WilsonCloverHelpers<Impl> Helpers; | ||||
|  | ||||
|   static void Instantiate(CloverField& CloverTerm, CloverField& CloverTermInv, RealD csw_t, RealD diag_mass) { | ||||
|     GridBase *grid = CloverTerm.Grid(); | ||||
|     CloverTerm += diag_mass; | ||||
|  | ||||
|     int lvol = grid->lSites(); | ||||
|     int DimRep = Impl::Dimension; | ||||
|     { | ||||
|       autoView(CTv,CloverTerm,CpuRead); | ||||
|       autoView(CTIv,CloverTermInv,CpuWrite); | ||||
|       thread_for(site, lvol, { | ||||
|         Coordinate lcoor; | ||||
|         grid->LocalIndexToLocalCoor(site, lcoor); | ||||
|         Eigen::MatrixXcd EigenCloverOp = Eigen::MatrixXcd::Zero(Ns * DimRep, Ns * DimRep); | ||||
|         Eigen::MatrixXcd EigenInvCloverOp = Eigen::MatrixXcd::Zero(Ns * DimRep, Ns * DimRep); | ||||
|         typename SiteClover::scalar_object Qx = Zero(), Qxinv = Zero(); | ||||
|         peekLocalSite(Qx, CTv, lcoor); | ||||
|  | ||||
|         for (int j = 0; j < Ns; j++) | ||||
|           for (int k = 0; k < Ns; k++) | ||||
|             for (int a = 0; a < DimRep; a++) | ||||
|               for (int b = 0; b < DimRep; b++){ | ||||
|                 auto zz =  Qx()(j, k)(a, b); | ||||
|                 EigenCloverOp(a + j * DimRep, b + k * DimRep) = std::complex<double>(zz); | ||||
|               } | ||||
|  | ||||
|         EigenInvCloverOp = EigenCloverOp.inverse(); | ||||
|         for (int j = 0; j < Ns; j++) | ||||
|           for (int k = 0; k < Ns; k++) | ||||
|             for (int a = 0; a < DimRep; a++) | ||||
|               for (int b = 0; b < DimRep; b++) | ||||
|                 Qxinv()(j, k)(a, b) = EigenInvCloverOp(a + j * DimRep, b + k * DimRep); | ||||
|                pokeLocalSite(Qxinv, CTIv, lcoor); | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) { | ||||
|     return Helpers::Cmunu(U, lambda, mu, nu); | ||||
|   } | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| ////////////////////////////////// | ||||
| // Generic Exp Clover | ||||
| ////////////////////////////////// | ||||
|  | ||||
| template<class Impl> | ||||
| class ExpCloverHelpers: public WilsonCloverHelpers<Impl> { | ||||
| public: | ||||
|  | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|   INHERIT_CLOVER_TYPES(Impl); | ||||
|  | ||||
|   template <typename vtype> using iImplClover = iScalar<iMatrix<iMatrix<vtype, Impl::Dimension>, Ns>>; | ||||
|   typedef WilsonCloverHelpers<Impl> Helpers; | ||||
|  | ||||
|   // Can this be avoided? | ||||
|   static void IdentityTimesC(const CloverField& in, RealD c) { | ||||
|     int DimRep = Impl::Dimension; | ||||
|  | ||||
|     autoView(in_v, in, AcceleratorWrite); | ||||
|  | ||||
|     accelerator_for(ss, in.Grid()->oSites(), 1, { | ||||
|       for (int sa=0; sa<Ns; sa++) | ||||
|         for (int ca=0; ca<DimRep; ca++) | ||||
|           in_v[ss]()(sa,sa)(ca,ca) = c; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   static int getNMAX(RealD prec, RealD R) { | ||||
|     /* compute stop condition for exponential */ | ||||
|     int NMAX=1; | ||||
|     RealD cond=R*R/2.; | ||||
|  | ||||
|     while (cond*std::exp(R)>prec) { | ||||
|       NMAX++; | ||||
|       cond*=R/(double)(NMAX+1); | ||||
|     } | ||||
|     return NMAX; | ||||
|   } | ||||
|  | ||||
|   static int getNMAX(Lattice<iImplClover<vComplexD2>> &t, RealD R) {return getNMAX(1e-12,R);} | ||||
|   static int getNMAX(Lattice<iImplClover<vComplexD>> &t, RealD R) {return getNMAX(1e-12,R);} | ||||
|   static int getNMAX(Lattice<iImplClover<vComplexF>> &t, RealD R) {return getNMAX(1e-6,R);} | ||||
|  | ||||
|   static void Instantiate(CloverField& Clover, CloverField& CloverInv, RealD csw_t, RealD diag_mass) { | ||||
|     GridBase* grid = Clover.Grid(); | ||||
|     CloverField ExpClover(grid); | ||||
|  | ||||
|     int NMAX = getNMAX(Clover, 3.*csw_t/diag_mass); | ||||
|  | ||||
|     Clover *= (1.0/diag_mass); | ||||
|  | ||||
|     // Taylor expansion, slow but generic | ||||
|     // Horner scheme: a0 + a1 x + a2 x^2 + .. = a0 + x (a1 + x(...)) | ||||
|     // qN = cN | ||||
|     // qn = cn + qn+1 X | ||||
|     std::vector<RealD> cn(NMAX+1); | ||||
|     cn[0] = 1.0; | ||||
|     for (int i=1; i<=NMAX; i++) | ||||
|       cn[i] = cn[i-1] / RealD(i); | ||||
|  | ||||
|     ExpClover = Zero(); | ||||
|     IdentityTimesC(ExpClover, cn[NMAX]); | ||||
|     for (int i=NMAX-1; i>=0; i--) | ||||
|       ExpClover = ExpClover * Clover + cn[i]; | ||||
|  | ||||
|     // prepare inverse | ||||
|     CloverInv = (-1.0)*Clover; | ||||
|  | ||||
|     Clover = ExpClover * diag_mass; | ||||
|  | ||||
|     ExpClover = Zero(); | ||||
|     IdentityTimesC(ExpClover, cn[NMAX]); | ||||
|     for (int i=NMAX-1; i>=0; i--) | ||||
|       ExpClover = ExpClover * CloverInv + cn[i]; | ||||
|  | ||||
|     CloverInv = ExpClover * (1.0/diag_mass); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) { | ||||
|     assert(0); | ||||
|     return lambda; | ||||
|   } | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| ////////////////////////////////// | ||||
| // Compact Standard Clover | ||||
| ////////////////////////////////// | ||||
|  | ||||
|  | ||||
| template<class Impl> | ||||
| class CompactCloverHelpers: public CompactWilsonCloverHelpers<Impl>, | ||||
|                             public WilsonCloverHelpers<Impl> { | ||||
| public: | ||||
|  | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|   INHERIT_CLOVER_TYPES(Impl); | ||||
|   INHERIT_COMPACT_CLOVER_TYPES(Impl); | ||||
|  | ||||
|   typedef WilsonCloverHelpers<Impl> Helpers; | ||||
|   typedef CompactWilsonCloverHelpers<Impl> CompactHelpers; | ||||
|  | ||||
|   static void InstantiateClover(CloverField& Clover, CloverField& CloverInv, RealD csw_t, RealD diag_mass) { | ||||
|     Clover += diag_mass; | ||||
|   } | ||||
|  | ||||
|   static void InvertClover(CloverField& InvClover, | ||||
|                             const CloverDiagonalField& diagonal, | ||||
|                             const CloverTriangleField& triangle, | ||||
|                             CloverDiagonalField&       diagonalInv, | ||||
|                             CloverTriangleField&       triangleInv, | ||||
|                             bool fixedBoundaries) { | ||||
|  | ||||
|     CompactHelpers::Invert(diagonal, triangle, diagonalInv, triangleInv); | ||||
|   } | ||||
|  | ||||
|   // TODO: implement Cmunu for better performances with compact layout, but don't do it | ||||
|   // here, but rather in WilsonCloverHelpers.h -> CompactWilsonCloverHelpers | ||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) { | ||||
|     return Helpers::Cmunu(U, lambda, mu, nu); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| ////////////////////////////////// | ||||
| // Compact Exp Clover | ||||
| ////////////////////////////////// | ||||
|  | ||||
| template<class Impl> | ||||
| class CompactExpCloverHelpers: public CompactWilsonCloverHelpers<Impl> { | ||||
| public: | ||||
|  | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|   INHERIT_CLOVER_TYPES(Impl); | ||||
|   INHERIT_COMPACT_CLOVER_TYPES(Impl); | ||||
|  | ||||
|   template <typename vtype> using iImplClover = iScalar<iMatrix<iMatrix<vtype, Impl::Dimension>, Ns>>; | ||||
|   typedef CompactWilsonCloverHelpers<Impl> CompactHelpers; | ||||
|  | ||||
|   // Can this be avoided? | ||||
|   static void IdentityTimesC(const CloverField& in, RealD c) { | ||||
|     int DimRep = Impl::Dimension; | ||||
|  | ||||
|     autoView(in_v, in, AcceleratorWrite); | ||||
|  | ||||
|     accelerator_for(ss, in.Grid()->oSites(), 1, { | ||||
|       for (int sa=0; sa<Ns; sa++) | ||||
|         for (int ca=0; ca<DimRep; ca++) | ||||
|           in_v[ss]()(sa,sa)(ca,ca) = c; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   static int getNMAX(RealD prec, RealD R) { | ||||
|     /* compute stop condition for exponential */ | ||||
|     int NMAX=1; | ||||
|     RealD cond=R*R/2.; | ||||
|  | ||||
|     while (cond*std::exp(R)>prec) { | ||||
|       NMAX++; | ||||
|       cond*=R/(double)(NMAX+1); | ||||
|     } | ||||
|     return NMAX; | ||||
|   } | ||||
|  | ||||
|   static int getNMAX(Lattice<iImplClover<vComplexD>> &t, RealD R) {return getNMAX(1e-12,R);} | ||||
|   static int getNMAX(Lattice<iImplClover<vComplexF>> &t, RealD R) {return getNMAX(1e-6,R);} | ||||
|  | ||||
|   static void InstantiateClover(CloverField& Clover, CloverField& CloverInv, RealD csw_t, RealD diag_mass) { | ||||
|  | ||||
|     GridBase* grid = Clover.Grid(); | ||||
|     CloverField ExpClover(grid); | ||||
|  | ||||
|     int NMAX = getNMAX(Clover, 3.*csw_t/diag_mass); | ||||
|  | ||||
|     Clover *= (1.0/diag_mass); | ||||
|  | ||||
|     // Taylor expansion, slow but generic | ||||
|     // Horner scheme: a0 + a1 x + a2 x^2 + .. = a0 + x (a1 + x(...)) | ||||
|     // qN = cN | ||||
|     // qn = cn + qn+1 X | ||||
|     std::vector<RealD> cn(NMAX+1); | ||||
|     cn[0] = 1.0; | ||||
|     for (int i=1; i<=NMAX; i++) | ||||
|       cn[i] = cn[i-1] / RealD(i); | ||||
|  | ||||
|     ExpClover = Zero(); | ||||
|     IdentityTimesC(ExpClover, cn[NMAX]); | ||||
|     for (int i=NMAX-1; i>=0; i--) | ||||
|       ExpClover = ExpClover * Clover + cn[i]; | ||||
|  | ||||
|     // prepare inverse | ||||
|     CloverInv = (-1.0)*Clover; | ||||
|  | ||||
|     Clover = ExpClover * diag_mass; | ||||
|  | ||||
|     ExpClover = Zero(); | ||||
|     IdentityTimesC(ExpClover, cn[NMAX]); | ||||
|     for (int i=NMAX-1; i>=0; i--) | ||||
|       ExpClover = ExpClover * CloverInv + cn[i]; | ||||
|  | ||||
|     CloverInv = ExpClover * (1.0/diag_mass); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   static void InvertClover(CloverField& InvClover, | ||||
|                             const CloverDiagonalField& diagonal, | ||||
|                             const CloverTriangleField& triangle, | ||||
|                             CloverDiagonalField&       diagonalInv, | ||||
|                             CloverTriangleField&       triangleInv, | ||||
|                             bool fixedBoundaries) { | ||||
|  | ||||
|     if (fixedBoundaries) | ||||
|     { | ||||
|       CompactHelpers::Invert(diagonal, triangle, diagonalInv, triangleInv); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       CompactHelpers::ConvertLayout(InvClover, diagonalInv, triangleInv); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static GaugeLinkField Cmunu(std::vector<GaugeLinkField> &U, GaugeLinkField &lambda, int mu, int nu) { | ||||
|     assert(0); | ||||
|     return lambda; | ||||
|   } | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -31,7 +31,6 @@ | ||||
|  | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverTypes.h> | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | ||||
| #include <Grid/qcd/action/fermion/CloverHelpers.h> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| @@ -86,7 +85,7 @@ NAMESPACE_BEGIN(Grid); | ||||
| //           + (2 * 1 + 4 * 1/2) triangle parts = 4 triangle parts =  60 complex words per site | ||||
| //                                                                 =  84 complex words per site | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| template<class Impl> | ||||
| class CompactWilsonCloverFermion : public WilsonFermion<Impl>, | ||||
|                                    public WilsonCloverHelpers<Impl>, | ||||
|                                    public CompactWilsonCloverHelpers<Impl> { | ||||
| @@ -225,7 +224,7 @@ public: | ||||
|   RealD csw_t; | ||||
|   RealD cF; | ||||
|  | ||||
|   bool fixedBoundaries; | ||||
|   bool open_boundaries; | ||||
|  | ||||
|   CloverDiagonalField Diagonal,    DiagonalEven,    DiagonalOdd; | ||||
|   CloverDiagonalField DiagonalInv, DiagonalInvEven, DiagonalInvOdd; | ||||
|   | ||||
| @@ -1,291 +0,0 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/DWFSlow.h | ||||
|  | ||||
| Copyright (C) 2022 | ||||
|  | ||||
| Author: Peter Boyle <pboyle@bnl.gov> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution | ||||
| directory | ||||
| *************************************************************************************/ | ||||
| 			   /*  END LEGAL */ | ||||
| #pragma once | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| template <class Impl> | ||||
| class DWFSlowFermion : public FermionOperator<Impl> | ||||
| { | ||||
| public: | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Implement the abstract base | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   GridBase *GaugeGrid(void) { return _grid4; } | ||||
|   GridBase *GaugeRedBlackGrid(void) { return _cbgrid4; } | ||||
|   GridBase *FermionGrid(void) { return _grid; } | ||||
|   GridBase *FermionRedBlackGrid(void) { return _cbgrid; } | ||||
|  | ||||
|   FermionField _tmp; | ||||
|   FermionField &tmp(void) { return _tmp; } | ||||
|  | ||||
|   ////////////////////////////////////////////////////////////////// | ||||
|   // override multiply; cut number routines if pass dagger argument | ||||
|   // and also make interface more uniformly consistent | ||||
|   ////////////////////////////////////////////////////////////////// | ||||
|   virtual void  M(const FermionField &in, FermionField &out) | ||||
|   { | ||||
|     FermionField tmp(_grid); | ||||
|     out = (5.0 - M5) * in; | ||||
|     Dhop(in,tmp,DaggerNo); | ||||
|     out = out + tmp; | ||||
|   } | ||||
|   virtual void  Mdag(const FermionField &in, FermionField &out) | ||||
|   { | ||||
|     FermionField tmp(_grid); | ||||
|     out = (5.0 - M5) * in; | ||||
|     Dhop(in,tmp,DaggerYes); | ||||
|     out = out + tmp; | ||||
|   }; | ||||
|  | ||||
|   ///////////////////////////////////////////////////////// | ||||
|   // half checkerboard operations 5D redblack so just site identiy | ||||
|   ///////////////////////////////////////////////////////// | ||||
|   void Meooe(const FermionField &in, FermionField &out) | ||||
|   { | ||||
|     if ( in.Checkerboard() == Odd ) { | ||||
|       this->DhopEO(in,out,DaggerNo); | ||||
|     } else { | ||||
|       this->DhopOE(in,out,DaggerNo); | ||||
|     } | ||||
|   } | ||||
|   void MeooeDag(const FermionField &in, FermionField &out) | ||||
|   { | ||||
|     if ( in.Checkerboard() == Odd ) { | ||||
|       this->DhopEO(in,out,DaggerYes); | ||||
|     } else { | ||||
|       this->DhopOE(in,out,DaggerYes); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   // allow override for twisted mass and clover | ||||
|   virtual void Mooee(const FermionField &in, FermionField &out) | ||||
|   { | ||||
|     out = (5.0 - M5) * in; | ||||
|   } | ||||
|   virtual void MooeeDag(const FermionField &in, FermionField &out) | ||||
|   { | ||||
|     out = (5.0 - M5) * in; | ||||
|   } | ||||
|   virtual void MooeeInv(const FermionField &in, FermionField &out) | ||||
|   { | ||||
|     out = (1.0/(5.0 - M5)) * in; | ||||
|   }; | ||||
|   virtual void MooeeInvDag(const FermionField &in, FermionField &out) | ||||
|   { | ||||
|     out = (1.0/(5.0 - M5)) * in; | ||||
|   }; | ||||
|  | ||||
|   virtual void  MomentumSpacePropagator(FermionField &out,const FermionField &in,RealD _mass,std::vector<double> twist) {} ; | ||||
|  | ||||
|   //////////////////////// | ||||
|   // Derivative interface | ||||
|   //////////////////////// | ||||
|   // Interface calls an internal routine | ||||
|   void DhopDeriv(GaugeField &mat,const FermionField &U,const FermionField &V,int dag)  { assert(0);}; | ||||
|   void DhopDerivOE(GaugeField &mat,const FermionField &U,const FermionField &V,int dag){ assert(0);}; | ||||
|   void DhopDerivEO(GaugeField &mat,const FermionField &U,const FermionField &V,int dag){ assert(0);}; | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // non-hermitian hopping term; half cb or both | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   void Dhop(const FermionField &in, FermionField &out, int dag) | ||||
|   { | ||||
|     FermionField tmp(in.Grid()); | ||||
|     Dhop5(in,out,MassField,MassField,dag ); | ||||
|     for(int mu=0;mu<4;mu++){ | ||||
|       DhopDirU(in,Umu[mu],Umu[mu],tmp,mu,dag );    out = out + tmp; | ||||
|     } | ||||
|   }; | ||||
|   void DhopOE(const FermionField &in, FermionField &out, int dag) | ||||
|   { | ||||
|     FermionField tmp(in.Grid()); | ||||
|     assert(in.Checkerboard()==Even); | ||||
|     Dhop5(in,out,MassFieldOdd,MassFieldEven,dag); | ||||
|     for(int mu=0;mu<4;mu++){ | ||||
|       DhopDirU(in,UmuOdd[mu],UmuEven[mu],tmp,mu,dag );    out = out + tmp; | ||||
|     } | ||||
|   }; | ||||
|   void DhopEO(const FermionField &in, FermionField &out, int dag) | ||||
|   { | ||||
|     FermionField tmp(in.Grid()); | ||||
|     assert(in.Checkerboard()==Odd); | ||||
|     Dhop5(in,out, MassFieldEven,MassFieldOdd ,dag );   | ||||
|     for(int mu=0;mu<4;mu++){ | ||||
|       DhopDirU(in,UmuEven[mu],UmuOdd[mu],tmp,mu,dag );    out = out + tmp; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Multigrid assistance; force term uses too | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   void Mdir(const FermionField &in, FermionField &out, int dir, int disp){ assert(0);}; | ||||
|   void MdirAll(const FermionField &in, std::vector<FermionField> &out)   { assert(0);}; | ||||
|   void DhopDir(const FermionField &in, FermionField &out, int dir, int disp) { assert(0);}; | ||||
|   void DhopDirAll(const FermionField &in, std::vector<FermionField> &out)    { assert(0);}; | ||||
|   void DhopDirCalc(const FermionField &in, FermionField &out, int dirdisp,int gamma, int dag) { assert(0);}; | ||||
|  | ||||
|   void DhopDirU(const FermionField &in, const GaugeLinkField &U5e, const GaugeLinkField &U5o, FermionField &out, int mu, int dag) | ||||
|   { | ||||
|     RealD     sgn= 1.0; | ||||
|     if (dag ) sgn=-1.0; | ||||
|  | ||||
|     Gamma::Algebra Gmu [] = { | ||||
| 			 Gamma::Algebra::GammaX, | ||||
| 			 Gamma::Algebra::GammaY, | ||||
| 			 Gamma::Algebra::GammaZ, | ||||
| 			 Gamma::Algebra::GammaT | ||||
|     }; | ||||
|  | ||||
|     //    mass is  1,1,1,1,-m has to multiply the round the world term | ||||
|     FermionField tmp (in.Grid()); | ||||
|     tmp = U5e * Cshift(in,mu+1,1); | ||||
|     out = tmp - Gamma(Gmu[mu])*tmp*sgn; | ||||
|      | ||||
|     tmp = Cshift(adj(U5o)*in,mu+1,-1); | ||||
|     out = out + tmp + Gamma(Gmu[mu])*tmp*sgn; | ||||
|  | ||||
|     out = -0.5*out; | ||||
|   }; | ||||
|  | ||||
|   void Dhop5(const FermionField &in, FermionField &out, ComplexField &massE, ComplexField &massO, int dag) | ||||
|   { | ||||
|     // Mass term.... must multiple the round world with mass = 1,1,1,1, -m | ||||
|     RealD     sgn= 1.0; | ||||
|     if (dag ) sgn=-1.0; | ||||
|  | ||||
|     Gamma G5(Gamma::Algebra::Gamma5); | ||||
|  | ||||
|     FermionField tmp (in.Grid()); | ||||
|     tmp = massE*Cshift(in,0,1); | ||||
|     out = tmp - G5*tmp*sgn; | ||||
|      | ||||
|     tmp = Cshift(massO*in,0,-1); | ||||
|     out = out + tmp + G5*tmp*sgn; | ||||
|     out = -0.5*out; | ||||
|   }; | ||||
|  | ||||
|   // Constructor | ||||
|   DWFSlowFermion(GaugeField &_Umu, GridCartesian &Fgrid, | ||||
| 		 GridRedBlackCartesian &Hgrid, RealD _mass, RealD _M5) | ||||
|     : | ||||
|     _grid(&Fgrid), | ||||
|     _cbgrid(&Hgrid), | ||||
|     _grid4(_Umu.Grid()), | ||||
|     Umu(Nd,&Fgrid), | ||||
|     UmuEven(Nd,&Hgrid), | ||||
|     UmuOdd(Nd,&Hgrid), | ||||
|     MassField(&Fgrid), | ||||
|     MassFieldEven(&Hgrid), | ||||
|     MassFieldOdd(&Hgrid), | ||||
|     M5(_M5), | ||||
|     mass(_mass), | ||||
|     _tmp(&Hgrid) | ||||
|     { | ||||
|       Ls=Fgrid._fdimensions[0]; | ||||
|       ImportGauge(_Umu); | ||||
|  | ||||
|       typedef typename FermionField::scalar_type scalar; | ||||
|  | ||||
|       Lattice<iScalar<vInteger> > coor(&Fgrid); | ||||
|       LatticeCoordinate(coor, 0); // Scoor | ||||
|       ComplexField one(&Fgrid); | ||||
|       MassField =scalar(-mass); | ||||
|       one       =scalar(1.0); | ||||
|       MassField =where(coor==Integer(Ls-1),MassField,one); | ||||
|       for(int mu=0;mu<Nd;mu++){ | ||||
| 	pickCheckerboard(Even,UmuEven[mu],Umu[mu]); | ||||
| 	pickCheckerboard(Odd ,UmuOdd[mu],Umu[mu]); | ||||
|       } | ||||
|       pickCheckerboard(Even,MassFieldEven,MassField); | ||||
|       pickCheckerboard(Odd ,MassFieldOdd,MassField); | ||||
|        | ||||
|     } | ||||
|    | ||||
|   // DoubleStore impl dependent | ||||
|   void ImportGauge(const GaugeField &_Umu4) | ||||
|   { | ||||
|     GaugeLinkField U4(_grid4); | ||||
|     for(int mu=0;mu<Nd;mu++){ | ||||
|       U4 = PeekIndex<LorentzIndex>(_Umu4, mu); | ||||
|       for(int s=0;s<this->Ls;s++){ | ||||
| 	InsertSlice(U4,Umu[mu],s,0); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Data members require to support the functionality | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|  | ||||
| public: | ||||
|   virtual RealD Mass(void) { return mass; } | ||||
|   virtual int   isTrivialEE(void) { return 1; }; | ||||
|   RealD mass; | ||||
|   RealD M5; | ||||
|   int Ls; | ||||
|  | ||||
|   GridBase *_grid4; | ||||
|   GridBase *_grid; | ||||
|   GridBase *_cbgrid4; | ||||
|   GridBase *_cbgrid; | ||||
|  | ||||
|   // Copy of the gauge field , with even and odd subsets | ||||
|   std::vector<GaugeLinkField> Umu; | ||||
|   std::vector<GaugeLinkField> UmuEven; | ||||
|   std::vector<GaugeLinkField> UmuOdd; | ||||
|   ComplexField MassField; | ||||
|   ComplexField MassFieldEven; | ||||
|   ComplexField MassFieldOdd; | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Conserved current utilities | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   void ContractConservedCurrent(PropagatorField &q_in_1, | ||||
|                                 PropagatorField &q_in_2, | ||||
|                                 PropagatorField &q_out, | ||||
|                                 PropagatorField &phys_src, | ||||
|                                 Current curr_type, | ||||
|                                 unsigned int mu){} | ||||
|   void SeqConservedCurrent(PropagatorField &q_in, | ||||
|                            PropagatorField &q_out, | ||||
|                            PropagatorField &phys_src, | ||||
|                            Current curr_type, | ||||
|                            unsigned int mu, | ||||
|                            unsigned int tmin, | ||||
| 			   unsigned int tmax, | ||||
| 			   ComplexField &lattice_cmplx){} | ||||
| }; | ||||
|  | ||||
| typedef DWFSlowFermion<WilsonImplF> DWFSlowFermionF; | ||||
| typedef DWFSlowFermion<WilsonImplD> DWFSlowFermionD; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -47,7 +47,6 @@ Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| //////////////////////////////////////////// | ||||
| // Fermion operators / actions | ||||
| //////////////////////////////////////////// | ||||
| #include <Grid/qcd/action/fermion/DWFSlow.h>       // Slow DWF | ||||
|  | ||||
| #include <Grid/qcd/action/fermion/WilsonFermion.h>       // 4d wilson like | ||||
| NAMESPACE_CHECK(Wilson); | ||||
| @@ -113,151 +112,200 @@ NAMESPACE_CHECK(DWFutils); | ||||
| // Cayley 5d | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| typedef WilsonFermion<WilsonImplD2> WilsonFermionD2; | ||||
| typedef WilsonFermion<WilsonImplR> WilsonFermionR; | ||||
| typedef WilsonFermion<WilsonImplF> WilsonFermionF; | ||||
| typedef WilsonFermion<WilsonImplD> WilsonFermionD; | ||||
|  | ||||
| //typedef WilsonFermion<WilsonImplRL> WilsonFermionRL; | ||||
| //typedef WilsonFermion<WilsonImplFH> WilsonFermionFH; | ||||
| //typedef WilsonFermion<WilsonImplDF> WilsonFermionDF; | ||||
|  | ||||
| typedef WilsonFermion<WilsonAdjImplR> WilsonAdjFermionR; | ||||
| typedef WilsonFermion<WilsonAdjImplF> WilsonAdjFermionF; | ||||
| typedef WilsonFermion<WilsonAdjImplD> WilsonAdjFermionD; | ||||
|  | ||||
| typedef WilsonFermion<WilsonTwoIndexSymmetricImplR> WilsonTwoIndexSymmetricFermionR; | ||||
| typedef WilsonFermion<WilsonTwoIndexSymmetricImplF> WilsonTwoIndexSymmetricFermionF; | ||||
| typedef WilsonFermion<WilsonTwoIndexSymmetricImplD> WilsonTwoIndexSymmetricFermionD; | ||||
|  | ||||
| typedef WilsonFermion<WilsonTwoIndexAntiSymmetricImplR> WilsonTwoIndexAntiSymmetricFermionR; | ||||
| typedef WilsonFermion<WilsonTwoIndexAntiSymmetricImplF> WilsonTwoIndexAntiSymmetricFermionF; | ||||
| typedef WilsonFermion<WilsonTwoIndexAntiSymmetricImplD> WilsonTwoIndexAntiSymmetricFermionD; | ||||
|  | ||||
| // Twisted mass fermion | ||||
| typedef WilsonTMFermion<WilsonImplD2> WilsonTMFermionD2; | ||||
| typedef WilsonTMFermion<WilsonImplR> WilsonTMFermionR; | ||||
| typedef WilsonTMFermion<WilsonImplF> WilsonTMFermionF; | ||||
| typedef WilsonTMFermion<WilsonImplD> WilsonTMFermionD; | ||||
|  | ||||
| // Clover fermions | ||||
| template <typename WImpl> using WilsonClover = WilsonCloverFermion<WImpl, CloverHelpers<WImpl>>; | ||||
| template <typename WImpl> using WilsonExpClover = WilsonCloverFermion<WImpl, ExpCloverHelpers<WImpl>>; | ||||
| typedef WilsonCloverFermion<WilsonImplR> WilsonCloverFermionR; | ||||
| typedef WilsonCloverFermion<WilsonImplF> WilsonCloverFermionF; | ||||
| typedef WilsonCloverFermion<WilsonImplD> WilsonCloverFermionD; | ||||
|  | ||||
| typedef WilsonClover<WilsonImplD2> WilsonCloverFermionD2; | ||||
| typedef WilsonClover<WilsonImplF> WilsonCloverFermionF; | ||||
| typedef WilsonClover<WilsonImplD> WilsonCloverFermionD; | ||||
| typedef WilsonCloverFermion<WilsonAdjImplR> WilsonCloverAdjFermionR; | ||||
| typedef WilsonCloverFermion<WilsonAdjImplF> WilsonCloverAdjFermionF; | ||||
| typedef WilsonCloverFermion<WilsonAdjImplD> WilsonCloverAdjFermionD; | ||||
|  | ||||
| typedef WilsonExpClover<WilsonImplD2> WilsonExpCloverFermionD2; | ||||
| typedef WilsonExpClover<WilsonImplF> WilsonExpCloverFermionF; | ||||
| typedef WilsonExpClover<WilsonImplD> WilsonExpCloverFermionD; | ||||
| typedef WilsonCloverFermion<WilsonTwoIndexSymmetricImplR> WilsonCloverTwoIndexSymmetricFermionR; | ||||
| typedef WilsonCloverFermion<WilsonTwoIndexSymmetricImplF> WilsonCloverTwoIndexSymmetricFermionF; | ||||
| typedef WilsonCloverFermion<WilsonTwoIndexSymmetricImplD> WilsonCloverTwoIndexSymmetricFermionD; | ||||
|  | ||||
| typedef WilsonClover<WilsonAdjImplF> WilsonCloverAdjFermionF; | ||||
| typedef WilsonClover<WilsonAdjImplD> WilsonCloverAdjFermionD; | ||||
|  | ||||
| typedef WilsonClover<WilsonTwoIndexSymmetricImplF> WilsonCloverTwoIndexSymmetricFermionF; | ||||
| typedef WilsonClover<WilsonTwoIndexSymmetricImplD> WilsonCloverTwoIndexSymmetricFermionD; | ||||
|  | ||||
| typedef WilsonClover<WilsonTwoIndexAntiSymmetricImplF> WilsonCloverTwoIndexAntiSymmetricFermionF; | ||||
| typedef WilsonClover<WilsonTwoIndexAntiSymmetricImplD> WilsonCloverTwoIndexAntiSymmetricFermionD; | ||||
| typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplR> WilsonCloverTwoIndexAntiSymmetricFermionR; | ||||
| typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplF> WilsonCloverTwoIndexAntiSymmetricFermionF; | ||||
| typedef WilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplD> WilsonCloverTwoIndexAntiSymmetricFermionD; | ||||
|  | ||||
| // Compact Clover fermions | ||||
| template <typename WImpl> using CompactWilsonClover = CompactWilsonCloverFermion<WImpl, CompactCloverHelpers<WImpl>>; | ||||
| template <typename WImpl> using CompactWilsonExpClover = CompactWilsonCloverFermion<WImpl, CompactExpCloverHelpers<WImpl>>; | ||||
| typedef CompactWilsonCloverFermion<WilsonImplR> CompactWilsonCloverFermionR; | ||||
| typedef CompactWilsonCloverFermion<WilsonImplF> CompactWilsonCloverFermionF; | ||||
| typedef CompactWilsonCloverFermion<WilsonImplD> CompactWilsonCloverFermionD; | ||||
|  | ||||
| typedef CompactWilsonClover<WilsonImplD2> CompactWilsonCloverFermionD2; | ||||
| typedef CompactWilsonClover<WilsonImplF> CompactWilsonCloverFermionF; | ||||
| typedef CompactWilsonClover<WilsonImplD> CompactWilsonCloverFermionD; | ||||
| typedef CompactWilsonCloverFermion<WilsonAdjImplR> CompactWilsonCloverAdjFermionR; | ||||
| typedef CompactWilsonCloverFermion<WilsonAdjImplF> CompactWilsonCloverAdjFermionF; | ||||
| typedef CompactWilsonCloverFermion<WilsonAdjImplD> CompactWilsonCloverAdjFermionD; | ||||
|  | ||||
| typedef CompactWilsonExpClover<WilsonImplD2> CompactWilsonExpCloverFermionD2; | ||||
| typedef CompactWilsonExpClover<WilsonImplF> CompactWilsonExpCloverFermionF; | ||||
| typedef CompactWilsonExpClover<WilsonImplD> CompactWilsonExpCloverFermionD; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplR> CompactWilsonCloverTwoIndexSymmetricFermionR; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplF> CompactWilsonCloverTwoIndexSymmetricFermionF; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexSymmetricImplD> CompactWilsonCloverTwoIndexSymmetricFermionD; | ||||
|  | ||||
| typedef CompactWilsonClover<WilsonAdjImplF> CompactWilsonCloverAdjFermionF; | ||||
| typedef CompactWilsonClover<WilsonAdjImplD> CompactWilsonCloverAdjFermionD; | ||||
|  | ||||
| typedef CompactWilsonClover<WilsonTwoIndexSymmetricImplF> CompactWilsonCloverTwoIndexSymmetricFermionF; | ||||
| typedef CompactWilsonClover<WilsonTwoIndexSymmetricImplD> CompactWilsonCloverTwoIndexSymmetricFermionD; | ||||
|  | ||||
| typedef CompactWilsonClover<WilsonTwoIndexAntiSymmetricImplF> CompactWilsonCloverTwoIndexAntiSymmetricFermionF; | ||||
| typedef CompactWilsonClover<WilsonTwoIndexAntiSymmetricImplD> CompactWilsonCloverTwoIndexAntiSymmetricFermionD; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplR> CompactWilsonCloverTwoIndexAntiSymmetricFermionR; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplF> CompactWilsonCloverTwoIndexAntiSymmetricFermionF; | ||||
| typedef CompactWilsonCloverFermion<WilsonTwoIndexAntiSymmetricImplD> CompactWilsonCloverTwoIndexAntiSymmetricFermionD; | ||||
|  | ||||
| // Domain Wall fermions | ||||
| typedef DomainWallFermion<WilsonImplR> DomainWallFermionR; | ||||
| typedef DomainWallFermion<WilsonImplF> DomainWallFermionF; | ||||
| typedef DomainWallFermion<WilsonImplD> DomainWallFermionD; | ||||
| typedef DomainWallFermion<WilsonImplD2> DomainWallFermionD2; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<WilsonImplD2> DomainWallEOFAFermionD2; | ||||
| //typedef DomainWallFermion<WilsonImplRL> DomainWallFermionRL; | ||||
| //typedef DomainWallFermion<WilsonImplFH> DomainWallFermionFH; | ||||
| //typedef DomainWallFermion<WilsonImplDF> DomainWallFermionDF; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<WilsonImplR> DomainWallEOFAFermionR; | ||||
| typedef DomainWallEOFAFermion<WilsonImplF> DomainWallEOFAFermionF; | ||||
| typedef DomainWallEOFAFermion<WilsonImplD> DomainWallEOFAFermionD; | ||||
|  | ||||
| typedef MobiusFermion<WilsonImplD2> MobiusFermionD2; | ||||
| //typedef DomainWallEOFAFermion<WilsonImplRL> DomainWallEOFAFermionRL; | ||||
| //typedef DomainWallEOFAFermion<WilsonImplFH> DomainWallEOFAFermionFH; | ||||
| //typedef DomainWallEOFAFermion<WilsonImplDF> DomainWallEOFAFermionDF; | ||||
|  | ||||
| typedef MobiusFermion<WilsonImplR> MobiusFermionR; | ||||
| typedef MobiusFermion<WilsonImplF> MobiusFermionF; | ||||
| typedef MobiusFermion<WilsonImplD> MobiusFermionD; | ||||
|  | ||||
| typedef MobiusEOFAFermion<WilsonImplD2> MobiusEOFAFermionD2; | ||||
| //typedef MobiusFermion<WilsonImplRL> MobiusFermionRL; | ||||
| //typedef MobiusFermion<WilsonImplFH> MobiusFermionFH; | ||||
| //typedef MobiusFermion<WilsonImplDF> MobiusFermionDF; | ||||
|  | ||||
| typedef MobiusEOFAFermion<WilsonImplR> MobiusEOFAFermionR; | ||||
| typedef MobiusEOFAFermion<WilsonImplF> MobiusEOFAFermionF; | ||||
| typedef MobiusEOFAFermion<WilsonImplD> MobiusEOFAFermionD; | ||||
|  | ||||
| typedef ZMobiusFermion<ZWilsonImplD2> ZMobiusFermionD2; | ||||
| //typedef MobiusEOFAFermion<WilsonImplRL> MobiusEOFAFermionRL; | ||||
| //typedef MobiusEOFAFermion<WilsonImplFH> MobiusEOFAFermionFH; | ||||
| //typedef MobiusEOFAFermion<WilsonImplDF> MobiusEOFAFermionDF; | ||||
|  | ||||
| typedef ZMobiusFermion<ZWilsonImplR> ZMobiusFermionR; | ||||
| typedef ZMobiusFermion<ZWilsonImplF> ZMobiusFermionF; | ||||
| typedef ZMobiusFermion<ZWilsonImplD> ZMobiusFermionD; | ||||
|  | ||||
| typedef ScaledShamirFermion<WilsonImplD2> ScaledShamirFermionD2; | ||||
| //typedef ZMobiusFermion<ZWilsonImplRL> ZMobiusFermionRL; | ||||
| //typedef ZMobiusFermion<ZWilsonImplFH> ZMobiusFermionFH; | ||||
| //typedef ZMobiusFermion<ZWilsonImplDF> ZMobiusFermionDF; | ||||
|  | ||||
| // Ls vectorised | ||||
| typedef ScaledShamirFermion<WilsonImplR> ScaledShamirFermionR; | ||||
| typedef ScaledShamirFermion<WilsonImplF> ScaledShamirFermionF; | ||||
| typedef ScaledShamirFermion<WilsonImplD> ScaledShamirFermionD; | ||||
|  | ||||
| typedef MobiusZolotarevFermion<WilsonImplD2> MobiusZolotarevFermionD2; | ||||
| typedef MobiusZolotarevFermion<WilsonImplR> MobiusZolotarevFermionR; | ||||
| typedef MobiusZolotarevFermion<WilsonImplF> MobiusZolotarevFermionF; | ||||
| typedef MobiusZolotarevFermion<WilsonImplD> MobiusZolotarevFermionD; | ||||
| typedef ShamirZolotarevFermion<WilsonImplD2> ShamirZolotarevFermionD2; | ||||
| typedef ShamirZolotarevFermion<WilsonImplR> ShamirZolotarevFermionR; | ||||
| typedef ShamirZolotarevFermion<WilsonImplF> ShamirZolotarevFermionF; | ||||
| typedef ShamirZolotarevFermion<WilsonImplD> ShamirZolotarevFermionD; | ||||
|  | ||||
| typedef OverlapWilsonCayleyTanhFermion<WilsonImplD2> OverlapWilsonCayleyTanhFermionD2; | ||||
| typedef OverlapWilsonCayleyTanhFermion<WilsonImplR> OverlapWilsonCayleyTanhFermionR; | ||||
| typedef OverlapWilsonCayleyTanhFermion<WilsonImplF> OverlapWilsonCayleyTanhFermionF; | ||||
| typedef OverlapWilsonCayleyTanhFermion<WilsonImplD> OverlapWilsonCayleyTanhFermionD; | ||||
| typedef OverlapWilsonCayleyZolotarevFermion<WilsonImplD2> OverlapWilsonCayleyZolotarevFermionD2; | ||||
| typedef OverlapWilsonCayleyZolotarevFermion<WilsonImplR> OverlapWilsonCayleyZolotarevFermionR; | ||||
| typedef OverlapWilsonCayleyZolotarevFermion<WilsonImplF> OverlapWilsonCayleyZolotarevFermionF; | ||||
| typedef OverlapWilsonCayleyZolotarevFermion<WilsonImplD> OverlapWilsonCayleyZolotarevFermionD; | ||||
|  | ||||
| // Continued fraction | ||||
| typedef OverlapWilsonContFracTanhFermion<WilsonImplD2> OverlapWilsonContFracTanhFermionD2; | ||||
| typedef OverlapWilsonContFracTanhFermion<WilsonImplR> OverlapWilsonContFracTanhFermionR; | ||||
| typedef OverlapWilsonContFracTanhFermion<WilsonImplF> OverlapWilsonContFracTanhFermionF; | ||||
| typedef OverlapWilsonContFracTanhFermion<WilsonImplD> OverlapWilsonContFracTanhFermionD; | ||||
| typedef OverlapWilsonContFracZolotarevFermion<WilsonImplD2> OverlapWilsonContFracZolotarevFermionD2; | ||||
| typedef OverlapWilsonContFracZolotarevFermion<WilsonImplR> OverlapWilsonContFracZolotarevFermionR; | ||||
| typedef OverlapWilsonContFracZolotarevFermion<WilsonImplF> OverlapWilsonContFracZolotarevFermionF; | ||||
| typedef OverlapWilsonContFracZolotarevFermion<WilsonImplD> OverlapWilsonContFracZolotarevFermionD; | ||||
|  | ||||
| // Partial fraction | ||||
| typedef OverlapWilsonPartialFractionTanhFermion<WilsonImplD2> OverlapWilsonPartialFractionTanhFermionD2; | ||||
| typedef OverlapWilsonPartialFractionTanhFermion<WilsonImplR> OverlapWilsonPartialFractionTanhFermionR; | ||||
| typedef OverlapWilsonPartialFractionTanhFermion<WilsonImplF> OverlapWilsonPartialFractionTanhFermionF; | ||||
| typedef OverlapWilsonPartialFractionTanhFermion<WilsonImplD> OverlapWilsonPartialFractionTanhFermionD; | ||||
|  | ||||
| typedef OverlapWilsonPartialFractionZolotarevFermion<WilsonImplD2> OverlapWilsonPartialFractionZolotarevFermionD2; | ||||
| typedef OverlapWilsonPartialFractionZolotarevFermion<WilsonImplR> OverlapWilsonPartialFractionZolotarevFermionR; | ||||
| typedef OverlapWilsonPartialFractionZolotarevFermion<WilsonImplF> OverlapWilsonPartialFractionZolotarevFermionF; | ||||
| typedef OverlapWilsonPartialFractionZolotarevFermion<WilsonImplD> OverlapWilsonPartialFractionZolotarevFermionD; | ||||
|  | ||||
| // Gparity cases; partial list until tested | ||||
| typedef WilsonFermion<GparityWilsonImplR>     GparityWilsonFermionR; | ||||
| typedef WilsonFermion<GparityWilsonImplF>     GparityWilsonFermionF; | ||||
| typedef WilsonFermion<GparityWilsonImplD>     GparityWilsonFermionD; | ||||
|  | ||||
| //typedef WilsonFermion<GparityWilsonImplRL>     GparityWilsonFermionRL; | ||||
| //typedef WilsonFermion<GparityWilsonImplFH>     GparityWilsonFermionFH; | ||||
| //typedef WilsonFermion<GparityWilsonImplDF>     GparityWilsonFermionDF; | ||||
|  | ||||
| typedef DomainWallFermion<GparityWilsonImplR> GparityDomainWallFermionR; | ||||
| typedef DomainWallFermion<GparityWilsonImplF> GparityDomainWallFermionF; | ||||
| typedef DomainWallFermion<GparityWilsonImplD> GparityDomainWallFermionD; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplR> GparityDomainWallEOFAFermionD2; | ||||
| //typedef DomainWallFermion<GparityWilsonImplRL> GparityDomainWallFermionRL; | ||||
| //typedef DomainWallFermion<GparityWilsonImplFH> GparityDomainWallFermionFH; | ||||
| //typedef DomainWallFermion<GparityWilsonImplDF> GparityDomainWallFermionDF; | ||||
|  | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplR> GparityDomainWallEOFAFermionR; | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplF> GparityDomainWallEOFAFermionF; | ||||
| typedef DomainWallEOFAFermion<GparityWilsonImplD> GparityDomainWallEOFAFermionD; | ||||
|  | ||||
| typedef WilsonTMFermion<GparityWilsonImplR> GparityWilsonTMFermionD2; | ||||
| //typedef DomainWallEOFAFermion<GparityWilsonImplRL> GparityDomainWallEOFAFermionRL; | ||||
| //typedef DomainWallEOFAFermion<GparityWilsonImplFH> GparityDomainWallEOFAFermionFH; | ||||
| //typedef DomainWallEOFAFermion<GparityWilsonImplDF> GparityDomainWallEOFAFermionDF; | ||||
|  | ||||
| typedef WilsonTMFermion<GparityWilsonImplR> GparityWilsonTMFermionR; | ||||
| typedef WilsonTMFermion<GparityWilsonImplF> GparityWilsonTMFermionF; | ||||
| typedef WilsonTMFermion<GparityWilsonImplD> GparityWilsonTMFermionD; | ||||
|  | ||||
| typedef MobiusFermion<GparityWilsonImplR> GparityMobiusFermionD2; | ||||
| //typedef WilsonTMFermion<GparityWilsonImplRL> GparityWilsonTMFermionRL; | ||||
| //typedef WilsonTMFermion<GparityWilsonImplFH> GparityWilsonTMFermionFH; | ||||
| //typedef WilsonTMFermion<GparityWilsonImplDF> GparityWilsonTMFermionDF; | ||||
|  | ||||
| typedef MobiusFermion<GparityWilsonImplR> GparityMobiusFermionR; | ||||
| typedef MobiusFermion<GparityWilsonImplF> GparityMobiusFermionF; | ||||
| typedef MobiusFermion<GparityWilsonImplD> GparityMobiusFermionD; | ||||
|  | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplR> GparityMobiusEOFAFermionD2; | ||||
| //typedef MobiusFermion<GparityWilsonImplRL> GparityMobiusFermionRL; | ||||
| //typedef MobiusFermion<GparityWilsonImplFH> GparityMobiusFermionFH; | ||||
| //typedef MobiusFermion<GparityWilsonImplDF> GparityMobiusFermionDF; | ||||
|  | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplR> GparityMobiusEOFAFermionR; | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplF> GparityMobiusEOFAFermionF; | ||||
| typedef MobiusEOFAFermion<GparityWilsonImplD> GparityMobiusEOFAFermionD; | ||||
|  | ||||
| //typedef MobiusEOFAFermion<GparityWilsonImplRL> GparityMobiusEOFAFermionRL; | ||||
| //typedef MobiusEOFAFermion<GparityWilsonImplFH> GparityMobiusEOFAFermionFH; | ||||
| //typedef MobiusEOFAFermion<GparityWilsonImplDF> GparityMobiusEOFAFermionDF; | ||||
|  | ||||
| typedef ImprovedStaggeredFermion<StaggeredImplR> ImprovedStaggeredFermionR; | ||||
| typedef ImprovedStaggeredFermion<StaggeredImplF> ImprovedStaggeredFermionF; | ||||
| typedef ImprovedStaggeredFermion<StaggeredImplD> ImprovedStaggeredFermionD; | ||||
|  | ||||
| typedef NaiveStaggeredFermion<StaggeredImplR> NaiveStaggeredFermionR; | ||||
| typedef NaiveStaggeredFermion<StaggeredImplF> NaiveStaggeredFermionF; | ||||
| typedef NaiveStaggeredFermion<StaggeredImplD> NaiveStaggeredFermionD; | ||||
|  | ||||
| typedef ImprovedStaggeredFermion5D<StaggeredImplR> ImprovedStaggeredFermion5DR; | ||||
| typedef ImprovedStaggeredFermion5D<StaggeredImplF> ImprovedStaggeredFermion5DF; | ||||
| typedef ImprovedStaggeredFermion5D<StaggeredImplD> ImprovedStaggeredFermion5DD; | ||||
|  | ||||
|   | ||||
| @@ -49,8 +49,6 @@ public: | ||||
|  | ||||
|   virtual FermionField &tmp(void) = 0; | ||||
|  | ||||
|   virtual void DirichletBlock(const Coordinate & _Block) { assert(0); }; | ||||
|    | ||||
|   GridBase * Grid(void)   { return FermionGrid(); };   // this is all the linalg routines need to know | ||||
|   GridBase * RedBlackGrid(void) { return FermionRedBlackGrid(); }; | ||||
|  | ||||
|   | ||||
| @@ -47,6 +47,18 @@ public: | ||||
|   FermionField _tmp; | ||||
|   FermionField &tmp(void) { return _tmp; } | ||||
|  | ||||
|   //////////////////////////////////////// | ||||
|   // Performance monitoring | ||||
|   //////////////////////////////////////// | ||||
|   void Report(void); | ||||
|   void ZeroCounters(void); | ||||
|   double DhopTotalTime; | ||||
|   double DhopCalls; | ||||
|   double DhopCommTime; | ||||
|   double DhopComputeTime; | ||||
|   double DhopComputeTime2; | ||||
|   double DhopFaceTime; | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Implement the abstract base | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -52,6 +52,18 @@ public: | ||||
|   FermionField _tmp; | ||||
|   FermionField &tmp(void) { return _tmp; } | ||||
|  | ||||
|   //////////////////////////////////////// | ||||
|   // Performance monitoring | ||||
|   //////////////////////////////////////// | ||||
|   void Report(void); | ||||
|   void ZeroCounters(void); | ||||
|   double DhopTotalTime; | ||||
|   double DhopCalls; | ||||
|   double DhopCommTime; | ||||
|   double DhopComputeTime; | ||||
|   double DhopComputeTime2; | ||||
|   double DhopFaceTime; | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Implement the abstract base | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -47,6 +47,18 @@ public: | ||||
|   FermionField _tmp; | ||||
|   FermionField &tmp(void) { return _tmp; } | ||||
|  | ||||
|   //////////////////////////////////////// | ||||
|   // Performance monitoring | ||||
|   //////////////////////////////////////// | ||||
|   void Report(void); | ||||
|   void ZeroCounters(void); | ||||
|   double DhopTotalTime; | ||||
|   double DhopCalls; | ||||
|   double DhopCommTime; | ||||
|   double DhopComputeTime; | ||||
|   double DhopComputeTime2; | ||||
|   double DhopFaceTime; | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Implement the abstract base | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -32,7 +32,6 @@ | ||||
|  | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverTypes.h> | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverHelpers.h> | ||||
| #include <Grid/qcd/action/fermion/CloverHelpers.h> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| @@ -52,7 +51,7 @@ NAMESPACE_BEGIN(Grid); | ||||
| // csw_r = csw_t to recover the isotropic version | ||||
| ////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| template <class Impl> | ||||
| class WilsonCloverFermion : public WilsonFermion<Impl>, | ||||
|                             public WilsonCloverHelpers<Impl> | ||||
| { | ||||
|   | ||||
| @@ -209,8 +209,6 @@ public: | ||||
| }; | ||||
|  | ||||
|  | ||||
| //////////////////////////////////////////////////////// | ||||
|  | ||||
| template<class Impl> class CompactWilsonCloverHelpers { | ||||
| public: | ||||
|  | ||||
|   | ||||
| @@ -47,6 +47,8 @@ class CompactWilsonCloverTypes { | ||||
| public: | ||||
|   INHERIT_IMPL_TYPES(Impl); | ||||
|  | ||||
|   static_assert(Nd == 4 && Nc == 3 && Ns == 4 && Impl::Dimension == 3, "Wrong dimensions"); | ||||
|  | ||||
|   static constexpr int Nred      = Nc * Nhs;        // 6 | ||||
|   static constexpr int Nblock    = Nhs;             // 2 | ||||
|   static constexpr int Ndiagonal = Nred;            // 6 | ||||
|   | ||||
| @@ -32,218 +32,17 @@ Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| /////////////////////////////////////////////////////////////// | ||||
| // Wilson compressor will need FaceGather policies for: | ||||
| // Periodic, Dirichlet, and partial Dirichlet for DWF | ||||
| /////////////////////////////////////////////////////////////// | ||||
| const int dwf_compressor_depth=2; | ||||
| #define DWF_COMPRESS | ||||
| class FaceGatherPartialDWF | ||||
| { | ||||
| public: | ||||
| #ifdef DWF_COMPRESS | ||||
|   static int PartialCompressionFactor(GridBase *grid) {return grid->_fdimensions[0]/(2*dwf_compressor_depth);}; | ||||
| #else | ||||
|   static int PartialCompressionFactor(GridBase *grid) { return 1;} | ||||
| #endif | ||||
|   template<class vobj,class cobj,class compressor> | ||||
|   static void Gather_plane_simple (commVector<std::pair<int,int> >& table, | ||||
| 				   const Lattice<vobj> &rhs, | ||||
| 				   cobj *buffer, | ||||
| 				   compressor &compress, | ||||
| 				   int off,int so,int partial) | ||||
|   { | ||||
|     //DWF only hack: If a direction that is OFF node we use Partial Dirichlet | ||||
|     //  Shrinks local and remote comms buffers | ||||
|     GridBase *Grid = rhs.Grid(); | ||||
|     int Ls = Grid->_rdimensions[0]; | ||||
| #ifdef DWF_COMPRESS | ||||
|     int depth=dwf_compressor_depth; | ||||
| #else  | ||||
|     int depth=Ls/2; | ||||
| #endif | ||||
|     std::pair<int,int> *table_v = & table[0]; | ||||
|     auto rhs_v = rhs.View(AcceleratorRead); | ||||
|     int vol=table.size()/Ls; | ||||
|     accelerator_forNB( idx,table.size(), vobj::Nsimd(), { | ||||
| 	Integer i=idx/Ls; | ||||
| 	Integer s=idx%Ls; | ||||
| 	Integer sc=depth+s-(Ls-depth); | ||||
| 	if(s<depth)     compress.Compress(buffer[off+i+s*vol],rhs_v[so+table_v[idx].second]); | ||||
| 	if(s>=Ls-depth) compress.Compress(buffer[off+i+sc*vol],rhs_v[so+table_v[idx].second]); | ||||
|     }); | ||||
|     rhs_v.ViewClose(); | ||||
|   } | ||||
|   template<class decompressor,class Decompression> | ||||
|   static void DecompressFace(decompressor decompress,Decompression &dd) | ||||
|   { | ||||
|     auto Ls = dd.dims[0]; | ||||
| #ifdef DWF_COMPRESS | ||||
|     int depth=dwf_compressor_depth; | ||||
| #else | ||||
|     int depth=Ls/2; | ||||
| #endif     | ||||
|     // Just pass in the Grid | ||||
|     auto kp = dd.kernel_p; | ||||
|     auto mp = dd.mpi_p; | ||||
|     int size= dd.buffer_size; | ||||
|     int vol= size/Ls; | ||||
|     accelerator_forNB(o,size,1,{ | ||||
| 	int idx=o/Ls; | ||||
| 	int   s=o%Ls; | ||||
| 	if ( s < depth ) { | ||||
| 	  int oo=s*vol+idx; | ||||
| 	  kp[o]=mp[oo]; | ||||
| 	} else if ( s >= Ls-depth ) { | ||||
| 	  int sc = depth + s - (Ls-depth); | ||||
| 	  int oo=sc*vol+idx;  | ||||
| 	  kp[o]=mp[oo]; | ||||
| 	} else { | ||||
| 	  kp[o] = Zero();//fill rest with zero if partial dirichlet | ||||
| 	} | ||||
|     }); | ||||
|   } | ||||
|   //////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Need to gather *interior portions* for ALL s-slices in simd directions | ||||
|   // Do the gather as need to treat SIMD lanes differently, and insert zeroes on receive side | ||||
|   // Reorder the fifth dim to be s=Ls-1 , s=0, s=1,...,Ls-2. | ||||
|   //////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   template<class vobj,class cobj,class compressor> | ||||
|   static void Gather_plane_exchange(commVector<std::pair<int,int> >& table,const Lattice<vobj> &rhs, | ||||
| 				    std::vector<cobj *> pointers,int dimension,int plane,int cbmask, | ||||
| 				    compressor &compress,int type,int partial) | ||||
|   { | ||||
|     GridBase *Grid = rhs.Grid(); | ||||
|     int Ls = Grid->_rdimensions[0]; | ||||
| #ifdef DWF_COMPRESS | ||||
|     int depth=dwf_compressor_depth; | ||||
| #else | ||||
|     int depth = Ls/2; | ||||
| #endif | ||||
|      | ||||
|     // insertion of zeroes... | ||||
|     assert( (table.size()&0x1)==0); | ||||
|     int num=table.size()/2; | ||||
|     int so  = plane*rhs.Grid()->_ostride[dimension]; // base offset for start of plane | ||||
|      | ||||
|     auto rhs_v = rhs.View(AcceleratorRead); | ||||
|     auto p0=&pointers[0][0]; | ||||
|     auto p1=&pointers[1][0]; | ||||
|     auto tp=&table[0]; | ||||
|     int nnum=num/Ls; | ||||
|     accelerator_forNB(j, num, vobj::Nsimd(), { | ||||
| 	//  Reorders both local and remote comms buffers | ||||
| 	//   | ||||
| 	int s  = j % Ls; | ||||
| 	int sp1 = (s+depth)%Ls;  // peri incremented s slice | ||||
| 	 | ||||
| 	int hxyz= j/Ls; | ||||
|  | ||||
| 	int xyz0= hxyz*2; // xyzt part of coor | ||||
| 	int xyz1= hxyz*2+1; | ||||
| 	 | ||||
| 	int jj= hxyz + sp1*nnum ; // 0,1,2,3 -> Ls-1 slice , 0-slice, 1-slice .... | ||||
| 	 | ||||
| 	int kk0= xyz0*Ls + s ; // s=0 goes to s=1 | ||||
| 	int kk1= xyz1*Ls + s ; // s=Ls-1 -> s=0 | ||||
| 	compress.CompressExchange(p0[jj],p1[jj], | ||||
| 				  rhs_v[so+tp[kk0 ].second], // Same s, consecutive xyz sites | ||||
| 				  rhs_v[so+tp[kk1 ].second],  | ||||
| 				  type); | ||||
|     }); | ||||
|     rhs_v.ViewClose(); | ||||
|   } | ||||
|   // Merge routine is for SIMD faces | ||||
|   template<class decompressor,class Merger> | ||||
|   static void MergeFace(decompressor decompress,Merger &mm) | ||||
|   { | ||||
|     auto Ls = mm.dims[0]; | ||||
| #ifdef DWF_COMPRESS | ||||
|     int depth=dwf_compressor_depth; | ||||
| #else | ||||
|     int depth = Ls/2; | ||||
| #endif | ||||
|     int  num= mm.buffer_size/2; // relate vol and Ls to buffer size | ||||
|     auto mp = &mm.mpointer[0]; | ||||
|     auto vp0= &mm.vpointers[0][0]; // First arg is exchange first | ||||
|     auto vp1= &mm.vpointers[1][0]; | ||||
|     auto type= mm.type; | ||||
|     int nnum = num/Ls; | ||||
|     accelerator_forNB(o,num,Merger::Nsimd,{ | ||||
|  | ||||
| 	int  s=o%Ls; | ||||
| 	int hxyz=o/Ls; // xyzt related component | ||||
| 	int xyz0=hxyz*2; | ||||
| 	int xyz1=hxyz*2+1; | ||||
|  | ||||
| 	int sp = (s+depth)%Ls;  | ||||
| 	int jj= hxyz + sp*nnum ; // 0,1,2,3 -> Ls-1 slice , 0-slice, 1-slice .... | ||||
|  | ||||
| 	int oo0= s+xyz0*Ls; | ||||
| 	int oo1= s+xyz1*Ls; | ||||
|  | ||||
| 	// same ss0, ss1 pair goes to new layout | ||||
| 	decompress.Exchange(mp[oo0],mp[oo1],vp0[jj],vp1[jj],type); | ||||
|       }); | ||||
|   } | ||||
| }; | ||||
| class FaceGatherDWFMixedBCs | ||||
| { | ||||
| public: | ||||
| #ifdef DWF_COMPRESS | ||||
|   static int PartialCompressionFactor(GridBase *grid) {return grid->_fdimensions[0]/(2*dwf_compressor_depth);}; | ||||
| #else  | ||||
|   static int PartialCompressionFactor(GridBase *grid) {return 1;} | ||||
| #endif | ||||
|    | ||||
|   template<class vobj,class cobj,class compressor> | ||||
|   static void Gather_plane_simple (commVector<std::pair<int,int> >& table, | ||||
| 					 const Lattice<vobj> &rhs, | ||||
| 					 cobj *buffer, | ||||
| 					 compressor &compress, | ||||
| 					 int off,int so,int partial) | ||||
|   { | ||||
|     //    std::cout << " face gather simple DWF partial "<<partial <<std::endl; | ||||
|     if(partial) FaceGatherPartialDWF::Gather_plane_simple(table,rhs,buffer,compress,off,so,partial); | ||||
|     else        FaceGatherSimple::Gather_plane_simple(table,rhs,buffer,compress,off,so,partial); | ||||
|   } | ||||
|   template<class vobj,class cobj,class compressor> | ||||
|   static void Gather_plane_exchange(commVector<std::pair<int,int> >& table,const Lattice<vobj> &rhs, | ||||
| 				    std::vector<cobj *> pointers,int dimension,int plane,int cbmask, | ||||
| 				    compressor &compress,int type,int partial) | ||||
|   { | ||||
|     //    std::cout << " face gather exch DWF partial "<<partial <<std::endl; | ||||
|     if(partial) FaceGatherPartialDWF::Gather_plane_exchange(table,rhs,pointers,dimension, plane,cbmask,compress,type,partial); | ||||
|     else        FaceGatherSimple::Gather_plane_exchange    (table,rhs,pointers,dimension, plane,cbmask,compress,type,partial); | ||||
|   } | ||||
|   template<class decompressor,class Merger> | ||||
|   static void MergeFace(decompressor decompress,Merger &mm) | ||||
|   { | ||||
|     int partial = mm.partial; | ||||
|     //    std::cout << " merge DWF partial "<<partial <<std::endl; | ||||
|     if ( partial ) FaceGatherPartialDWF::MergeFace(decompress,mm); | ||||
|     else           FaceGatherSimple::MergeFace(decompress,mm); | ||||
|   } | ||||
|  | ||||
|   template<class decompressor,class Decompression> | ||||
|   static void DecompressFace(decompressor decompress,Decompression &dd) | ||||
|   { | ||||
|     int partial = dd.partial; | ||||
|     //    std::cout << " decompress DWF partial "<<partial <<std::endl; | ||||
|     if ( partial ) FaceGatherPartialDWF::DecompressFace(decompress,dd); | ||||
|     else           FaceGatherSimple::DecompressFace(decompress,dd); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////// | ||||
| // optimised versions supporting half precision too??? Deprecate | ||||
| // optimised versions supporting half precision too | ||||
| ///////////////////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| template<class _HCspinor,class _Hspinor,class _Spinor, class projector,typename SFINAE = void > | ||||
| class WilsonCompressorTemplate; | ||||
|  | ||||
|  | ||||
| //Could make FaceGather a template param, but then behaviour is runtime not compile time | ||||
| template<class _HCspinor,class _Hspinor,class _Spinor, class projector> | ||||
| class WilsonCompressorTemplate  : public FaceGatherDWFMixedBCs | ||||
| //  : public FaceGatherSimple | ||||
| class WilsonCompressorTemplate< _HCspinor, _Hspinor, _Spinor, projector, | ||||
| 				typename std::enable_if<std::is_same<_HCspinor,_Hspinor>::value>::type > | ||||
| { | ||||
| public: | ||||
|    | ||||
| @@ -280,19 +79,18 @@ public: | ||||
|   /*****************************************************/ | ||||
|   /* Exchange includes precision change if mpi data is not same */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline void Exchange(SiteHalfSpinor &mp0, | ||||
| 				   SiteHalfSpinor &mp1, | ||||
| 				   const SiteHalfSpinor & vp0, | ||||
| 				   const SiteHalfSpinor & vp1, | ||||
| 				   Integer type) const { | ||||
|   accelerator_inline void Exchange(SiteHalfSpinor *mp, | ||||
| 				   const SiteHalfSpinor * __restrict__ vp0, | ||||
| 				   const SiteHalfSpinor * __restrict__ vp1, | ||||
| 				   Integer type,Integer o) const { | ||||
| #ifdef GRID_SIMT | ||||
|     exchangeSIMT(mp0,mp1,vp0,vp1,type); | ||||
|     exchangeSIMT(mp[2*o],mp[2*o+1],vp0[o],vp1[o],type); | ||||
| #else | ||||
|     SiteHalfSpinor tmp1; | ||||
|     SiteHalfSpinor tmp2; | ||||
|     exchange(tmp1,tmp2,vp0,vp1,type); | ||||
|     vstream(mp0,tmp1); | ||||
|     vstream(mp1,tmp2); | ||||
|     exchange(tmp1,tmp2,vp0[o],vp1[o],type); | ||||
|     vstream(mp[2*o  ],tmp1); | ||||
|     vstream(mp[2*o+1],tmp2); | ||||
| #endif | ||||
|   } | ||||
|  | ||||
| @@ -300,61 +98,153 @@ public: | ||||
|   /*****************************************************/ | ||||
|   /* Have a decompression step if mpi data is not same */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline void Decompress(SiteHalfSpinor &out, | ||||
| 				     SiteHalfSpinor &in) const {     | ||||
|     out = in; | ||||
|   accelerator_inline void Decompress(SiteHalfSpinor * __restrict__ out, | ||||
| 				     SiteHalfSpinor * __restrict__ in, Integer o) const {     | ||||
|     assert(0); | ||||
|   } | ||||
|  | ||||
|   /*****************************************************/ | ||||
|   /* Compress Exchange                                 */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline void CompressExchange(SiteHalfSpinor &out0, | ||||
| 					   SiteHalfSpinor &out1, | ||||
| 					   const SiteSpinor &in0, | ||||
| 					   const SiteSpinor &in1, | ||||
| 					   Integer type) const | ||||
|   accelerator_inline void CompressExchange(SiteHalfSpinor * __restrict__ out0, | ||||
| 					   SiteHalfSpinor * __restrict__ out1, | ||||
| 					   const SiteSpinor * __restrict__ in, | ||||
| 					   Integer j,Integer k, Integer m,Integer type) const | ||||
|   { | ||||
| #ifdef GRID_SIMT | ||||
|     typedef SiteSpinor vobj; | ||||
|     typedef SiteHalfSpinor hvobj; | ||||
|     typedef decltype(coalescedRead(in0))    sobj; | ||||
|     typedef decltype(coalescedRead(out0)) hsobj; | ||||
|     typedef decltype(coalescedRead(*in))    sobj; | ||||
|     typedef decltype(coalescedRead(*out0)) hsobj; | ||||
|  | ||||
|     constexpr unsigned int Nsimd = vobj::Nsimd(); | ||||
|     unsigned int Nsimd = vobj::Nsimd(); | ||||
|     unsigned int mask = Nsimd >> (type + 1); | ||||
|     int lane = acceleratorSIMTlane(Nsimd); | ||||
|     int j0 = lane &(~mask); // inner coor zero | ||||
|     int j1 = lane |(mask) ; // inner coor one | ||||
|     const vobj *vp0 = &in0; | ||||
|     const vobj *vp1 = &in1; | ||||
|     const vobj *vp0 = &in[k]; | ||||
|     const vobj *vp1 = &in[m]; | ||||
|     const vobj *vp = (lane&mask) ? vp1:vp0; | ||||
|     auto sa = coalescedRead(*vp,j0); | ||||
|     auto sb = coalescedRead(*vp,j1); | ||||
|     hsobj psa, psb; | ||||
|     projector::Proj(psa,sa,mu,dag); | ||||
|     projector::Proj(psb,sb,mu,dag); | ||||
|     coalescedWrite(out0,psa); | ||||
|     coalescedWrite(out1,psb); | ||||
|     coalescedWrite(out0[j],psa); | ||||
|     coalescedWrite(out1[j],psb); | ||||
| #else | ||||
|     SiteHalfSpinor temp1, temp2; | ||||
|     SiteHalfSpinor temp3, temp4; | ||||
|     projector::Proj(temp1,in0,mu,dag); | ||||
|     projector::Proj(temp2,in1,mu,dag); | ||||
|     projector::Proj(temp1,in[k],mu,dag); | ||||
|     projector::Proj(temp2,in[m],mu,dag); | ||||
|     exchange(temp3,temp4,temp1,temp2,type); | ||||
|     vstream(out0,temp3); | ||||
|     vstream(out1,temp4); | ||||
|     vstream(out0[j],temp3); | ||||
|     vstream(out1[j],temp4); | ||||
| #endif | ||||
|   } | ||||
|  | ||||
|   /*****************************************************/ | ||||
|   /* Pass the info to the stencil */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline bool DecompressionStep(void) const { | ||||
|     return false; | ||||
|   } | ||||
|   accelerator_inline bool DecompressionStep(void) const { return false; } | ||||
|  | ||||
| }; | ||||
|  | ||||
| #if 0 | ||||
| template<class _HCspinor,class _Hspinor,class _Spinor, class projector> | ||||
| class WilsonCompressorTemplate< _HCspinor, _Hspinor, _Spinor, projector, | ||||
| 				typename std::enable_if<!std::is_same<_HCspinor,_Hspinor>::value>::type > | ||||
| { | ||||
| public: | ||||
|    | ||||
|   int mu,dag;   | ||||
|  | ||||
|   void Point(int p) { mu=p; }; | ||||
|  | ||||
|   WilsonCompressorTemplate(int _dag=0){ | ||||
|     dag = _dag; | ||||
|   } | ||||
|  | ||||
|   typedef _Spinor         SiteSpinor; | ||||
|   typedef _Hspinor     SiteHalfSpinor; | ||||
|   typedef _HCspinor SiteHalfCommSpinor; | ||||
|   typedef typename SiteHalfCommSpinor::vector_type vComplexLow; | ||||
|   typedef typename SiteHalfSpinor::vector_type     vComplexHigh; | ||||
|   constexpr static int Nw=sizeof(SiteHalfSpinor)/sizeof(vComplexHigh); | ||||
|  | ||||
|   accelerator_inline int CommDatumSize(void) const { | ||||
|     return sizeof(SiteHalfCommSpinor); | ||||
|   } | ||||
|  | ||||
|   /*****************************************************/ | ||||
|   /* Compress includes precision change if mpi data is not same */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline void Compress(SiteHalfSpinor &buf,const SiteSpinor &in) const { | ||||
|     SiteHalfSpinor hsp; | ||||
|     SiteHalfCommSpinor *hbuf = (SiteHalfCommSpinor *)buf; | ||||
|     projector::Proj(hsp,in,mu,dag); | ||||
|     precisionChange((vComplexLow *)&hbuf[o],(vComplexHigh *)&hsp,Nw); | ||||
|   } | ||||
|   accelerator_inline void Compress(SiteHalfSpinor &buf,const SiteSpinor &in) const { | ||||
| #ifdef GRID_SIMT | ||||
|     typedef decltype(coalescedRead(buf)) sobj; | ||||
|     sobj sp; | ||||
|     auto sin = coalescedRead(in); | ||||
|     projector::Proj(sp,sin,mu,dag); | ||||
|     coalescedWrite(buf,sp); | ||||
| #else | ||||
|     projector::Proj(buf,in,mu,dag); | ||||
| #endif | ||||
|   } | ||||
|  | ||||
|   /*****************************************************/ | ||||
|   /* Exchange includes precision change if mpi data is not same */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline void Exchange(SiteHalfSpinor *mp, | ||||
|                        SiteHalfSpinor *vp0, | ||||
|                        SiteHalfSpinor *vp1, | ||||
| 		       Integer type,Integer o) const { | ||||
|     SiteHalfSpinor vt0,vt1; | ||||
|     SiteHalfCommSpinor *vpp0 = (SiteHalfCommSpinor *)vp0; | ||||
|     SiteHalfCommSpinor *vpp1 = (SiteHalfCommSpinor *)vp1; | ||||
|     precisionChange((vComplexHigh *)&vt0,(vComplexLow *)&vpp0[o],Nw); | ||||
|     precisionChange((vComplexHigh *)&vt1,(vComplexLow *)&vpp1[o],Nw); | ||||
|     exchange(mp[2*o],mp[2*o+1],vt0,vt1,type); | ||||
|   } | ||||
|  | ||||
|   /*****************************************************/ | ||||
|   /* Have a decompression step if mpi data is not same */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline void Decompress(SiteHalfSpinor *out, SiteHalfSpinor *in, Integer o) const { | ||||
|     SiteHalfCommSpinor *hin=(SiteHalfCommSpinor *)in; | ||||
|     precisionChange((vComplexHigh *)&out[o],(vComplexLow *)&hin[o],Nw); | ||||
|   } | ||||
|  | ||||
|   /*****************************************************/ | ||||
|   /* Compress Exchange                                 */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline void CompressExchange(SiteHalfSpinor *out0, | ||||
| 			       SiteHalfSpinor *out1, | ||||
| 			       const SiteSpinor *in, | ||||
| 			       Integer j,Integer k, Integer m,Integer type) const { | ||||
|     SiteHalfSpinor temp1, temp2,temp3,temp4; | ||||
|     SiteHalfCommSpinor *hout0 = (SiteHalfCommSpinor *)out0; | ||||
|     SiteHalfCommSpinor *hout1 = (SiteHalfCommSpinor *)out1; | ||||
|     projector::Proj(temp1,in[k],mu,dag); | ||||
|     projector::Proj(temp2,in[m],mu,dag); | ||||
|     exchange(temp3,temp4,temp1,temp2,type); | ||||
|     precisionChange((vComplexLow *)&hout0[j],(vComplexHigh *)&temp3,Nw); | ||||
|     precisionChange((vComplexLow *)&hout1[j],(vComplexHigh *)&temp4,Nw); | ||||
|   } | ||||
|  | ||||
|   /*****************************************************/ | ||||
|   /* Pass the info to the stencil */ | ||||
|   /*****************************************************/ | ||||
|   accelerator_inline bool DecompressionStep(void) const { return true; } | ||||
|  | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| #define DECLARE_PROJ(Projector,Compressor,spProj)			\ | ||||
|   class Projector {							\ | ||||
|   public:								\ | ||||
| @@ -404,7 +294,11 @@ public: | ||||
|   typedef typename Base::View_type View_type; | ||||
|   typedef typename Base::StencilVector StencilVector; | ||||
|  | ||||
|   //  Vector<int> surface_list; | ||||
|   void ZeroCountersi(void)  {  } | ||||
|   void Reporti(int calls)  {  } | ||||
|  | ||||
|   std::vector<int> surface_list; | ||||
|  | ||||
|   WilsonStencil(GridBase *grid, | ||||
| 		int npoints, | ||||
| 		int checkerboard, | ||||
| @@ -412,11 +306,11 @@ public: | ||||
| 		const std::vector<int> &distances,Parameters p)   | ||||
|     : CartesianStencil<vobj,cobj,Parameters> (grid,npoints,checkerboard,directions,distances,p)  | ||||
|   {  | ||||
|     //    surface_list.resize(0); | ||||
|     ZeroCountersi(); | ||||
|     surface_list.resize(0); | ||||
|     this->same_node.resize(npoints); | ||||
|   }; | ||||
|  | ||||
|   /* | ||||
|   void BuildSurfaceList(int Ls,int vol4){ | ||||
|  | ||||
|     // find same node for SHM | ||||
| @@ -437,7 +331,6 @@ public: | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   */ | ||||
|  | ||||
|   template < class compressor> | ||||
|   void HaloExchangeOpt(const Lattice<vobj> &source,compressor &compress)  | ||||
| @@ -484,29 +377,28 @@ public: | ||||
|  | ||||
|     int dag = compress.dag; | ||||
|     int face_idx=0; | ||||
| #define vet_same_node(a,b) \ | ||||
|       { auto tmp = b;  } | ||||
|     if ( dag ) {  | ||||
|       vet_same_node(this->same_node[Xp],this->HaloGatherDir(source,XpCompress,Xp,face_idx)); | ||||
|       vet_same_node(this->same_node[Yp],this->HaloGatherDir(source,YpCompress,Yp,face_idx)); | ||||
|       vet_same_node(this->same_node[Zp],this->HaloGatherDir(source,ZpCompress,Zp,face_idx)); | ||||
|       vet_same_node(this->same_node[Tp],this->HaloGatherDir(source,TpCompress,Tp,face_idx)); | ||||
|       vet_same_node(this->same_node[Xm],this->HaloGatherDir(source,XmCompress,Xm,face_idx)); | ||||
|       vet_same_node(this->same_node[Ym],this->HaloGatherDir(source,YmCompress,Ym,face_idx)); | ||||
|       vet_same_node(this->same_node[Zm],this->HaloGatherDir(source,ZmCompress,Zm,face_idx)); | ||||
|       vet_same_node(this->same_node[Tm],this->HaloGatherDir(source,TmCompress,Tm,face_idx)); | ||||
|       assert(this->same_node[Xp]==this->HaloGatherDir(source,XpCompress,Xp,face_idx)); | ||||
|       assert(this->same_node[Yp]==this->HaloGatherDir(source,YpCompress,Yp,face_idx)); | ||||
|       assert(this->same_node[Zp]==this->HaloGatherDir(source,ZpCompress,Zp,face_idx)); | ||||
|       assert(this->same_node[Tp]==this->HaloGatherDir(source,TpCompress,Tp,face_idx)); | ||||
|       assert(this->same_node[Xm]==this->HaloGatherDir(source,XmCompress,Xm,face_idx)); | ||||
|       assert(this->same_node[Ym]==this->HaloGatherDir(source,YmCompress,Ym,face_idx)); | ||||
|       assert(this->same_node[Zm]==this->HaloGatherDir(source,ZmCompress,Zm,face_idx)); | ||||
|       assert(this->same_node[Tm]==this->HaloGatherDir(source,TmCompress,Tm,face_idx)); | ||||
|     } else { | ||||
|       vet_same_node(this->same_node[Xp],this->HaloGatherDir(source,XmCompress,Xp,face_idx)); | ||||
|       vet_same_node(this->same_node[Yp],this->HaloGatherDir(source,YmCompress,Yp,face_idx)); | ||||
|       vet_same_node(this->same_node[Zp],this->HaloGatherDir(source,ZmCompress,Zp,face_idx)); | ||||
|       vet_same_node(this->same_node[Tp],this->HaloGatherDir(source,TmCompress,Tp,face_idx)); | ||||
|       vet_same_node(this->same_node[Xm],this->HaloGatherDir(source,XpCompress,Xm,face_idx)); | ||||
|       vet_same_node(this->same_node[Ym],this->HaloGatherDir(source,YpCompress,Ym,face_idx)); | ||||
|       vet_same_node(this->same_node[Zm],this->HaloGatherDir(source,ZpCompress,Zm,face_idx)); | ||||
|       vet_same_node(this->same_node[Tm],this->HaloGatherDir(source,TpCompress,Tm,face_idx)); | ||||
|       assert(this->same_node[Xp]==this->HaloGatherDir(source,XmCompress,Xp,face_idx)); | ||||
|       assert(this->same_node[Yp]==this->HaloGatherDir(source,YmCompress,Yp,face_idx)); | ||||
|       assert(this->same_node[Zp]==this->HaloGatherDir(source,ZmCompress,Zp,face_idx)); | ||||
|       assert(this->same_node[Tp]==this->HaloGatherDir(source,TmCompress,Tp,face_idx)); | ||||
|       assert(this->same_node[Xm]==this->HaloGatherDir(source,XpCompress,Xm,face_idx)); | ||||
|       assert(this->same_node[Ym]==this->HaloGatherDir(source,YpCompress,Ym,face_idx)); | ||||
|       assert(this->same_node[Zm]==this->HaloGatherDir(source,ZpCompress,Zm,face_idx)); | ||||
|       assert(this->same_node[Tm]==this->HaloGatherDir(source,TpCompress,Tm,face_idx)); | ||||
|     } | ||||
|     this->face_table_computed=1; | ||||
|     assert(this->u_comm_offset==this->_unified_buffer_size); | ||||
|     accelerator_barrier(); | ||||
|   } | ||||
|  | ||||
| }; | ||||
|   | ||||
| @@ -74,6 +74,20 @@ public: | ||||
|   FermionField _tmp; | ||||
|   FermionField &tmp(void) { return _tmp; } | ||||
|  | ||||
|   void Report(void); | ||||
|   void ZeroCounters(void); | ||||
|   double DhopCalls; | ||||
|   double DhopCommTime; | ||||
|   double DhopComputeTime; | ||||
|   double DhopComputeTime2; | ||||
|   double DhopFaceTime; | ||||
|   double DhopTotalTime; | ||||
|  | ||||
|   double DerivCalls; | ||||
|   double DerivCommTime; | ||||
|   double DerivComputeTime; | ||||
|   double DerivDhopComputeTime; | ||||
|  | ||||
|   ////////////////////////////////////////////////////////////////// | ||||
|   // override multiply; cut number routines if pass dagger argument | ||||
|   // and also make interface more uniformly consistent | ||||
|   | ||||
| @@ -75,8 +75,19 @@ public: | ||||
|   FermionField _tmp; | ||||
|   FermionField &tmp(void) { return _tmp; } | ||||
|  | ||||
|   int Dirichlet; | ||||
|   Coordinate Block;  | ||||
|   void Report(void); | ||||
|   void ZeroCounters(void); | ||||
|   double DhopCalls; | ||||
|   double DhopCommTime; | ||||
|   double DhopComputeTime; | ||||
|   double DhopComputeTime2; | ||||
|   double DhopFaceTime; | ||||
|   double DhopTotalTime; | ||||
|  | ||||
|   double DerivCalls; | ||||
|   double DerivCommTime; | ||||
|   double DerivComputeTime; | ||||
|   double DerivDhopComputeTime; | ||||
|  | ||||
|   /////////////////////////////////////////////////////////////// | ||||
|   // Implement the abstract base | ||||
| @@ -163,9 +174,6 @@ public: | ||||
| 		  GridRedBlackCartesian &FourDimRedBlackGrid, | ||||
| 		  double _M5,const ImplParams &p= ImplParams()); | ||||
|      | ||||
|   virtual void DirichletBlock(const Coordinate & block) | ||||
|   { | ||||
|   } | ||||
|   // Constructors | ||||
|   /* | ||||
|     WilsonFermion5D(int simd,  | ||||
|   | ||||
| @@ -242,12 +242,18 @@ public: | ||||
| typedef WilsonImpl<vComplex,  FundamentalRepresentation, CoeffReal > WilsonImplR;  // Real.. whichever prec | ||||
| typedef WilsonImpl<vComplexF, FundamentalRepresentation, CoeffReal > WilsonImplF;  // Float | ||||
| typedef WilsonImpl<vComplexD, FundamentalRepresentation, CoeffReal > WilsonImplD;  // Double | ||||
| typedef WilsonImpl<vComplexD2, FundamentalRepresentation, CoeffReal > WilsonImplD2;  // Double | ||||
|  | ||||
| //typedef WilsonImpl<vComplex,  FundamentalRepresentation, CoeffRealHalfComms > WilsonImplRL;  // Real.. whichever prec | ||||
| //typedef WilsonImpl<vComplexF, FundamentalRepresentation, CoeffRealHalfComms > WilsonImplFH;  // Float | ||||
| //typedef WilsonImpl<vComplexD, FundamentalRepresentation, CoeffRealHalfComms > WilsonImplDF;  // Double | ||||
|  | ||||
| typedef WilsonImpl<vComplex,  FundamentalRepresentation, CoeffComplex > ZWilsonImplR; // Real.. whichever prec | ||||
| typedef WilsonImpl<vComplexF, FundamentalRepresentation, CoeffComplex > ZWilsonImplF; // Float | ||||
| typedef WilsonImpl<vComplexD, FundamentalRepresentation, CoeffComplex > ZWilsonImplD; // Double | ||||
| typedef WilsonImpl<vComplexD2, FundamentalRepresentation, CoeffComplex > ZWilsonImplD2; // Double | ||||
|  | ||||
| //typedef WilsonImpl<vComplex,  FundamentalRepresentation, CoeffComplexHalfComms > ZWilsonImplRL; // Real.. whichever prec | ||||
| //typedef WilsonImpl<vComplexF, FundamentalRepresentation, CoeffComplexHalfComms > ZWilsonImplFH; // Float | ||||
| //typedef WilsonImpl<vComplexD, FundamentalRepresentation, CoeffComplexHalfComms > ZWilsonImplDF; // Double | ||||
|   | ||||
| typedef WilsonImpl<vComplex,  AdjointRepresentation, CoeffReal > WilsonAdjImplR;   // Real.. whichever prec | ||||
| typedef WilsonImpl<vComplexF, AdjointRepresentation, CoeffReal > WilsonAdjImplF;  // Float | ||||
|   | ||||
| @@ -52,6 +52,13 @@ public: | ||||
|   typedef AcceleratorVector<int,STENCIL_MAX> StencilVector;    | ||||
| public: | ||||
|  | ||||
| #ifdef GRID_SYCL | ||||
| #define SYCL_HACK | ||||
| #endif   | ||||
| #ifdef SYCL_HACK | ||||
|   static void HandDhopSiteSycl(StencilVector st_perm,StencilEntry *st_p, SiteDoubledGaugeField *U,SiteHalfSpinor  *buf, | ||||
| 			       int ss,int sU,const SiteSpinor *in, SiteSpinor *out); | ||||
| #endif | ||||
|    | ||||
|   static void DhopKernel(int Opt,StencilImpl &st,  DoubledGaugeField &U, SiteHalfSpinor * buf, | ||||
| 			 int Ls, int Nsite, const FermionField &in, FermionField &out, | ||||
|   | ||||
| @@ -47,7 +47,7 @@ CayleyFermion5D<Impl>::CayleyFermion5D(GaugeField &_Umu, | ||||
| 			FiveDimRedBlackGrid, | ||||
| 			FourDimGrid, | ||||
| 			FourDimRedBlackGrid,_M5,p), | ||||
|   mass_plus(_mass), mass_minus(_mass) | ||||
|   mass(_mass) | ||||
| {  | ||||
| } | ||||
|  | ||||
| @@ -152,13 +152,65 @@ void CayleyFermion5D<Impl>::DminusDag(const FermionField &psi, FermionField &chi | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<class Impl> void CayleyFermion5D<Impl>::CayleyReport(void) | ||||
| { | ||||
|   this->Report(); | ||||
|   Coordinate latt = GridDefaultLatt();           | ||||
|   RealD volume = this->Ls;  for(int mu=0;mu<Nd;mu++) volume=volume*latt[mu]; | ||||
|   RealD NP     = this->_FourDimGrid->_Nprocessors; | ||||
|   if ( M5Dcalls > 0 ) { | ||||
|     std::cout << GridLogMessage << "#### M5D calls report " << std::endl; | ||||
|     std::cout << GridLogMessage << "CayleyFermion5D Number of M5D Calls     : " << M5Dcalls   << std::endl; | ||||
|     std::cout << GridLogMessage << "CayleyFermion5D ComputeTime/Calls       : " << M5Dtime / M5Dcalls << " us" << std::endl; | ||||
|  | ||||
|     // Flops = 10.0*(Nc*Ns) *Ls*vol | ||||
|     RealD mflops = 10.0*(Nc*Ns)*volume*M5Dcalls/M5Dtime/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per rank       : " << mflops/NP << std::endl; | ||||
|  | ||||
|     // Bytes = sizeof(Real) * (Nc*Ns*Nreim) * Ls * vol * (read+write) (/2 for red black counting) | ||||
|     // read = 2 ( psi[ss+s+1] and psi[ss+s-1] count as 1 ) | ||||
|     // write = 1 | ||||
|     RealD Gbytes = sizeof(Real) * (Nc*Ns*2) * volume * 3 /2. * 1.e-9; | ||||
|     std::cout << GridLogMessage << "Average bandwidth (GB/s)                 : " << Gbytes/M5Dtime*M5Dcalls*1.e6 << std::endl; | ||||
|   } | ||||
|  | ||||
|   if ( MooeeInvCalls > 0 ) { | ||||
|  | ||||
|     std::cout << GridLogMessage << "#### MooeeInv calls report " << std::endl; | ||||
|     std::cout << GridLogMessage << "CayleyFermion5D Number of MooeeInv Calls     : " << MooeeInvCalls   << std::endl; | ||||
|     std::cout << GridLogMessage << "CayleyFermion5D ComputeTime/Calls            : " << MooeeInvTime / MooeeInvCalls << " us" << std::endl; | ||||
| #ifdef GRID_CUDA | ||||
|     RealD mflops = ( -16.*Nc*Ns+this->Ls*(1.+18.*Nc*Ns) )*volume*MooeeInvCalls/MooeeInvTime/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per rank       : " << mflops/NP << std::endl; | ||||
| #else | ||||
|     // Flops = MADD * Ls *Ls *4dvol * spin/colour/complex | ||||
|     RealD mflops = 2.0*24*this->Ls*volume*MooeeInvCalls/MooeeInvTime/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per rank       : " << mflops/NP << std::endl; | ||||
| #endif | ||||
|   } | ||||
|  | ||||
| } | ||||
| template<class Impl> void CayleyFermion5D<Impl>::CayleyZeroCounters(void) | ||||
| { | ||||
|   this->ZeroCounters(); | ||||
|   M5Dflops=0; | ||||
|   M5Dcalls=0; | ||||
|   M5Dtime=0; | ||||
|   MooeeInvFlops=0; | ||||
|   MooeeInvCalls=0; | ||||
|   MooeeInvTime=0; | ||||
| } | ||||
|  | ||||
| template<class Impl>   | ||||
| void CayleyFermion5D<Impl>::M5D   (const FermionField &psi, FermionField &chi) | ||||
| { | ||||
|   int Ls=this->Ls; | ||||
|   Vector<Coeff_t> diag (Ls,1.0); | ||||
|   Vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1]=mass_minus; | ||||
|   Vector<Coeff_t> lower(Ls,-1.0); lower[0]   =mass_plus; | ||||
|   Vector<Coeff_t> upper(Ls,-1.0); upper[Ls-1]=mass; | ||||
|   Vector<Coeff_t> lower(Ls,-1.0); lower[0]   =mass; | ||||
|   M5D(psi,chi,chi,lower,diag,upper); | ||||
| } | ||||
| template<class Impl> | ||||
| @@ -168,8 +220,8 @@ void CayleyFermion5D<Impl>::Meooe5D    (const FermionField &psi, FermionField &D | ||||
|   Vector<Coeff_t> diag = bs; | ||||
|   Vector<Coeff_t> upper= cs; | ||||
|   Vector<Coeff_t> lower= cs;  | ||||
|   upper[Ls-1]=-mass_minus*upper[Ls-1]; | ||||
|   lower[0]   =-mass_plus*lower[0]; | ||||
|   upper[Ls-1]=-mass*upper[Ls-1]; | ||||
|   lower[0]   =-mass*lower[0]; | ||||
|   M5D(psi,psi,Din,lower,diag,upper); | ||||
| } | ||||
| // FIXME Redunant with the above routine; check this and eliminate | ||||
| @@ -183,8 +235,8 @@ template<class Impl> void CayleyFermion5D<Impl>::Meo5D     (const FermionField & | ||||
|     upper[i]=-ceo[i]; | ||||
|     lower[i]=-ceo[i]; | ||||
|   } | ||||
|   upper[Ls-1]=-mass_minus*upper[Ls-1]; | ||||
|   lower[0]   =-mass_plus*lower[0]; | ||||
|   upper[Ls-1]=-mass*upper[Ls-1]; | ||||
|   lower[0]   =-mass*lower[0]; | ||||
|   M5D(psi,psi,chi,lower,diag,upper); | ||||
| } | ||||
| template<class Impl> | ||||
| @@ -198,8 +250,8 @@ void CayleyFermion5D<Impl>::Mooee       (const FermionField &psi, FermionField & | ||||
|     upper[i]=-cee[i]; | ||||
|     lower[i]=-cee[i]; | ||||
|   } | ||||
|   upper[Ls-1]=-mass_minus*upper[Ls-1]; | ||||
|   lower[0]   =-mass_plus*lower[0]; | ||||
|   upper[Ls-1]=-mass*upper[Ls-1]; | ||||
|   lower[0]   =-mass*lower[0]; | ||||
|   M5D(psi,psi,chi,lower,diag,upper); | ||||
| } | ||||
| template<class Impl> | ||||
| @@ -214,9 +266,9 @@ void CayleyFermion5D<Impl>::MooeeDag    (const FermionField &psi, FermionField & | ||||
|     // Assemble the 5d matrix | ||||
|     if ( s==0 ) { | ||||
|       upper[s] = -cee[s+1] ; | ||||
|       lower[s] = mass_minus*cee[Ls-1]; | ||||
|       lower[s] = mass*cee[Ls-1]; | ||||
|     } else if ( s==(Ls-1)) {  | ||||
|       upper[s] = mass_plus*cee[0]; | ||||
|       upper[s] = mass*cee[0]; | ||||
|       lower[s] = -cee[s-1]; | ||||
|     } else { | ||||
|       upper[s]=-cee[s+1]; | ||||
| @@ -239,8 +291,8 @@ void CayleyFermion5D<Impl>::M5Ddag (const FermionField &psi, FermionField &chi) | ||||
|   Vector<Coeff_t> diag(Ls,1.0); | ||||
|   Vector<Coeff_t> upper(Ls,-1.0); | ||||
|   Vector<Coeff_t> lower(Ls,-1.0); | ||||
|   upper[Ls-1]=-mass_plus*upper[Ls-1]; | ||||
|   lower[0]   =-mass_minus*lower[0]; | ||||
|   upper[Ls-1]=-mass*upper[Ls-1]; | ||||
|   lower[0]   =-mass*lower[0]; | ||||
|   M5Ddag(psi,chi,chi,lower,diag,upper); | ||||
| } | ||||
|  | ||||
| @@ -255,9 +307,9 @@ void CayleyFermion5D<Impl>::MeooeDag5D    (const FermionField &psi, FermionField | ||||
|   for (int s=0;s<Ls;s++){ | ||||
|     if ( s== 0 ) { | ||||
|       upper[s] = cs[s+1]; | ||||
|       lower[s] =-mass_minus*cs[Ls-1]; | ||||
|       lower[s] =-mass*cs[Ls-1]; | ||||
|     } else if ( s==(Ls-1) ) {  | ||||
|       upper[s] =-mass_plus*cs[0]; | ||||
|       upper[s] =-mass*cs[0]; | ||||
|       lower[s] = cs[s-1]; | ||||
|     } else {  | ||||
|       upper[s] = cs[s+1]; | ||||
| @@ -500,7 +552,7 @@ void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,Vector<Coeff_t | ||||
|        | ||||
|       lee[i] =-cee[i+1]/bee[i]; // sub-diag entry on the ith column | ||||
|        | ||||
|       leem[i]=mass_minus*cee[Ls-1]/bee[0]; | ||||
|       leem[i]=mass*cee[Ls-1]/bee[0]; | ||||
|       for(int j=0;j<i;j++) { | ||||
| 	assert(bee[j+1]!=Coeff_t(0.0)); | ||||
| 	leem[i]*= aee[j]/bee[j+1]; | ||||
| @@ -508,7 +560,7 @@ void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,Vector<Coeff_t | ||||
|        | ||||
|       uee[i] =-aee[i]/bee[i];   // up-diag entry on the ith row | ||||
|        | ||||
|       ueem[i]=mass_plus; | ||||
|       ueem[i]=mass; | ||||
|       for(int j=1;j<=i;j++) ueem[i]*= cee[j]/bee[j]; | ||||
|       ueem[i]*= aee[0]/bee[0]; | ||||
|        | ||||
| @@ -521,7 +573,7 @@ void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,Vector<Coeff_t | ||||
|   } | ||||
| 	 | ||||
|   {  | ||||
|     Coeff_t delta_d=mass_minus*cee[Ls-1]; | ||||
|     Coeff_t delta_d=mass*cee[Ls-1]; | ||||
|     for(int j=0;j<Ls-1;j++) { | ||||
|       assert(bee[j] != Coeff_t(0.0)); | ||||
|       delta_d *= cee[j]/bee[j]; | ||||
| @@ -590,10 +642,7 @@ void CayleyFermion5D<Impl>::ContractConservedCurrent( PropagatorField &q_in_1, | ||||
| 						      Current curr_type, | ||||
| 						      unsigned int mu) | ||||
| { | ||||
|  | ||||
|   assert(mass_plus == mass_minus); | ||||
|   RealD mass = mass_plus; | ||||
|    | ||||
| #if (!defined(GRID_HIP)) | ||||
|   Gamma::Algebra Gmu [] = { | ||||
|     Gamma::Algebra::GammaX, | ||||
|     Gamma::Algebra::GammaY, | ||||
| @@ -712,7 +761,7 @@ void CayleyFermion5D<Impl>::ContractConservedCurrent( PropagatorField &q_in_1, | ||||
|     else          q_out +=     C; | ||||
|      | ||||
|   } | ||||
|  | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template <class Impl> | ||||
| @@ -728,8 +777,6 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
|   assert(mu>=0); | ||||
|   assert(mu<Nd); | ||||
|  | ||||
|   assert(mass_plus == mass_minus); | ||||
|   RealD mass = mass_plus; | ||||
|  | ||||
| #if 0 | ||||
|   int tshift = (mu == Nd-1) ? 1 : 0; | ||||
| @@ -779,6 +826,7 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| #if (!defined(GRID_HIP)) | ||||
|   int tshift = (mu == Nd-1) ? 1 : 0; | ||||
|   unsigned int LLt    = GridDefaultLatt()[Tp]; | ||||
|   //////////////////////////////////////////////// | ||||
| @@ -898,6 +946,7 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
|  | ||||
|     InsertSlice(L_Q, q_out, s , 0); | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| #undef Pp | ||||
| #undef Pm | ||||
| @@ -905,6 +954,88 @@ void CayleyFermion5D<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
| #undef TopRowWithSource | ||||
|  | ||||
|  | ||||
|  | ||||
| #if 0 | ||||
| template<class Impl> | ||||
| void CayleyFermion5D<Impl>::MooeeInternalCompute(int dag, int inv, | ||||
| 						 Vector<iSinglet<Simd> > & Matp, | ||||
| 						 Vector<iSinglet<Simd> > & Matm) | ||||
| { | ||||
|   int Ls=this->Ls; | ||||
|  | ||||
|   GridBase *grid = this->FermionRedBlackGrid(); | ||||
|   int LLs = grid->_rdimensions[0]; | ||||
|  | ||||
|   if ( LLs == Ls ) { | ||||
|     return; // Not vectorised in 5th direction | ||||
|   } | ||||
|  | ||||
|   Eigen::MatrixXcd Pplus  = Eigen::MatrixXcd::Zero(Ls,Ls); | ||||
|   Eigen::MatrixXcd Pminus = Eigen::MatrixXcd::Zero(Ls,Ls); | ||||
|    | ||||
|   for(int s=0;s<Ls;s++){ | ||||
|     Pplus(s,s) = bee[s]; | ||||
|     Pminus(s,s)= bee[s]; | ||||
|   } | ||||
|    | ||||
|   for(int s=0;s<Ls-1;s++){ | ||||
|     Pminus(s,s+1) = -cee[s]; | ||||
|   } | ||||
|    | ||||
|   for(int s=0;s<Ls-1;s++){ | ||||
|     Pplus(s+1,s) = -cee[s+1]; | ||||
|   } | ||||
|   Pplus (0,Ls-1) = mass*cee[0]; | ||||
|   Pminus(Ls-1,0) = mass*cee[Ls-1]; | ||||
|    | ||||
|   Eigen::MatrixXcd PplusMat ; | ||||
|   Eigen::MatrixXcd PminusMat; | ||||
|    | ||||
|   if ( inv ) { | ||||
|     PplusMat =Pplus.inverse(); | ||||
|     PminusMat=Pminus.inverse(); | ||||
|   } else {  | ||||
|     PplusMat =Pplus; | ||||
|     PminusMat=Pminus; | ||||
|   } | ||||
|    | ||||
|   if(dag){ | ||||
|     PplusMat.adjointInPlace(); | ||||
|     PminusMat.adjointInPlace(); | ||||
|   } | ||||
|    | ||||
|   typedef typename SiteHalfSpinor::scalar_type scalar_type; | ||||
|   const int Nsimd=Simd::Nsimd(); | ||||
|   Matp.resize(Ls*LLs); | ||||
|   Matm.resize(Ls*LLs); | ||||
|  | ||||
|   for(int s2=0;s2<Ls;s2++){ | ||||
|     for(int s1=0;s1<LLs;s1++){ | ||||
|       int istride = LLs; | ||||
|       int ostride = 1; | ||||
|       Simd Vp; | ||||
|       Simd Vm; | ||||
|       scalar_type *sp = (scalar_type *)&Vp; | ||||
|       scalar_type *sm = (scalar_type *)&Vm; | ||||
|       for(int l=0;l<Nsimd;l++){ | ||||
| 	if ( switcheroo<Coeff_t>::iscomplex() ) { | ||||
| 	  sp[l] = PplusMat (l*istride+s1*ostride,s2); | ||||
| 	  sm[l] = PminusMat(l*istride+s1*ostride,s2); | ||||
| 	} else {  | ||||
| 	  // if real | ||||
| 	  scalar_type tmp; | ||||
| 	  tmp = PplusMat (l*istride+s1*ostride,s2); | ||||
| 	  sp[l] = scalar_type(tmp.real(),tmp.real()); | ||||
| 	  tmp = PminusMat(l*istride+s1*ostride,s2); | ||||
| 	  sm[l] = scalar_type(tmp.real(),tmp.real()); | ||||
| 	} | ||||
|       } | ||||
|       Matp[LLs*s2+s1] = Vp; | ||||
|       Matm[LLs*s2+s1] = Vm; | ||||
|     }} | ||||
| } | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -63,18 +63,23 @@ CayleyFermion5D<Impl>::M5D(const FermionField &psi_i, | ||||
|  | ||||
|   // 10 = 3 complex mult + 2 complex add | ||||
|   // Flops = 10.0*(Nc*Ns) *Ls*vol (/2 for red black counting) | ||||
|   uint64_t nloop = grid->oSites(); | ||||
|   M5Dcalls++; | ||||
|   M5Dtime-=usecond(); | ||||
|  | ||||
|   uint64_t nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t s = sss%Ls; | ||||
|     uint64_t ss= sss-s; | ||||
|     uint64_t ss= sss*Ls; | ||||
|     typedef decltype(coalescedRead(psi[0])) spinor; | ||||
|     spinor tmp1, tmp2; | ||||
|     for(int s=0;s<Ls;s++){ | ||||
|       uint64_t idx_u = ss+((s+1)%Ls); | ||||
|       uint64_t idx_l = ss+((s+Ls-1)%Ls); | ||||
|       spProj5m(tmp1,psi(idx_u)); | ||||
|       spProj5p(tmp2,psi(idx_l)); | ||||
|       coalescedWrite(chi[ss+s],pdiag[s]*phi(ss+s)+pupper[s]*tmp1+plower[s]*tmp2); | ||||
|     } | ||||
|   }); | ||||
|   M5Dtime+=usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl>   | ||||
| @@ -100,18 +105,23 @@ CayleyFermion5D<Impl>::M5Ddag(const FermionField &psi_i, | ||||
|   int Ls=this->Ls; | ||||
|  | ||||
|   // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|   uint64_t nloop = grid->oSites(); | ||||
|   M5Dcalls++; | ||||
|   M5Dtime-=usecond(); | ||||
|  | ||||
|   uint64_t nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t s = sss%Ls; | ||||
|     uint64_t ss= sss-s; | ||||
|     uint64_t ss=sss*Ls; | ||||
|     typedef decltype(coalescedRead(psi[0])) spinor; | ||||
|     spinor tmp1,tmp2; | ||||
|     for(int s=0;s<Ls;s++){ | ||||
|       uint64_t idx_u = ss+((s+1)%Ls); | ||||
|       uint64_t idx_l = ss+((s+Ls-1)%Ls); | ||||
|       spProj5p(tmp1,psi(idx_u)); | ||||
|       spProj5m(tmp2,psi(idx_l)); | ||||
|       coalescedWrite(chi[ss+s],pdiag[s]*phi(ss+s)+pupper[s]*tmp1+plower[s]*tmp2); | ||||
|     } | ||||
|   }); | ||||
|   M5Dtime+=usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -132,6 +142,8 @@ CayleyFermion5D<Impl>::MooeeInv    (const FermionField &psi_i, FermionField &chi | ||||
|   auto pleem = & leem[0]; | ||||
|   auto pueem = & ueem[0]; | ||||
|  | ||||
|   MooeeInvCalls++; | ||||
|   MooeeInvTime-=usecond(); | ||||
|   uint64_t nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t ss=sss*Ls; | ||||
| @@ -169,6 +181,8 @@ CayleyFermion5D<Impl>::MooeeInv    (const FermionField &psi_i, FermionField &chi | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   MooeeInvTime+=usecond(); | ||||
|    | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -190,6 +204,10 @@ CayleyFermion5D<Impl>::MooeeInvDag (const FermionField &psi_i, FermionField &chi | ||||
|  | ||||
|   assert(psi.Checkerboard() == psi.Checkerboard()); | ||||
|  | ||||
|   MooeeInvCalls++; | ||||
|   MooeeInvTime-=usecond(); | ||||
|  | ||||
|  | ||||
|   uint64_t nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t ss=sss*Ls; | ||||
| @@ -226,6 +244,7 @@ CayleyFermion5D<Impl>::MooeeInvDag (const FermionField &psi_i, FermionField &chi | ||||
|       coalescedWrite(chi[ss+s],res); | ||||
|     } | ||||
|   }); | ||||
|   MooeeInvTime+=usecond(); | ||||
|  | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -94,6 +94,10 @@ CayleyFermion5D<Impl>::M5D(const FermionField &psi_i, | ||||
|       d_p[ss] = diag[s]; | ||||
|     }} | ||||
|  | ||||
|  | ||||
|   M5Dcalls++; | ||||
|   M5Dtime-=usecond(); | ||||
|  | ||||
|   assert(Nc==3); | ||||
|  | ||||
|   thread_loop( (int ss=0;ss<grid->oSites();ss+=LLs),{ // adds LLs | ||||
| @@ -194,6 +198,7 @@ CayleyFermion5D<Impl>::M5D(const FermionField &psi_i, | ||||
|     } | ||||
| #endif | ||||
|   }); | ||||
|   M5Dtime+=usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl>   | ||||
| @@ -237,6 +242,8 @@ CayleyFermion5D<Impl>::M5Ddag(const FermionField &psi_i, | ||||
|       d_p[ss] = diag[s]; | ||||
|     }} | ||||
|  | ||||
|   M5Dcalls++; | ||||
|   M5Dtime-=usecond(); | ||||
|   thread_loop( (int ss=0;ss<grid->oSites();ss+=LLs),{ // adds LLs | ||||
| #if 0 | ||||
|     alignas(64) SiteHalfSpinor hp; | ||||
| @@ -332,6 +339,7 @@ CayleyFermion5D<Impl>::M5Ddag(const FermionField &psi_i, | ||||
|     } | ||||
| #endif | ||||
|   }); | ||||
|   M5Dtime+=usecond(); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -805,6 +813,9 @@ CayleyFermion5D<Impl>::MooeeInternal(const FermionField &psi, FermionField &chi, | ||||
|   } | ||||
|   assert(_Matp->size()==Ls*LLs); | ||||
|  | ||||
|   MooeeInvCalls++; | ||||
|   MooeeInvTime-=usecond(); | ||||
|  | ||||
|   if ( switcheroo<Coeff_t>::iscomplex() ) { | ||||
|     thread_loop( (auto site=0;site<vol;site++),{ | ||||
|       MooeeInternalZAsm(psi,chi,LLs,site,*_Matp,*_Matm); | ||||
| @@ -814,7 +825,7 @@ CayleyFermion5D<Impl>::MooeeInternal(const FermionField &psi, FermionField &chi, | ||||
|       MooeeInternalAsm(psi,chi,LLs,site,*_Matp,*_Matm); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   MooeeInvTime+=usecond(); | ||||
| } | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -32,10 +32,9 @@ | ||||
| #include <Grid/qcd/spin/Dirac.h> | ||||
| #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> | ||||
|  | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
| template<class Impl, class CloverHelpers> | ||||
| CompactWilsonCloverFermion<Impl, CloverHelpers>::CompactWilsonCloverFermion(GaugeField& _Umu, | ||||
| template<class Impl> | ||||
| CompactWilsonCloverFermion<Impl>::CompactWilsonCloverFermion(GaugeField& _Umu, | ||||
|                                                              GridCartesian& Fgrid, | ||||
|                                                              GridRedBlackCartesian& Hgrid, | ||||
|                                                              const RealD _mass, | ||||
| @@ -48,7 +47,7 @@ CompactWilsonCloverFermion<Impl, CloverHelpers>::CompactWilsonCloverFermion(Gaug | ||||
|   , csw_r(_csw_r) | ||||
|   , csw_t(_csw_t) | ||||
|   , cF(_cF) | ||||
|   , fixedBoundaries(impl_p.boundary_phases[Nd-1] == 0.0) | ||||
|   , open_boundaries(impl_p.boundary_phases[Nd-1] == 0.0) | ||||
|   , Diagonal(&Fgrid),        Triangle(&Fgrid) | ||||
|   , DiagonalEven(&Hgrid),    TriangleEven(&Hgrid) | ||||
|   , DiagonalOdd(&Hgrid),     TriangleOdd(&Hgrid) | ||||
| @@ -59,85 +58,80 @@ CompactWilsonCloverFermion<Impl, CloverHelpers>::CompactWilsonCloverFermion(Gaug | ||||
|   , BoundaryMask(&Fgrid) | ||||
|   , BoundaryMaskEven(&Hgrid), BoundaryMaskOdd(&Hgrid) | ||||
| { | ||||
|   assert(Nd == 4 && Nc == 3 && Ns == 4 && Impl::Dimension == 3); | ||||
|  | ||||
|   csw_r *= 0.5; | ||||
|   csw_t *= 0.5; | ||||
|   if (clover_anisotropy.isAnisotropic) | ||||
|     csw_r /= clover_anisotropy.xi_0; | ||||
|  | ||||
|   ImportGauge(_Umu); | ||||
|   if (fixedBoundaries) { | ||||
|     this->BoundaryMaskEven.Checkerboard() = Even; | ||||
|     this->BoundaryMaskOdd.Checkerboard() = Odd; | ||||
|   if (open_boundaries) | ||||
|     CompactHelpers::SetupMasks(this->BoundaryMask, this->BoundaryMaskEven, this->BoundaryMaskOdd); | ||||
| } | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Dhop(const FermionField& in, FermionField& out, int dag) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Dhop(const FermionField& in, FermionField& out, int dag) { | ||||
|   WilsonBase::Dhop(in, out, dag); | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::DhopOE(const FermionField& in, FermionField& out, int dag) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::DhopOE(const FermionField& in, FermionField& out, int dag) { | ||||
|   WilsonBase::DhopOE(in, out, dag); | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::DhopEO(const FermionField& in, FermionField& out, int dag) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::DhopEO(const FermionField& in, FermionField& out, int dag) { | ||||
|   WilsonBase::DhopEO(in, out, dag); | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::DhopDir(const FermionField& in, FermionField& out, int dir, int disp) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::DhopDir(const FermionField& in, FermionField& out, int dir, int disp) { | ||||
|   WilsonBase::DhopDir(in, out, dir, disp); | ||||
|   if(this->fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(this->open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::DhopDirAll(const FermionField& in, std::vector<FermionField>& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::DhopDirAll(const FermionField& in, std::vector<FermionField>& out) { | ||||
|   WilsonBase::DhopDirAll(in, out); | ||||
|   if(this->fixedBoundaries) { | ||||
|   if(this->open_boundaries) { | ||||
|     for(auto& o : out) ApplyBoundaryMask(o); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::M(const FermionField& in, FermionField& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::M(const FermionField& in, FermionField& out) { | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   WilsonBase::Dhop(in, out, DaggerNo); // call base to save applying bc | ||||
|   Mooee(in, Tmp); | ||||
|   axpy(out, 1.0, out, Tmp); | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Mdag(const FermionField& in, FermionField& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Mdag(const FermionField& in, FermionField& out) { | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   WilsonBase::Dhop(in, out, DaggerYes);  // call base to save applying bc | ||||
|   MooeeDag(in, Tmp); | ||||
|   axpy(out, 1.0, out, Tmp); | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Meooe(const FermionField& in, FermionField& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Meooe(const FermionField& in, FermionField& out) { | ||||
|   WilsonBase::Meooe(in, out); | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MeooeDag(const FermionField& in, FermionField& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MeooeDag(const FermionField& in, FermionField& out) { | ||||
|   WilsonBase::MeooeDag(in, out); | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Mooee(const FermionField& in, FermionField& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Mooee(const FermionField& in, FermionField& out) { | ||||
|   if(in.Grid()->_isCheckerBoarded) { | ||||
|     if(in.Checkerboard() == Odd) { | ||||
|       MooeeInternal(in, out, DiagonalOdd, TriangleOdd); | ||||
| @@ -147,16 +141,16 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::Mooee(const FermionField& | ||||
|   } else { | ||||
|     MooeeInternal(in, out, Diagonal, Triangle); | ||||
|   } | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeDag(const FermionField& in, FermionField& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooeeDag(const FermionField& in, FermionField& out) { | ||||
|   Mooee(in, out); // blocks are hermitian | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInv(const FermionField& in, FermionField& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooeeInv(const FermionField& in, FermionField& out) { | ||||
|   if(in.Grid()->_isCheckerBoarded) { | ||||
|     if(in.Checkerboard() == Odd) { | ||||
|       MooeeInternal(in, out, DiagonalInvOdd, TriangleInvOdd); | ||||
| @@ -166,27 +160,27 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInv(const FermionFiel | ||||
|   } else { | ||||
|     MooeeInternal(in, out, DiagonalInv, TriangleInv); | ||||
|   } | ||||
|   if(fixedBoundaries) ApplyBoundaryMask(out); | ||||
|   if(open_boundaries) ApplyBoundaryMask(out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInvDag(const FermionField& in, FermionField& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooeeInvDag(const FermionField& in, FermionField& out) { | ||||
|   MooeeInv(in, out); // blocks are hermitian | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::Mdir(const FermionField& in, FermionField& out, int dir, int disp) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::Mdir(const FermionField& in, FermionField& out, int dir, int disp) { | ||||
|   DhopDir(in, out, dir, disp); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MdirAll(const FermionField& in, std::vector<FermionField>& out) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MdirAll(const FermionField& in, std::vector<FermionField>& out) { | ||||
|   DhopDirAll(in, out); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField& force, const FermionField& X, const FermionField& Y, int dag) { | ||||
|   assert(!fixedBoundaries); // TODO check for changes required for open bc | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MDeriv(GaugeField& force, const FermionField& X, const FermionField& Y, int dag) { | ||||
|   assert(!open_boundaries); // TODO check for changes required for open bc | ||||
|  | ||||
|   // NOTE: code copied from original clover term | ||||
|   conformable(X.Grid(), Y.Grid()); | ||||
| @@ -257,7 +251,7 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField& force, | ||||
|       } | ||||
|       PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked | ||||
|       Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok | ||||
|       force_mu -= factor*CloverHelpers::Cmunu(U, lambda, mu, nu);   // checked | ||||
|       force_mu -= factor*Helpers::Cmunu(U, lambda, mu, nu);   // checked | ||||
|       count++; | ||||
|     } | ||||
|  | ||||
| @@ -267,18 +261,18 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField& force, | ||||
|   force += clover_force; | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | ||||
|   assert(0); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MeeDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MeeDeriv(GaugeField& mat, const FermionField& U, const FermionField& V, int dag) { | ||||
|   assert(0); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInternal(const FermionField&        in, | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::MooeeInternal(const FermionField&        in, | ||||
|                     FermionField&              out, | ||||
|                     const CloverDiagonalField& diagonal, | ||||
|                     const CloverTriangleField& triangle) { | ||||
| @@ -291,8 +285,8 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::MooeeInternal(const Fermio | ||||
|   CompactHelpers::MooeeKernel(diagonal.oSites(), 1, in, out, diagonal, triangle); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void CompactWilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeField& _Umu) { | ||||
| template<class Impl> | ||||
| void CompactWilsonCloverFermion<Impl>::ImportGauge(const GaugeField& _Umu) { | ||||
|   // NOTE: parts copied from original implementation | ||||
|  | ||||
|   // Import gauge into base class | ||||
| @@ -305,7 +299,6 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeFie | ||||
|   GridBase* grid = _Umu.Grid(); | ||||
|   typename Impl::GaugeLinkField Bx(grid), By(grid), Bz(grid), Ex(grid), Ey(grid), Ez(grid); | ||||
|   CloverField TmpOriginal(grid); | ||||
|   CloverField TmpInverse(grid); | ||||
|  | ||||
|   // Compute the field strength terms mu>nu | ||||
|   double t2 = usecond(); | ||||
| @@ -325,30 +318,22 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeFie | ||||
|   TmpOriginal += Helpers::fillCloverXT(Ex) * csw_t; | ||||
|   TmpOriginal += Helpers::fillCloverYT(Ey) * csw_t; | ||||
|   TmpOriginal += Helpers::fillCloverZT(Ez) * csw_t; | ||||
|  | ||||
|   // Instantiate the clover term | ||||
|   // - In case of the standard clover the mass term is added | ||||
|   // - In case of the exponential clover the clover term is exponentiated | ||||
|   double t4 = usecond(); | ||||
|   CloverHelpers::InstantiateClover(TmpOriginal, TmpInverse, csw_t, this->diag_mass); | ||||
|   TmpOriginal += this->diag_mass; | ||||
|  | ||||
|   // Convert the data layout of the clover term | ||||
|   double t5 = usecond(); | ||||
|   double t4 = usecond(); | ||||
|   CompactHelpers::ConvertLayout(TmpOriginal, Diagonal, Triangle); | ||||
|  | ||||
|   // Modify the clover term at the temporal boundaries in case of open boundary conditions | ||||
|   double t6 = usecond(); | ||||
|   if(fixedBoundaries) CompactHelpers::ModifyBoundaries(Diagonal, Triangle, csw_t, cF, this->diag_mass); | ||||
|   // Possible modify the boundary values | ||||
|   double t5 = usecond(); | ||||
|   if(open_boundaries) CompactHelpers::ModifyBoundaries(Diagonal, Triangle, csw_t, cF, this->diag_mass); | ||||
|  | ||||
|   // Invert the Clover term | ||||
|   // In case of the exponential clover with (anti-)periodic boundary conditions exp(-Clover) saved | ||||
|   // in TmpInverse can be used. In all other cases the clover term has to be explictly inverted. | ||||
|   // TODO: For now this inversion is explictly done on the CPU | ||||
|   double t7 = usecond(); | ||||
|   CloverHelpers::InvertClover(TmpInverse, Diagonal, Triangle, DiagonalInv, TriangleInv, fixedBoundaries); | ||||
|   // Invert the clover term in the improved layout | ||||
|   double t6 = usecond(); | ||||
|   CompactHelpers::Invert(Diagonal, Triangle, DiagonalInv, TriangleInv); | ||||
|  | ||||
|   // Fill the remaining clover fields | ||||
|   double t8 = usecond(); | ||||
|   double t7 = usecond(); | ||||
|   pickCheckerboard(Even, DiagonalEven,    Diagonal); | ||||
|   pickCheckerboard(Even, TriangleEven,    Triangle); | ||||
|   pickCheckerboard(Odd,  DiagonalOdd,     Diagonal); | ||||
| @@ -359,19 +344,20 @@ void CompactWilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeFie | ||||
|   pickCheckerboard(Odd,  TriangleInvOdd,  TriangleInv); | ||||
|  | ||||
|   // Report timings | ||||
|   double t9 = usecond(); | ||||
|  | ||||
|   std::cout << GridLogDebug << "CompactWilsonCloverFermion::ImportGauge timings:" << std::endl; | ||||
|   std::cout << GridLogDebug << "WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "allocations =                " << (t2 - t1) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "field strength =             " << (t3 - t2) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "fill clover =                " << (t4 - t3) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "instantiate clover =         " << (t5 - t4) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "convert layout =             " << (t6 - t5) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "modify boundaries =          " << (t7 - t6) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "invert clover =              " << (t8 - t7) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "pick cbs =                   " << (t9 - t8) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "total =                      " << (t9 - t0) / 1e6 << std::endl; | ||||
|   double t8 = usecond(); | ||||
| #if 0 | ||||
|   std::cout << GridLogMessage << "CompactWilsonCloverFermion::ImportGauge timings:" | ||||
|             << " WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 | ||||
|             << ", allocations = "               << (t2 - t1) / 1e6 | ||||
|             << ", field strength = "            << (t3 - t2) / 1e6 | ||||
|             << ", fill clover = "               << (t4 - t3) / 1e6 | ||||
|             << ", convert = "                   << (t5 - t4) / 1e6 | ||||
|             << ", boundaries = "                << (t6 - t5) / 1e6 | ||||
|             << ", inversions = "                << (t7 - t6) / 1e6 | ||||
|             << ", pick cbs = "                  << (t8 - t7) / 1e6 | ||||
|             << ", total = "                     << (t8 - t0) / 1e6 | ||||
|             << std::endl; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -54,6 +54,8 @@ void DomainWallEOFAFermion<Impl>::M5D(const FermionField& psi_i, const FermionFi | ||||
|   auto pupper = &upper[0]; | ||||
|   auto plower = &lower[0]; | ||||
|   // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|   this->M5Dcalls++; | ||||
|   this->M5Dtime -= usecond(); | ||||
|    | ||||
|   auto nloop=grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
| @@ -69,6 +71,7 @@ void DomainWallEOFAFermion<Impl>::M5D(const FermionField& psi_i, const FermionFi | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   this->M5Dtime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -88,6 +91,8 @@ void DomainWallEOFAFermion<Impl>::M5Ddag(const FermionField& psi_i, const Fermio | ||||
|   auto plower = &lower[0]; | ||||
|  | ||||
|   // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|   this->M5Dcalls++; | ||||
|   this->M5Dtime -= usecond(); | ||||
|  | ||||
|   auto nloop=grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
| @@ -103,6 +108,7 @@ void DomainWallEOFAFermion<Impl>::M5Ddag(const FermionField& psi_i, const Fermio | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   this->M5Dtime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -121,6 +127,8 @@ void DomainWallEOFAFermion<Impl>::MooeeInv(const FermionField& psi_i, FermionFie | ||||
|   auto pleem = & this->leem[0]; | ||||
|   auto pueem = & this->ueem[0]; | ||||
|  | ||||
|   this->MooeeInvCalls++; | ||||
|   this->MooeeInvTime -= usecond(); | ||||
|   uint64_t nloop=grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t ss=sss*Ls; | ||||
| @@ -156,6 +164,7 @@ void DomainWallEOFAFermion<Impl>::MooeeInv(const FermionField& psi_i, FermionFie | ||||
|       coalescedWrite(chi[ss+s],res); | ||||
|     } | ||||
|   }); | ||||
|   this->MooeeInvTime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -176,6 +185,8 @@ void DomainWallEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi_i, Fermion | ||||
|  | ||||
|   assert(psi.Checkerboard() == psi.Checkerboard()); | ||||
|  | ||||
|   this->MooeeInvCalls++; | ||||
|   this->MooeeInvTime -= usecond(); | ||||
|   auto nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t ss=sss*Ls; | ||||
| @@ -212,6 +223,7 @@ void DomainWallEOFAFermion<Impl>::MooeeInvDag(const FermionField& psi_i, Fermion | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   this->MooeeInvTime += usecond(); | ||||
| } | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -298,33 +298,45 @@ void ImprovedStaggeredFermion5D<Impl>::DhopInternalOverlappedComms(StencilImpl & | ||||
|   int LLs = in.Grid()->_rdimensions[0]; | ||||
|   int len =  U.Grid()->oSites(); | ||||
|  | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.Prepare(); | ||||
|   st.HaloGather(in,compressor); | ||||
|   DhopFaceTime+=usecond(); | ||||
|  | ||||
|   DhopCommTime -=usecond(); | ||||
|   std::vector<std::vector<CommsRequest_t> > requests; | ||||
|   st.CommunicateBegin(requests); | ||||
|  | ||||
|   //  st.HaloExchangeOptGather(in,compressor); // Wilson compressor | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.CommsMergeSHM(compressor);// Could do this inside parallel region overlapped with comms | ||||
|   DhopFaceTime+=usecond(); | ||||
|  | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Remove explicit thread mapping introduced for OPA reasons. | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   DhopComputeTime-=usecond(); | ||||
|   { | ||||
|     int interior=1; | ||||
|     int exterior=0; | ||||
|     Kernels::DhopImproved(st,lo,U,UUU,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime+=usecond(); | ||||
|  | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.CommsMerge(compressor); | ||||
|   DhopFaceTime+=usecond(); | ||||
|  | ||||
|   st.CommunicateComplete(requests); | ||||
|   DhopCommTime +=usecond(); | ||||
|  | ||||
|   DhopComputeTime2-=usecond(); | ||||
|   { | ||||
|     int interior=0; | ||||
|     int exterior=1; | ||||
|     Kernels::DhopImproved(st,lo,U,UUU,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime2+=usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -335,14 +347,22 @@ void ImprovedStaggeredFermion5D<Impl>::DhopInternalSerialComms(StencilImpl & st, | ||||
|   Compressor compressor; | ||||
|   int LLs = in.Grid()->_rdimensions[0]; | ||||
|  | ||||
|  //double t1=usecond(); | ||||
|   DhopTotalTime -= usecond(); | ||||
|   DhopCommTime -= usecond(); | ||||
|   st.HaloExchange(in,compressor); | ||||
|   DhopCommTime += usecond(); | ||||
|    | ||||
|   DhopComputeTime -= usecond(); | ||||
|   // Dhop takes the 4d grid from U, and makes a 5d index for fermion | ||||
|   { | ||||
|     int interior=1; | ||||
|     int exterior=1; | ||||
|     Kernels::DhopImproved(st,lo,U,UUU,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime += usecond(); | ||||
|   DhopTotalTime   += usecond(); | ||||
|  | ||||
| } | ||||
| /*CHANGE END*/ | ||||
|  | ||||
| @@ -351,6 +371,7 @@ void ImprovedStaggeredFermion5D<Impl>::DhopInternalSerialComms(StencilImpl & st, | ||||
| template<class Impl> | ||||
| void ImprovedStaggeredFermion5D<Impl>::DhopOE(const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   DhopCalls+=1; | ||||
|   conformable(in.Grid(),FermionRedBlackGrid());    // verifies half grid | ||||
|   conformable(in.Grid(),out.Grid()); // drops the cb check | ||||
|  | ||||
| @@ -362,6 +383,7 @@ void ImprovedStaggeredFermion5D<Impl>::DhopOE(const FermionField &in, FermionFie | ||||
| template<class Impl> | ||||
| void ImprovedStaggeredFermion5D<Impl>::DhopEO(const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   DhopCalls+=1; | ||||
|   conformable(in.Grid(),FermionRedBlackGrid());    // verifies half grid | ||||
|   conformable(in.Grid(),out.Grid()); // drops the cb check | ||||
|  | ||||
| @@ -373,6 +395,7 @@ void ImprovedStaggeredFermion5D<Impl>::DhopEO(const FermionField &in, FermionFie | ||||
| template<class Impl> | ||||
| void ImprovedStaggeredFermion5D<Impl>::Dhop(const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   DhopCalls+=2; | ||||
|   conformable(in.Grid(),FermionGrid()); // verifies full grid | ||||
|   conformable(in.Grid(),out.Grid()); | ||||
|  | ||||
| @@ -381,6 +404,58 @@ void ImprovedStaggeredFermion5D<Impl>::Dhop(const FermionField &in, FermionField | ||||
|   DhopInternal(Stencil,Lebesgue,Umu,UUUmu,in,out,dag); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void ImprovedStaggeredFermion5D<Impl>::Report(void)  | ||||
| { | ||||
|   Coordinate latt = GridDefaultLatt();           | ||||
|   RealD volume = Ls;  for(int mu=0;mu<Nd;mu++) volume=volume*latt[mu]; | ||||
|   RealD NP = _FourDimGrid->_Nprocessors; | ||||
|   RealD NN = _FourDimGrid->NodeCount(); | ||||
|  | ||||
|   std::cout << GridLogMessage << "#### Dhop calls report " << std::endl; | ||||
|  | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion5D Number of DhopEO Calls   : "  | ||||
| 	    << DhopCalls   << std::endl; | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion5D TotalTime   /Calls       : "  | ||||
| 	    << DhopTotalTime   / DhopCalls << " us" << std::endl; | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion5D CommTime    /Calls       : "  | ||||
| 	    << DhopCommTime    / DhopCalls << " us" << std::endl; | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion5D ComputeTime/Calls        : "  | ||||
| 	    << DhopComputeTime / DhopCalls << " us" << std::endl; | ||||
|  | ||||
|   // Average the compute time | ||||
|   _FourDimGrid->GlobalSum(DhopComputeTime); | ||||
|   DhopComputeTime/=NP; | ||||
|  | ||||
|   RealD mflops = 1154*volume*DhopCalls/DhopComputeTime/2; // 2 for red black counting | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per rank       : " << mflops/NP << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per node       : " << mflops/NN << std::endl; | ||||
|    | ||||
|   RealD Fullmflops = 1154*volume*DhopCalls/(DhopTotalTime)/2; // 2 for red black counting | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call (full)         : " << Fullmflops << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per rank (full): " << Fullmflops/NP << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per node (full): " << Fullmflops/NN << std::endl; | ||||
|  | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion5D Stencil"    <<std::endl;  Stencil.Report(); | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion5D StencilEven"<<std::endl;  StencilEven.Report(); | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion5D StencilOdd" <<std::endl;  StencilOdd.Report(); | ||||
| } | ||||
| template<class Impl> | ||||
| void ImprovedStaggeredFermion5D<Impl>::ZeroCounters(void)  | ||||
| { | ||||
|   DhopCalls       = 0; | ||||
|   DhopTotalTime    = 0; | ||||
|   DhopCommTime    = 0; | ||||
|   DhopComputeTime = 0; | ||||
|   DhopFaceTime    = 0; | ||||
|  | ||||
|  | ||||
|   Stencil.ZeroCounters(); | ||||
|   StencilEven.ZeroCounters(); | ||||
|   StencilOdd.ZeroCounters(); | ||||
| } | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////// | ||||
| // Implement the general interface. Here we use SAME mass on all slices | ||||
| ///////////////////////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -334,6 +334,7 @@ void ImprovedStaggeredFermion<Impl>::DhopDerivEO(GaugeField &mat, const FermionF | ||||
| template <class Impl> | ||||
| void ImprovedStaggeredFermion<Impl>::Dhop(const FermionField &in, FermionField &out, int dag)  | ||||
| { | ||||
|   DhopCalls+=2; | ||||
|   conformable(in.Grid(), _grid);  // verifies full grid | ||||
|   conformable(in.Grid(), out.Grid()); | ||||
|  | ||||
| @@ -345,6 +346,7 @@ void ImprovedStaggeredFermion<Impl>::Dhop(const FermionField &in, FermionField & | ||||
| template <class Impl> | ||||
| void ImprovedStaggeredFermion<Impl>::DhopOE(const FermionField &in, FermionField &out, int dag)  | ||||
| { | ||||
|   DhopCalls+=1; | ||||
|   conformable(in.Grid(), _cbgrid);    // verifies half grid | ||||
|   conformable(in.Grid(), out.Grid());  // drops the cb check | ||||
|  | ||||
| @@ -357,6 +359,7 @@ void ImprovedStaggeredFermion<Impl>::DhopOE(const FermionField &in, FermionField | ||||
| template <class Impl> | ||||
| void ImprovedStaggeredFermion<Impl>::DhopEO(const FermionField &in, FermionField &out, int dag)  | ||||
| { | ||||
|   DhopCalls+=1; | ||||
|   conformable(in.Grid(), _cbgrid);    // verifies half grid | ||||
|   conformable(in.Grid(), out.Grid());  // drops the cb check | ||||
|  | ||||
| @@ -415,33 +418,47 @@ void ImprovedStaggeredFermion<Impl>::DhopInternalOverlappedComms(StencilImpl &st | ||||
|   Compressor compressor;  | ||||
|   int len =  U.Grid()->oSites(); | ||||
|  | ||||
|   DhopTotalTime   -= usecond(); | ||||
|  | ||||
|   DhopFaceTime    -= usecond(); | ||||
|   st.Prepare(); | ||||
|   st.HaloGather(in,compressor); | ||||
|   DhopFaceTime    += usecond(); | ||||
|  | ||||
|   DhopCommTime -=usecond(); | ||||
|   std::vector<std::vector<CommsRequest_t> > requests; | ||||
|   st.CommunicateBegin(requests); | ||||
|  | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.CommsMergeSHM(compressor); | ||||
|   DhopFaceTime+= usecond(); | ||||
|  | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Removed explicit thread comms | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   DhopComputeTime    -= usecond(); | ||||
|   { | ||||
|     int interior=1; | ||||
|     int exterior=0; | ||||
|     Kernels::DhopImproved(st,lo,U,UUU,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime    += usecond(); | ||||
|  | ||||
|   st.CommunicateComplete(requests); | ||||
|   DhopCommTime +=usecond(); | ||||
|  | ||||
|   // First to enter, last to leave timing | ||||
|   DhopFaceTime    -= usecond(); | ||||
|   st.CommsMerge(compressor); | ||||
|   DhopFaceTime    -= usecond(); | ||||
|  | ||||
|   DhopComputeTime2    -= usecond(); | ||||
|   { | ||||
|     int interior=0; | ||||
|     int exterior=1; | ||||
|     Kernels::DhopImproved(st,lo,U,UUU,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime2    += usecond(); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -454,16 +471,78 @@ void ImprovedStaggeredFermion<Impl>::DhopInternalSerialComms(StencilImpl &st, Le | ||||
| { | ||||
|   assert((dag == DaggerNo) || (dag == DaggerYes)); | ||||
|  | ||||
|   DhopTotalTime   -= usecond(); | ||||
|  | ||||
|   DhopCommTime    -= usecond(); | ||||
|   Compressor compressor; | ||||
|   st.HaloExchange(in, compressor); | ||||
|   DhopCommTime    += usecond(); | ||||
|  | ||||
|   DhopComputeTime -= usecond(); | ||||
|   { | ||||
|     int interior=1; | ||||
|     int exterior=1; | ||||
|     Kernels::DhopImproved(st,lo,U,UUU,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime += usecond(); | ||||
|   DhopTotalTime   += usecond(); | ||||
| }; | ||||
|  | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Reporting | ||||
|   //////////////////////////////////////////////////////////////// | ||||
| template<class Impl> | ||||
| void ImprovedStaggeredFermion<Impl>::Report(void)  | ||||
| { | ||||
|   Coordinate latt = _grid->GlobalDimensions(); | ||||
|   RealD volume = 1;  for(int mu=0;mu<Nd;mu++) volume=volume*latt[mu]; | ||||
|   RealD NP = _grid->_Nprocessors; | ||||
|   RealD NN = _grid->NodeCount(); | ||||
|  | ||||
|   std::cout << GridLogMessage << "#### Dhop calls report " << std::endl; | ||||
|  | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion Number of DhopEO Calls   : "  | ||||
| 	    << DhopCalls   << std::endl; | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion TotalTime   /Calls       : "  | ||||
| 	    << DhopTotalTime   / DhopCalls << " us" << std::endl; | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion CommTime    /Calls       : "  | ||||
| 	    << DhopCommTime    / DhopCalls << " us" << std::endl; | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion ComputeTime/Calls        : "  | ||||
| 	    << DhopComputeTime / DhopCalls << " us" << std::endl; | ||||
|  | ||||
|   // Average the compute time | ||||
|   _grid->GlobalSum(DhopComputeTime); | ||||
|   DhopComputeTime/=NP; | ||||
|  | ||||
|   RealD mflops = 1154*volume*DhopCalls/DhopComputeTime/2; // 2 for red black counting | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per rank       : " << mflops/NP << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per node       : " << mflops/NN << std::endl; | ||||
|    | ||||
|   RealD Fullmflops = 1154*volume*DhopCalls/(DhopTotalTime)/2; // 2 for red black counting | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call (full)         : " << Fullmflops << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per rank (full): " << Fullmflops/NP << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per node (full): " << Fullmflops/NN << std::endl; | ||||
|  | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion Stencil"    <<std::endl;  Stencil.Report(); | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion StencilEven"<<std::endl;  StencilEven.Report(); | ||||
|   std::cout << GridLogMessage << "ImprovedStaggeredFermion StencilOdd" <<std::endl;  StencilOdd.Report(); | ||||
| } | ||||
| template<class Impl> | ||||
| void ImprovedStaggeredFermion<Impl>::ZeroCounters(void)  | ||||
| { | ||||
|   DhopCalls       = 0; | ||||
|   DhopTotalTime   = 0; | ||||
|   DhopCommTime    = 0; | ||||
|   DhopComputeTime = 0; | ||||
|   DhopFaceTime    = 0; | ||||
|  | ||||
|   Stencil.ZeroCounters(); | ||||
|   StencilEven.ZeroCounters(); | ||||
|   StencilOdd.ZeroCounters(); | ||||
| } | ||||
|  | ||||
|  | ||||
| ////////////////////////////////////////////////////////  | ||||
| // Conserved current - not yet implemented. | ||||
| //////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -55,6 +55,9 @@ void MobiusEOFAFermion<Impl>::M5D(const FermionField &psi_i, const FermionField | ||||
|   auto plower = &lower[0]; | ||||
|  | ||||
|   // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|   this->M5Dcalls++; | ||||
|   this->M5Dtime -= usecond(); | ||||
|  | ||||
|   int nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t ss = sss*Ls; | ||||
| @@ -70,6 +73,7 @@ void MobiusEOFAFermion<Impl>::M5D(const FermionField &psi_i, const FermionField | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   this->M5Dtime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -95,6 +99,9 @@ void MobiusEOFAFermion<Impl>::M5D_shift(const FermionField &psi_i, const Fermion | ||||
|   auto pshift_coeffs = &shift_coeffs[0]; | ||||
|  | ||||
|   // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|   this->M5Dcalls++; | ||||
|   this->M5Dtime -= usecond(); | ||||
|  | ||||
|   int nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t ss = sss*Ls; | ||||
| @@ -115,6 +122,7 @@ void MobiusEOFAFermion<Impl>::M5D_shift(const FermionField &psi_i, const Fermion | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   this->M5Dtime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -135,6 +143,9 @@ void MobiusEOFAFermion<Impl>::M5Ddag(const FermionField &psi_i, const FermionFie | ||||
|   auto plower = &lower[0]; | ||||
|  | ||||
|   // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|   this->M5Dcalls++; | ||||
|   this->M5Dtime -= usecond(); | ||||
|  | ||||
|   int nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(), { | ||||
|     uint64_t ss = sss*Ls; | ||||
| @@ -150,6 +161,8 @@ void MobiusEOFAFermion<Impl>::M5Ddag(const FermionField &psi_i, const FermionFie | ||||
|       coalescedWrite(chi[ss+s], pdiag[s]*phi(ss+s) + pupper[s]*tmp1 + plower[s]*tmp2); | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   this->M5Dtime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -173,6 +186,9 @@ void MobiusEOFAFermion<Impl>::M5Ddag_shift(const FermionField &psi_i, const Ferm | ||||
|   auto pshift_coeffs = &shift_coeffs[0]; | ||||
|  | ||||
|   // Flops = 6.0*(Nc*Ns) *Ls*vol | ||||
|   this->M5Dcalls++; | ||||
|   this->M5Dtime -= usecond(); | ||||
|  | ||||
|   auto pm = this->pm; | ||||
|  | ||||
|   int nloop = grid->oSites()/Ls; | ||||
| @@ -201,6 +217,7 @@ void MobiusEOFAFermion<Impl>::M5Ddag_shift(const FermionField &psi_i, const Ferm | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   this->M5Dtime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -220,6 +237,9 @@ void MobiusEOFAFermion<Impl>::MooeeInv(const FermionField &psi_i, FermionField & | ||||
|  | ||||
|   if(this->shift != 0.0){ MooeeInv_shift(psi_i,chi_i); return; } | ||||
|  | ||||
|   this->MooeeInvCalls++; | ||||
|   this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|   int nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t ss=sss*Ls; | ||||
| @@ -257,6 +277,7 @@ void MobiusEOFAFermion<Impl>::MooeeInv(const FermionField &psi_i, FermionField & | ||||
|     } | ||||
|   }); | ||||
|     | ||||
|   this->MooeeInvTime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -276,6 +297,8 @@ void MobiusEOFAFermion<Impl>::MooeeInv_shift(const FermionField &psi_i, FermionF | ||||
|   auto pueem= & this->ueem[0]; | ||||
|   auto pMooeeInv_shift_lc   = &MooeeInv_shift_lc[0]; | ||||
|   auto pMooeeInv_shift_norm = &MooeeInv_shift_norm[0]; | ||||
|   this->MooeeInvCalls++; | ||||
|   this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|   int nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
| @@ -320,6 +343,7 @@ void MobiusEOFAFermion<Impl>::MooeeInv_shift(const FermionField &psi_i, FermionF | ||||
|       } | ||||
|   }); | ||||
|  | ||||
|   this->MooeeInvTime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -339,6 +363,9 @@ void MobiusEOFAFermion<Impl>::MooeeInvDag(const FermionField &psi_i, FermionFiel | ||||
|   auto pleem= & this->leem[0]; | ||||
|   auto pueem= & this->ueem[0]; | ||||
|  | ||||
|   this->MooeeInvCalls++; | ||||
|   this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|   int nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|     uint64_t ss=sss*Ls; | ||||
| @@ -375,6 +402,7 @@ void MobiusEOFAFermion<Impl>::MooeeInvDag(const FermionField &psi_i, FermionFiel | ||||
|       coalescedWrite(chi[ss+s],res); | ||||
|     } | ||||
|   }); | ||||
|   this->MooeeInvTime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -395,6 +423,9 @@ void MobiusEOFAFermion<Impl>::MooeeInvDag_shift(const FermionField &psi_i, Fermi | ||||
|   auto pMooeeInvDag_shift_lc   = &MooeeInvDag_shift_lc[0]; | ||||
|   auto pMooeeInvDag_shift_norm = &MooeeInvDag_shift_norm[0]; | ||||
|  | ||||
|   this->MooeeInvCalls++; | ||||
|   this->MooeeInvTime -= usecond(); | ||||
|  | ||||
|   int nloop = grid->oSites()/Ls; | ||||
|   accelerator_for(sss,nloop,Simd::Nsimd(),{ | ||||
|       uint64_t ss=sss*Ls; | ||||
| @@ -438,6 +469,7 @@ void MobiusEOFAFermion<Impl>::MooeeInvDag_shift(const FermionField &psi_i, Fermi | ||||
|       } | ||||
|   }); | ||||
|  | ||||
|   this->MooeeInvTime += usecond(); | ||||
| } | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -263,6 +263,7 @@ void NaiveStaggeredFermion<Impl>::DhopDerivEO(GaugeField &mat, const FermionFiel | ||||
| template <class Impl> | ||||
| void NaiveStaggeredFermion<Impl>::Dhop(const FermionField &in, FermionField &out, int dag)  | ||||
| { | ||||
|   DhopCalls+=2; | ||||
|   conformable(in.Grid(), _grid);  // verifies full grid | ||||
|   conformable(in.Grid(), out.Grid()); | ||||
|  | ||||
| @@ -274,6 +275,7 @@ void NaiveStaggeredFermion<Impl>::Dhop(const FermionField &in, FermionField &out | ||||
| template <class Impl> | ||||
| void NaiveStaggeredFermion<Impl>::DhopOE(const FermionField &in, FermionField &out, int dag)  | ||||
| { | ||||
|   DhopCalls+=1; | ||||
|   conformable(in.Grid(), _cbgrid);    // verifies half grid | ||||
|   conformable(in.Grid(), out.Grid());  // drops the cb check | ||||
|  | ||||
| @@ -286,6 +288,7 @@ void NaiveStaggeredFermion<Impl>::DhopOE(const FermionField &in, FermionField &o | ||||
| template <class Impl> | ||||
| void NaiveStaggeredFermion<Impl>::DhopEO(const FermionField &in, FermionField &out, int dag)  | ||||
| { | ||||
|   DhopCalls+=1; | ||||
|   conformable(in.Grid(), _cbgrid);    // verifies half grid | ||||
|   conformable(in.Grid(), out.Grid());  // drops the cb check | ||||
|  | ||||
| @@ -342,33 +345,47 @@ void NaiveStaggeredFermion<Impl>::DhopInternalOverlappedComms(StencilImpl &st, L | ||||
|   Compressor compressor;  | ||||
|   int len =  U.Grid()->oSites(); | ||||
|  | ||||
|   DhopTotalTime   -= usecond(); | ||||
|  | ||||
|   DhopFaceTime    -= usecond(); | ||||
|   st.Prepare(); | ||||
|   st.HaloGather(in,compressor); | ||||
|   DhopFaceTime    += usecond(); | ||||
|  | ||||
|   DhopCommTime -=usecond(); | ||||
|   std::vector<std::vector<CommsRequest_t> > requests; | ||||
|   st.CommunicateBegin(requests); | ||||
|  | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.CommsMergeSHM(compressor); | ||||
|   DhopFaceTime+= usecond(); | ||||
|  | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   // Removed explicit thread comms | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
|   DhopComputeTime    -= usecond(); | ||||
|   { | ||||
|     int interior=1; | ||||
|     int exterior=0; | ||||
|     Kernels::DhopNaive(st,lo,U,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime    += usecond(); | ||||
|  | ||||
|   st.CommunicateComplete(requests); | ||||
|   DhopCommTime +=usecond(); | ||||
|  | ||||
|   // First to enter, last to leave timing | ||||
|   DhopFaceTime    -= usecond(); | ||||
|   st.CommsMerge(compressor); | ||||
|   DhopFaceTime    -= usecond(); | ||||
|  | ||||
|   DhopComputeTime2    -= usecond(); | ||||
|   { | ||||
|     int interior=0; | ||||
|     int exterior=1; | ||||
|     Kernels::DhopNaive(st,lo,U,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime2    += usecond(); | ||||
| } | ||||
|  | ||||
| template <class Impl> | ||||
| @@ -379,16 +396,78 @@ void NaiveStaggeredFermion<Impl>::DhopInternalSerialComms(StencilImpl &st, Lebes | ||||
| { | ||||
|   assert((dag == DaggerNo) || (dag == DaggerYes)); | ||||
|  | ||||
|   DhopTotalTime   -= usecond(); | ||||
|  | ||||
|   DhopCommTime    -= usecond(); | ||||
|   Compressor compressor; | ||||
|   st.HaloExchange(in, compressor); | ||||
|   DhopCommTime    += usecond(); | ||||
|  | ||||
|   DhopComputeTime -= usecond(); | ||||
|   { | ||||
|     int interior=1; | ||||
|     int exterior=1; | ||||
|     Kernels::DhopNaive(st,lo,U,in,out,dag,interior,exterior); | ||||
|   } | ||||
|   DhopComputeTime += usecond(); | ||||
|   DhopTotalTime   += usecond(); | ||||
| }; | ||||
|  | ||||
|   //////////////////////////////////////////////////////////////// | ||||
|   // Reporting | ||||
|   //////////////////////////////////////////////////////////////// | ||||
| template<class Impl> | ||||
| void NaiveStaggeredFermion<Impl>::Report(void)  | ||||
| { | ||||
|   Coordinate latt = _grid->GlobalDimensions(); | ||||
|   RealD volume = 1;  for(int mu=0;mu<Nd;mu++) volume=volume*latt[mu]; | ||||
|   RealD NP = _grid->_Nprocessors; | ||||
|   RealD NN = _grid->NodeCount(); | ||||
|  | ||||
|   std::cout << GridLogMessage << "#### Dhop calls report " << std::endl; | ||||
|  | ||||
|   std::cout << GridLogMessage << "NaiveStaggeredFermion Number of DhopEO Calls   : "  | ||||
| 	    << DhopCalls   << std::endl; | ||||
|   std::cout << GridLogMessage << "NaiveStaggeredFermion TotalTime   /Calls       : "  | ||||
| 	    << DhopTotalTime   / DhopCalls << " us" << std::endl; | ||||
|   std::cout << GridLogMessage << "NaiveStaggeredFermion CommTime    /Calls       : "  | ||||
| 	    << DhopCommTime    / DhopCalls << " us" << std::endl; | ||||
|   std::cout << GridLogMessage << "NaiveStaggeredFermion ComputeTime/Calls        : "  | ||||
| 	    << DhopComputeTime / DhopCalls << " us" << std::endl; | ||||
|  | ||||
|   // Average the compute time | ||||
|   _grid->GlobalSum(DhopComputeTime); | ||||
|   DhopComputeTime/=NP; | ||||
|  | ||||
|   RealD mflops = 1154*volume*DhopCalls/DhopComputeTime/2; // 2 for red black counting | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per rank       : " << mflops/NP << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per node       : " << mflops/NN << std::endl; | ||||
|    | ||||
|   RealD Fullmflops = 1154*volume*DhopCalls/(DhopTotalTime)/2; // 2 for red black counting | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call (full)         : " << Fullmflops << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per rank (full): " << Fullmflops/NP << std::endl; | ||||
|   std::cout << GridLogMessage << "Average mflops/s per call per node (full): " << Fullmflops/NN << std::endl; | ||||
|  | ||||
|   std::cout << GridLogMessage << "NaiveStaggeredFermion Stencil"    <<std::endl;  Stencil.Report(); | ||||
|   std::cout << GridLogMessage << "NaiveStaggeredFermion StencilEven"<<std::endl;  StencilEven.Report(); | ||||
|   std::cout << GridLogMessage << "NaiveStaggeredFermion StencilOdd" <<std::endl;  StencilOdd.Report(); | ||||
| } | ||||
| template<class Impl> | ||||
| void NaiveStaggeredFermion<Impl>::ZeroCounters(void)  | ||||
| { | ||||
|   DhopCalls       = 0; | ||||
|   DhopTotalTime   = 0; | ||||
|   DhopCommTime    = 0; | ||||
|   DhopComputeTime = 0; | ||||
|   DhopFaceTime    = 0; | ||||
|  | ||||
|   Stencil.ZeroCounters(); | ||||
|   StencilEven.ZeroCounters(); | ||||
|   StencilOdd.ZeroCounters(); | ||||
| } | ||||
|  | ||||
|  | ||||
| ////////////////////////////////////////////////////////  | ||||
| // Conserved current - not yet implemented. | ||||
| //////////////////////////////////////////////////////// | ||||
|   | ||||
| @@ -34,8 +34,8 @@ | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| WilsonCloverFermion<Impl, CloverHelpers>::WilsonCloverFermion(GaugeField&                         _Umu, | ||||
| template<class Impl> | ||||
| WilsonCloverFermion<Impl>::WilsonCloverFermion(GaugeField&                         _Umu, | ||||
|                                                GridCartesian&                      Fgrid, | ||||
|                                                GridRedBlackCartesian&              Hgrid, | ||||
|                                                const RealD                         _mass, | ||||
| @@ -74,8 +74,8 @@ WilsonCloverFermion<Impl, CloverHelpers>::WilsonCloverFermion(GaugeField& | ||||
| } | ||||
|  | ||||
| // *NOT* EO | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::M(const FermionField &in, FermionField &out) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::M(const FermionField &in, FermionField &out) | ||||
| { | ||||
|   FermionField temp(out.Grid()); | ||||
|  | ||||
| @@ -89,8 +89,8 @@ void WilsonCloverFermion<Impl, CloverHelpers>::M(const FermionField &in, Fermion | ||||
|   out += temp; | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::Mdag(const FermionField &in, FermionField &out) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::Mdag(const FermionField &in, FermionField &out) | ||||
| { | ||||
|   FermionField temp(out.Grid()); | ||||
|  | ||||
| @@ -104,8 +104,8 @@ void WilsonCloverFermion<Impl, CloverHelpers>::Mdag(const FermionField &in, Ferm | ||||
|   out += temp; | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeField &_Umu) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::ImportGauge(const GaugeField &_Umu) | ||||
| { | ||||
|   double t0 = usecond(); | ||||
|   WilsonFermion<Impl>::ImportGauge(_Umu); | ||||
| @@ -131,11 +131,47 @@ void WilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeField &_Um | ||||
|   CloverTerm += Helpers::fillCloverXT(Ex) * csw_t; | ||||
|   CloverTerm += Helpers::fillCloverYT(Ey) * csw_t; | ||||
|   CloverTerm += Helpers::fillCloverZT(Ez) * csw_t; | ||||
|   CloverTerm += diag_mass; | ||||
|  | ||||
|   double t4 = usecond(); | ||||
|   CloverHelpers::Instantiate(CloverTerm, CloverTermInv, csw_t, this->diag_mass); | ||||
|   int lvol = _Umu.Grid()->lSites(); | ||||
|   int DimRep = Impl::Dimension; | ||||
|  | ||||
|   double t5 = usecond(); | ||||
|   { | ||||
|     autoView(CTv,CloverTerm,CpuRead); | ||||
|     autoView(CTIv,CloverTermInv,CpuWrite); | ||||
|     thread_for(site, lvol, { | ||||
|       Coordinate lcoor; | ||||
|       grid->LocalIndexToLocalCoor(site, lcoor); | ||||
|       Eigen::MatrixXcd EigenCloverOp = Eigen::MatrixXcd::Zero(Ns * DimRep, Ns * DimRep); | ||||
|       Eigen::MatrixXcd EigenInvCloverOp = Eigen::MatrixXcd::Zero(Ns * DimRep, Ns * DimRep); | ||||
|       typename SiteClover::scalar_object Qx = Zero(), Qxinv = Zero(); | ||||
|       peekLocalSite(Qx, CTv, lcoor); | ||||
|       //if (csw!=0){ | ||||
|       for (int j = 0; j < Ns; j++) | ||||
| 	for (int k = 0; k < Ns; k++) | ||||
| 	  for (int a = 0; a < DimRep; a++) | ||||
| 	    for (int b = 0; b < DimRep; b++){ | ||||
| 	      auto zz =  Qx()(j, k)(a, b); | ||||
| 	      EigenCloverOp(a + j * DimRep, b + k * DimRep) = std::complex<double>(zz); | ||||
| 	    } | ||||
|       //   if (site==0) std::cout << "site =" << site << "\n" << EigenCloverOp << std::endl; | ||||
|        | ||||
|       EigenInvCloverOp = EigenCloverOp.inverse(); | ||||
|       //std::cout << EigenInvCloverOp << std::endl; | ||||
|       for (int j = 0; j < Ns; j++) | ||||
| 	for (int k = 0; k < Ns; k++) | ||||
| 	  for (int a = 0; a < DimRep; a++) | ||||
| 	    for (int b = 0; b < DimRep; b++) | ||||
| 	      Qxinv()(j, k)(a, b) = EigenInvCloverOp(a + j * DimRep, b + k * DimRep); | ||||
|       //    if (site==0) std::cout << "site =" << site << "\n" << EigenInvCloverOp << std::endl; | ||||
|       //  } | ||||
|       pokeLocalSite(Qxinv, CTIv, lcoor); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   double t6 = usecond(); | ||||
|   // Separate the even and odd parts | ||||
|   pickCheckerboard(Even, CloverTermEven, CloverTerm); | ||||
|   pickCheckerboard(Odd, CloverTermOdd, CloverTerm); | ||||
| @@ -148,44 +184,48 @@ void WilsonCloverFermion<Impl, CloverHelpers>::ImportGauge(const GaugeField &_Um | ||||
|  | ||||
|   pickCheckerboard(Even, CloverTermInvDagEven, adj(CloverTermInv)); | ||||
|   pickCheckerboard(Odd, CloverTermInvDagOdd, adj(CloverTermInv)); | ||||
|   double t6 = usecond(); | ||||
|   double t7 = usecond(); | ||||
|  | ||||
|   std::cout << GridLogDebug << "WilsonCloverFermion::ImportGauge timings:" << std::endl; | ||||
|   std::cout << GridLogDebug << "WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "allocations =                " << (t2 - t1) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "field strength =             " << (t3 - t2) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "fill clover =                " << (t4 - t3) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "instantiation =              " << (t5 - t4) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "pick cbs =                   " << (t6 - t5) / 1e6 << std::endl; | ||||
|   std::cout << GridLogDebug << "total =                      " << (t6 - t0) / 1e6 << std::endl; | ||||
| #if 0 | ||||
|   std::cout << GridLogMessage << "WilsonCloverFermion::ImportGauge timings:" | ||||
|             << " WilsonFermion::Importgauge = " << (t1 - t0) / 1e6 | ||||
|             << ", allocations = "               << (t2 - t1) / 1e6 | ||||
|             << ", field strength = "            << (t3 - t2) / 1e6 | ||||
|             << ", fill clover = "               << (t4 - t3) / 1e6 | ||||
|             << ", misc = "                      << (t5 - t4) / 1e6 | ||||
|             << ", inversions = "                << (t6 - t5) / 1e6 | ||||
|             << ", pick cbs = "                  << (t7 - t6) / 1e6 | ||||
|             << ", total = "                     << (t7 - t0) / 1e6 | ||||
|             << std::endl; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::Mooee(const FermionField &in, FermionField &out) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::Mooee(const FermionField &in, FermionField &out) | ||||
| { | ||||
|   this->MooeeInternal(in, out, DaggerNo, InverseNo); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooeeDag(const FermionField &in, FermionField &out) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MooeeDag(const FermionField &in, FermionField &out) | ||||
| { | ||||
|   this->MooeeInternal(in, out, DaggerYes, InverseNo); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooeeInv(const FermionField &in, FermionField &out) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MooeeInv(const FermionField &in, FermionField &out) | ||||
| { | ||||
|   this->MooeeInternal(in, out, DaggerNo, InverseYes); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooeeInvDag(const FermionField &in, FermionField &out) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MooeeInvDag(const FermionField &in, FermionField &out) | ||||
| { | ||||
|   this->MooeeInternal(in, out, DaggerYes, InverseYes); | ||||
| } | ||||
|  | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooeeInternal(const FermionField &in, FermionField &out, int dag, int inv) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MooeeInternal(const FermionField &in, FermionField &out, int dag, int inv) | ||||
| { | ||||
|   out.Checkerboard() = in.Checkerboard(); | ||||
|   CloverField *Clover; | ||||
| @@ -238,8 +278,8 @@ void WilsonCloverFermion<Impl, CloverHelpers>::MooeeInternal(const FermionField | ||||
| } // MooeeInternal | ||||
|  | ||||
| // Derivative parts unpreconditioned pseudofermions | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField &force, const FermionField &X, const FermionField &Y, int dag) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MDeriv(GaugeField &force, const FermionField &X, const FermionField &Y, int dag) | ||||
| { | ||||
|   conformable(X.Grid(), Y.Grid()); | ||||
|   conformable(X.Grid(), force.Grid()); | ||||
| @@ -309,7 +349,7 @@ void WilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField &force, const F | ||||
|       } | ||||
|       PropagatorField Slambda = Gamma(sigma[count]) * Lambda; // sigma checked | ||||
|       Impl::TraceSpinImpl(lambda, Slambda);                   // traceSpin ok | ||||
|       force_mu -= factor*CloverHelpers::Cmunu(U, lambda, mu, nu);                   // checked | ||||
|       force_mu -= factor*Helpers::Cmunu(U, lambda, mu, nu);                   // checked | ||||
|       count++; | ||||
|     } | ||||
|  | ||||
| @@ -320,15 +360,15 @@ void WilsonCloverFermion<Impl, CloverHelpers>::MDeriv(GaugeField &force, const F | ||||
| } | ||||
|  | ||||
| // Derivative parts | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MooDeriv(GaugeField &mat, const FermionField &X, const FermionField &Y, int dag) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MooDeriv(GaugeField &mat, const FermionField &X, const FermionField &Y, int dag) | ||||
| { | ||||
|   assert(0); | ||||
| } | ||||
|  | ||||
| // Derivative parts | ||||
| template<class Impl, class CloverHelpers> | ||||
| void WilsonCloverFermion<Impl, CloverHelpers>::MeeDeriv(GaugeField &mat, const FermionField &U, const FermionField &V, int dag) | ||||
| template <class Impl> | ||||
| void WilsonCloverFermion<Impl>::MeeDeriv(GaugeField &mat, const FermionField &U, const FermionField &V, int dag) | ||||
| { | ||||
|   assert(0); // not implemented yet | ||||
| } | ||||
|   | ||||
| @@ -60,13 +60,8 @@ WilsonFermion5D<Impl>::WilsonFermion5D(GaugeField &_Umu, | ||||
|   UmuOdd (_FourDimRedBlackGrid), | ||||
|   Lebesgue(_FourDimGrid), | ||||
|   LebesgueEvenOdd(_FourDimRedBlackGrid), | ||||
|   _tmp(&FiveDimRedBlackGrid), | ||||
|   Dirichlet(0) | ||||
|   _tmp(&FiveDimRedBlackGrid) | ||||
| { | ||||
|   Stencil.lo     = &Lebesgue; | ||||
|   StencilEven.lo = &LebesgueEvenOdd; | ||||
|   StencilOdd.lo  = &LebesgueEvenOdd; | ||||
|    | ||||
|   // some assertions | ||||
|   assert(FiveDimGrid._ndimension==5); | ||||
|   assert(FourDimGrid._ndimension==4); | ||||
| @@ -96,19 +91,6 @@ WilsonFermion5D<Impl>::WilsonFermion5D(GaugeField &_Umu, | ||||
|     assert(FourDimRedBlackGrid._simd_layout[d]  ==FourDimGrid._simd_layout[d]); | ||||
|   } | ||||
|  | ||||
|   if ( p.dirichlet.size() == Nd+1) { | ||||
|     Coordinate block = p.dirichlet; | ||||
|     if ( block[0] || block[1] || block[2] || block[3] || block[4] ){ | ||||
|       Dirichlet = 1; | ||||
|       std::cout << GridLogMessage << " WilsonFermion: non-trivial Dirichlet condition "<< block << std::endl; | ||||
|       std::cout << GridLogMessage << " WilsonFermion: partial Dirichlet "<< p.partialDirichlet << std::endl; | ||||
|       Block = block; | ||||
|     } | ||||
|   } else { | ||||
|     Coordinate block(Nd+1,0); | ||||
|     Block = block; | ||||
|   } | ||||
|  | ||||
|   if (Impl::LsVectorised) {  | ||||
|  | ||||
|     int nsimd = Simd::Nsimd(); | ||||
| @@ -143,38 +125,99 @@ WilsonFermion5D<Impl>::WilsonFermion5D(GaugeField &_Umu, | ||||
|   StencilEven.BuildSurfaceList(LLs,vol4); | ||||
|    StencilOdd.BuildSurfaceList(LLs,vol4); | ||||
|  | ||||
|    //  std::cout << GridLogMessage << " SurfaceLists "<< Stencil.surface_list.size() | ||||
|    //                       <<" " << StencilEven.surface_list.size()<<std::endl; | ||||
|  | ||||
| } | ||||
|       | ||||
| template<class Impl> | ||||
| void WilsonFermion5D<Impl>::Report(void) | ||||
| { | ||||
|   RealD NP     = _FourDimGrid->_Nprocessors; | ||||
|   RealD NN     = _FourDimGrid->NodeCount(); | ||||
|   RealD volume = Ls;   | ||||
|   Coordinate latt = _FourDimGrid->GlobalDimensions(); | ||||
|   for(int mu=0;mu<Nd;mu++) volume=volume*latt[mu]; | ||||
|  | ||||
|   if ( DhopCalls > 0 ) { | ||||
|     std::cout << GridLogMessage << "#### Dhop calls report " << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D Number of DhopEO Calls   : " << DhopCalls   << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D TotalTime   /Calls        : " << DhopTotalTime   / DhopCalls << " us" << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D CommTime    /Calls        : " << DhopCommTime    / DhopCalls << " us" << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D FaceTime    /Calls        : " << DhopFaceTime    / DhopCalls << " us" << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D ComputeTime1/Calls        : " << DhopComputeTime / DhopCalls << " us" << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D ComputeTime2/Calls        : " << DhopComputeTime2/ DhopCalls << " us" << std::endl; | ||||
|  | ||||
|     // Average the compute time | ||||
|     _FourDimGrid->GlobalSum(DhopComputeTime); | ||||
|     DhopComputeTime/=NP; | ||||
|     RealD mflops = 1344*volume*DhopCalls/DhopComputeTime/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per rank       : " << mflops/NP << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per node       : " << mflops/NN << std::endl; | ||||
|  | ||||
|     RealD Fullmflops = 1344*volume*DhopCalls/(DhopTotalTime)/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call (full)         : " << Fullmflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per rank (full): " << Fullmflops/NP << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per node (full): " << Fullmflops/NN << std::endl; | ||||
|  | ||||
|    } | ||||
|  | ||||
|   if ( DerivCalls > 0 ) { | ||||
|     std::cout << GridLogMessage << "#### Deriv calls report "<< std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D Number of Deriv Calls    : " <<DerivCalls <<std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D CommTime/Calls           : " <<DerivCommTime/DerivCalls<<" us" <<std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D ComputeTime/Calls        : " <<DerivComputeTime/DerivCalls<<" us" <<std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D Dhop ComputeTime/Calls   : " <<DerivDhopComputeTime/DerivCalls<<" us" <<std::endl; | ||||
|      | ||||
|     RealD mflops = 144*volume*DerivCalls/DerivDhopComputeTime; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per node       : " << mflops/NP << std::endl; | ||||
|  | ||||
|     RealD Fullmflops = 144*volume*DerivCalls/(DerivDhopComputeTime+DerivCommTime)/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call (full)         : " << Fullmflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per node (full): " << Fullmflops/NP << std::endl;  } | ||||
|  | ||||
|   if (DerivCalls > 0 || DhopCalls > 0){ | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D Stencil"    <<std::endl;  Stencil.Report(); | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D StencilEven"<<std::endl;  StencilEven.Report(); | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D StencilOdd" <<std::endl;  StencilOdd.Report(); | ||||
|   } | ||||
|   if ( DhopCalls > 0){ | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D Stencil     Reporti()"    <<std::endl;  Stencil.Reporti(DhopCalls); | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D StencilEven Reporti()"<<std::endl;  StencilEven.Reporti(DhopCalls); | ||||
|     std::cout << GridLogMessage << "WilsonFermion5D StencilOdd  Reporti()" <<std::endl;  StencilOdd.Reporti(DhopCalls); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void WilsonFermion5D<Impl>::ZeroCounters(void) { | ||||
|   DhopCalls       = 0; | ||||
|   DhopCommTime    = 0; | ||||
|   DhopComputeTime = 0; | ||||
|   DhopComputeTime2= 0; | ||||
|   DhopFaceTime    = 0; | ||||
|   DhopTotalTime   = 0; | ||||
|  | ||||
|   DerivCalls       = 0; | ||||
|   DerivCommTime    = 0; | ||||
|   DerivComputeTime = 0; | ||||
|   DerivDhopComputeTime = 0; | ||||
|  | ||||
|   Stencil.ZeroCounters(); | ||||
|   StencilEven.ZeroCounters(); | ||||
|   StencilOdd.ZeroCounters(); | ||||
|   Stencil.ZeroCountersi(); | ||||
|   StencilEven.ZeroCountersi(); | ||||
|   StencilOdd.ZeroCountersi(); | ||||
| } | ||||
|  | ||||
|  | ||||
| template<class Impl> | ||||
| void WilsonFermion5D<Impl>::ImportGauge(const GaugeField &_Umu) | ||||
| { | ||||
|   GaugeField HUmu(_Umu.Grid()); | ||||
|   HUmu = _Umu*(-0.5); | ||||
|   if ( Dirichlet ) { | ||||
|  | ||||
|     if ( this->Params.partialDirichlet ) { | ||||
|       std::cout << GridLogMessage << " partialDirichlet BCs " <<Block<<std::endl; | ||||
|     } else { | ||||
|       std::cout << GridLogMessage << " FULL Dirichlet BCs " <<Block<<std::endl; | ||||
|     } | ||||
|      | ||||
|     std:: cout << GridLogMessage << "Checking block size multiple of rank boundaries for Dirichlet"<<std::endl; | ||||
|     for(int d=0;d<Nd;d++) { | ||||
|       int GaugeBlock = Block[d+1]; | ||||
|       int ldim=GaugeGrid()->LocalDimensions()[d]; | ||||
|       if (GaugeBlock) assert( (GaugeBlock%ldim)==0); | ||||
|     } | ||||
|  | ||||
|     if (!this->Params.partialDirichlet) { | ||||
|       std::cout << GridLogMessage << " Dirichlet filtering gauge field BCs block " <<Block<<std::endl; | ||||
|       Coordinate GaugeBlock(Nd); | ||||
|       for(int d=0;d<Nd;d++) GaugeBlock[d] = Block[d+1]; | ||||
|       DirichletFilter<GaugeField> Filter(GaugeBlock); | ||||
|       Filter.applyFilter(HUmu); | ||||
|     } else { | ||||
|       std::cout << GridLogMessage << " Dirichlet "<< Dirichlet << " NOT filtered gauge field" <<std::endl; | ||||
|     } | ||||
|   } | ||||
|   Impl::DoubleStore(GaugeGrid(),Umu,HUmu); | ||||
|   pickCheckerboard(Even,UmuEven,Umu); | ||||
|   pickCheckerboard(Odd ,UmuOdd,Umu); | ||||
| @@ -216,6 +259,7 @@ void WilsonFermion5D<Impl>::DerivInternal(StencilImpl & st, | ||||
| 					  const FermionField &B, | ||||
| 					  int dag) | ||||
| { | ||||
|   DerivCalls++; | ||||
|   assert((dag==DaggerNo) ||(dag==DaggerYes)); | ||||
|  | ||||
|   conformable(st.Grid(),A.Grid()); | ||||
| @@ -226,12 +270,15 @@ void WilsonFermion5D<Impl>::DerivInternal(StencilImpl & st, | ||||
|   FermionField Btilde(B.Grid()); | ||||
|   FermionField Atilde(B.Grid()); | ||||
|  | ||||
|   DerivCommTime-=usecond(); | ||||
|   st.HaloExchange(B,compressor); | ||||
|   DerivCommTime+=usecond(); | ||||
|  | ||||
|   Atilde=A; | ||||
|   int LLs = B.Grid()->_rdimensions[0]; | ||||
|  | ||||
|  | ||||
|   DerivComputeTime-=usecond(); | ||||
|   for (int mu = 0; mu < Nd; mu++) { | ||||
|     //////////////////////////////////////////////////////////////////////// | ||||
|     // Flip gamma if dag | ||||
| @@ -243,6 +290,8 @@ void WilsonFermion5D<Impl>::DerivInternal(StencilImpl & st, | ||||
|     // Call the single hop | ||||
|     //////////////////////// | ||||
|  | ||||
|     DerivDhopComputeTime -= usecond(); | ||||
|  | ||||
|     int Usites = U.Grid()->oSites(); | ||||
|  | ||||
|     Kernels::DhopDirKernel(st, U, st.CommBuf(), Ls, Usites, B, Btilde, mu,gamma); | ||||
| @@ -250,8 +299,10 @@ void WilsonFermion5D<Impl>::DerivInternal(StencilImpl & st, | ||||
|     //////////////////////////// | ||||
|     // spin trace outer product | ||||
|     //////////////////////////// | ||||
|     DerivDhopComputeTime += usecond(); | ||||
|     Impl::InsertForce5D(mat, Btilde, Atilde, mu); | ||||
|   } | ||||
|   DerivComputeTime += usecond(); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| @@ -309,10 +360,12 @@ void WilsonFermion5D<Impl>::DhopInternal(StencilImpl & st, LebesgueOrder &lo, | ||||
|                                          DoubledGaugeField & U, | ||||
|                                          const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   DhopTotalTime-=usecond(); | ||||
|   if ( WilsonKernelsStatic::Comms == WilsonKernelsStatic::CommsAndCompute ) | ||||
|     DhopInternalOverlappedComms(st,lo,U,in,out,dag); | ||||
|   else  | ||||
|     DhopInternalSerialComms(st,lo,U,in,out,dag); | ||||
|   DhopTotalTime+=usecond(); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -321,7 +374,6 @@ void WilsonFermion5D<Impl>::DhopInternalOverlappedComms(StencilImpl & st, Lebesg | ||||
| 							DoubledGaugeField & U, | ||||
| 							const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   GRID_TRACE("DhopInternalOverlappedComms"); | ||||
|   Compressor compressor(dag); | ||||
|  | ||||
|   int LLs = in.Grid()->_rdimensions[0]; | ||||
| @@ -330,58 +382,53 @@ void WilsonFermion5D<Impl>::DhopInternalOverlappedComms(StencilImpl & st, Lebesg | ||||
|   ///////////////////////////// | ||||
|   // Start comms  // Gather intranode and extra node differentiated?? | ||||
|   ///////////////////////////// | ||||
|   { | ||||
|     GRID_TRACE("Gather"); | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.HaloExchangeOptGather(in,compressor); | ||||
|     accelerator_barrier(); | ||||
|   } | ||||
|   DhopFaceTime+=usecond(); | ||||
|  | ||||
|   DhopCommTime -=usecond(); | ||||
|   std::vector<std::vector<CommsRequest_t> > requests; | ||||
|   auto id=traceStart("Communicate overlapped"); | ||||
|   st.CommunicateBegin(requests); | ||||
|  | ||||
|   ///////////////////////////// | ||||
|   // Overlap with comms | ||||
|   ///////////////////////////// | ||||
|   { | ||||
|     GRID_TRACE("MergeSHM"); | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.CommsMergeSHM(compressor);// Could do this inside parallel region overlapped with comms | ||||
|   } | ||||
|   DhopFaceTime+=usecond(); | ||||
|        | ||||
|   ///////////////////////////// | ||||
|   // do the compute interior | ||||
|   ///////////////////////////// | ||||
|   int Opt = WilsonKernelsStatic::Opt; // Why pass this. Kernels should know | ||||
|   DhopComputeTime-=usecond(); | ||||
|   if (dag == DaggerYes) { | ||||
|     GRID_TRACE("DhopDagInterior"); | ||||
|     Kernels::DhopDagKernel(Opt,st,U,st.CommBuf(),LLs,U.oSites(),in,out,1,0); | ||||
|   } else { | ||||
|     GRID_TRACE("DhopInterior"); | ||||
|     Kernels::DhopKernel   (Opt,st,U,st.CommBuf(),LLs,U.oSites(),in,out,1,0); | ||||
|   } | ||||
|   DhopComputeTime+=usecond(); | ||||
|  | ||||
|   ///////////////////////////// | ||||
|   // Complete comms | ||||
|   ///////////////////////////// | ||||
|   st.CommunicateComplete(requests); | ||||
|   traceStop(id); | ||||
|   DhopCommTime   +=usecond(); | ||||
|  | ||||
|   ///////////////////////////// | ||||
|   // do the compute exterior | ||||
|   ///////////////////////////// | ||||
|   { | ||||
|     GRID_TRACE("Merge"); | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.CommsMerge(compressor); | ||||
|   } | ||||
|    | ||||
|   DhopFaceTime+=usecond(); | ||||
|  | ||||
|   DhopComputeTime2-=usecond(); | ||||
|   if (dag == DaggerYes) { | ||||
|     GRID_TRACE("DhopDagExterior"); | ||||
|     Kernels::DhopDagKernel(Opt,st,U,st.CommBuf(),LLs,U.oSites(),in,out,0,1); | ||||
|   } else { | ||||
|     GRID_TRACE("DhopExterior"); | ||||
|     Kernels::DhopKernel   (Opt,st,U,st.CommBuf(),LLs,U.oSites(),in,out,0,1); | ||||
|   } | ||||
|   DhopComputeTime2+=usecond(); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -391,30 +438,29 @@ void WilsonFermion5D<Impl>::DhopInternalSerialComms(StencilImpl & st, LebesgueOr | ||||
| 						    const FermionField &in,  | ||||
| 						    FermionField &out,int dag) | ||||
| { | ||||
|   GRID_TRACE("DhopInternalSerialComms"); | ||||
|   Compressor compressor(dag); | ||||
|  | ||||
|   int LLs = in.Grid()->_rdimensions[0]; | ||||
|    | ||||
|   { | ||||
|     GRID_TRACE("HaloExchange"); | ||||
|   DhopCommTime-=usecond(); | ||||
|   st.HaloExchangeOpt(in,compressor); | ||||
|   } | ||||
|   DhopCommTime+=usecond(); | ||||
|    | ||||
|   DhopComputeTime-=usecond(); | ||||
|   int Opt = WilsonKernelsStatic::Opt; | ||||
|   if (dag == DaggerYes) { | ||||
|     GRID_TRACE("DhopDag"); | ||||
|     Kernels::DhopDagKernel(Opt,st,U,st.CommBuf(),LLs,U.oSites(),in,out); | ||||
|   } else { | ||||
|     GRID_TRACE("Dhop"); | ||||
|     Kernels::DhopKernel(Opt,st,U,st.CommBuf(),LLs,U.oSites(),in,out); | ||||
|   } | ||||
|   DhopComputeTime+=usecond(); | ||||
| } | ||||
|  | ||||
|  | ||||
| template<class Impl> | ||||
| void WilsonFermion5D<Impl>::DhopOE(const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   DhopCalls++; | ||||
|   conformable(in.Grid(),FermionRedBlackGrid());    // verifies half grid | ||||
|   conformable(in.Grid(),out.Grid()); // drops the cb check | ||||
|  | ||||
| @@ -426,6 +472,7 @@ void WilsonFermion5D<Impl>::DhopOE(const FermionField &in, FermionField &out,int | ||||
| template<class Impl> | ||||
| void WilsonFermion5D<Impl>::DhopEO(const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   DhopCalls++; | ||||
|   conformable(in.Grid(),FermionRedBlackGrid());    // verifies half grid | ||||
|   conformable(in.Grid(),out.Grid()); // drops the cb check | ||||
|  | ||||
| @@ -437,6 +484,7 @@ void WilsonFermion5D<Impl>::DhopEO(const FermionField &in, FermionField &out,int | ||||
| template<class Impl> | ||||
| void WilsonFermion5D<Impl>::Dhop(const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   DhopCalls+=2; | ||||
|   conformable(in.Grid(),FermionGrid()); // verifies full grid | ||||
|   conformable(in.Grid(),out.Grid()); | ||||
|  | ||||
| @@ -491,17 +539,12 @@ void WilsonFermion5D<Impl>::MomentumSpacePropagatorHt_5d(FermionField &out,const | ||||
|   LatComplex    sk(_grid);  sk = Zero(); | ||||
|   LatComplex    sk2(_grid); sk2= Zero(); | ||||
|   LatComplex    W(_grid); W= Zero(); | ||||
|   LatComplex    a(_grid); a= Zero(); | ||||
|   LatComplex    one  (_grid); one = ScalComplex(1.0,0.0); | ||||
|   LatComplex 	cosha(_grid); | ||||
|   LatComplex 	kmu(_grid); | ||||
|   LatComplex 	Wea(_grid); | ||||
|   LatComplex 	Wema(_grid); | ||||
|   LatComplex 	ea(_grid); | ||||
|   LatComplex 	ema(_grid); | ||||
|   LatComplex 	eaLs(_grid); | ||||
|   LatComplex 	emaLs(_grid); | ||||
|   LatComplex 	ea2Ls(_grid); | ||||
|   LatComplex 	ema2Ls(_grid); | ||||
|   LatComplex 	sinha(_grid); | ||||
|   LatComplex 	sinhaLs(_grid); | ||||
|   LatComplex 	coshaLs(_grid); | ||||
| @@ -536,29 +579,39 @@ void WilsonFermion5D<Impl>::MomentumSpacePropagatorHt_5d(FermionField &out,const | ||||
|   //////////////////////////////////////////// | ||||
|   cosha = (one + W*W + sk) / (abs(W)*2.0); | ||||
|  | ||||
|   ea = (cosha + sqrt(cosha*cosha-one)); | ||||
|   ema= (cosha - sqrt(cosha*cosha-one)); | ||||
|   eaLs = pow(ea,Ls); | ||||
|   emaLs= pow(ema,Ls); | ||||
|   ea2Ls = pow(ea,2.0*Ls); | ||||
|   ema2Ls= pow(ema,2.0*Ls); | ||||
|   Wea= abs(W) * ea; | ||||
|   Wema= abs(W) * ema; | ||||
|   //  a=log(ea); | ||||
|   // FIXME Need a Lattice acosh | ||||
|  | ||||
|   sinha = 0.5*(ea - ema); | ||||
|   sinhaLs = 0.5*(eaLs-emaLs); | ||||
|   coshaLs = 0.5*(eaLs+emaLs); | ||||
|   { | ||||
|     autoView(cosha_v,cosha,CpuRead); | ||||
|     autoView(a_v,a,CpuWrite); | ||||
|     for(int idx=0;idx<_grid->lSites();idx++){ | ||||
|       Coordinate lcoor(Nd); | ||||
|       Tcomplex cc; | ||||
|       //    RealD sgn; | ||||
|       _grid->LocalIndexToLocalCoor(idx,lcoor); | ||||
|       peekLocalSite(cc,cosha_v,lcoor); | ||||
|       assert((double)real(cc)>=1.0); | ||||
|       assert(fabs((double)imag(cc))<=1.0e-15); | ||||
|       cc = ScalComplex(::acosh(real(cc)),0.0); | ||||
|       pokeLocalSite(cc,a_v,lcoor); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Wea = ( exp( a) * abs(W)  ); | ||||
|   Wema= ( exp(-a) * abs(W)  ); | ||||
|   sinha = 0.5*(exp( a) - exp(-a)); | ||||
|   sinhaLs = 0.5*(exp( a*Ls) - exp(-a*Ls)); | ||||
|   coshaLs = 0.5*(exp( a*Ls) + exp(-a*Ls)); | ||||
|  | ||||
|   A = one / (abs(W) * sinha * 2.0) * one / (sinhaLs * 2.0); | ||||
|   F = eaLs * (one - Wea + (Wema - one) * mass*mass); | ||||
|   F = F + emaLs * (Wema - one + (one - Wea) * mass*mass); | ||||
|   F = exp( a*Ls) * (one - Wea + (Wema - one) * mass*mass); | ||||
|   F = F + exp(-a*Ls) * (Wema - one + (one - Wea) * mass*mass); | ||||
|   F = F - abs(W) * sinha * 4.0 * mass; | ||||
|  | ||||
|   Bpp =  (A/F) * (ema2Ls - one) * (one - Wema) * (one - mass*mass * one); | ||||
|   Bmm =  (A/F) * (one - ea2Ls)  * (one - Wea) * (one - mass*mass * one); | ||||
|   App =  (A/F) * (ema2Ls - one) * ema * (ema - abs(W)) * (one - mass*mass * one); | ||||
|   Amm =  (A/F) * (one - ea2Ls)  * ea  * (ea  - abs(W)) * (one - mass*mass * one); | ||||
|   Bpp =  (A/F) * (exp(-a*Ls*2.0) - one) * (one - Wema) * (one - mass*mass * one); | ||||
|   Bmm =  (A/F) * (one - exp(a*Ls*2.0)) * (one - Wea) * (one - mass*mass * one); | ||||
|   App =  (A/F) * (exp(-a*Ls*2.0) - one) * exp(-a) * (exp(-a) - abs(W)) * (one - mass*mass * one); | ||||
|   Amm =  (A/F) * (one - exp(a*Ls*2.0)) * exp(a) * (exp(a) - abs(W)) * (one - mass*mass * one); | ||||
|   ABpm = (A/F) * abs(W) * sinha * 2.0  * (one + mass * coshaLs * 2.0 + mass*mass * one); | ||||
|  | ||||
|   //P+ source, P- source | ||||
| @@ -581,29 +634,29 @@ void WilsonFermion5D<Impl>::MomentumSpacePropagatorHt_5d(FermionField &out,const | ||||
|       buf1_4d = Zero(); | ||||
|       ExtractSlice(buf1_4d, PRsource, (tt-1), 0); | ||||
|       //G(s,t) | ||||
|       bufR_4d = bufR_4d + A * eaLs * pow(ema,f) * signW * buf1_4d + A * emaLs * pow(ea,f) * signW * buf1_4d; | ||||
|       bufR_4d = bufR_4d + A * exp(a*Ls) * exp(-a*f) * signW * buf1_4d + A * exp(-a*Ls) * exp(a*f) * signW * buf1_4d; | ||||
|       //A++*exp(a(s+t)) | ||||
|       bufR_4d = bufR_4d + App * pow(ea,ss) * pow(ea,tt) * signW * buf1_4d ; | ||||
|       bufR_4d = bufR_4d + App * exp(a*ss) * exp(a*tt) * signW * buf1_4d ; | ||||
|       //A+-*exp(a(s-t)) | ||||
|       bufR_4d = bufR_4d + ABpm * pow(ea,ss) * pow(ema,tt) * signW * buf1_4d ; | ||||
|       bufR_4d = bufR_4d + ABpm * exp(a*ss) * exp(-a*tt) * signW * buf1_4d ; | ||||
|       //A-+*exp(a(-s+t)) | ||||
|       bufR_4d = bufR_4d + ABpm * pow(ema,ss) * pow(ea,tt) * signW * buf1_4d ; | ||||
|       bufR_4d = bufR_4d + ABpm * exp(-a*ss) * exp(a*tt) * signW * buf1_4d ; | ||||
|       //A--*exp(a(-s-t)) | ||||
|       bufR_4d = bufR_4d + Amm * pow(ema,ss) * pow(ema,tt) * signW * buf1_4d ; | ||||
|       bufR_4d = bufR_4d + Amm * exp(-a*ss) * exp(-a*tt) * signW * buf1_4d ; | ||||
|  | ||||
|       //GL | ||||
|       buf2_4d = Zero(); | ||||
|       ExtractSlice(buf2_4d, PLsource, (tt-1), 0); | ||||
|       //G(s,t) | ||||
|       bufL_4d = bufL_4d + A * eaLs * pow(ema,f) * signW * buf2_4d + A * emaLs * pow(ea,f) * signW * buf2_4d; | ||||
|       bufL_4d = bufL_4d + A * exp(a*Ls) * exp(-a*f) * signW * buf2_4d + A * exp(-a*Ls) * exp(a*f) * signW * buf2_4d; | ||||
|       //B++*exp(a(s+t)) | ||||
|       bufL_4d = bufL_4d + Bpp * pow(ea,ss) * pow(ea,tt) * signW * buf2_4d ; | ||||
|       bufL_4d = bufL_4d + Bpp * exp(a*ss) * exp(a*tt) * signW * buf2_4d ; | ||||
|       //B+-*exp(a(s-t)) | ||||
|       bufL_4d = bufL_4d + ABpm * pow(ea,ss) * pow(ema,tt) * signW * buf2_4d ; | ||||
|       bufL_4d = bufL_4d + ABpm * exp(a*ss) * exp(-a*tt) * signW * buf2_4d ; | ||||
|       //B-+*exp(a(-s+t)) | ||||
|       bufL_4d = bufL_4d + ABpm * pow(ema,ss) * pow(ea,tt) * signW * buf2_4d ; | ||||
|       bufL_4d = bufL_4d + ABpm * exp(-a*ss) * exp(a*tt) * signW * buf2_4d ; | ||||
|       //B--*exp(a(-s-t)) | ||||
|       bufL_4d = bufL_4d + Bmm * pow(ema,ss) * pow(ema,tt) * signW * buf2_4d ; | ||||
|       bufL_4d = bufL_4d + Bmm * exp(-a*ss) * exp(-a*tt) * signW * buf2_4d ; | ||||
|     } | ||||
|     InsertSlice(bufR_4d, GR, (ss-1), 0); | ||||
|     InsertSlice(bufL_4d, GL, (ss-1), 0); | ||||
| @@ -722,12 +775,28 @@ void WilsonFermion5D<Impl>::MomentumSpacePropagatorHt(FermionField &out,const Fe | ||||
|   W = one - M5 + sk2; | ||||
|  | ||||
|   //////////////////////////////////////////// | ||||
|   // Cosh alpha -> exp(+/- alpha) | ||||
|   // Cosh alpha -> alpha | ||||
|   //////////////////////////////////////////// | ||||
|   cosha =  (one + W*W + sk) / (abs(W)*2.0); | ||||
|  | ||||
|   Wea = abs(W)*(cosha + sqrt(cosha*cosha-one)); | ||||
|   Wema= abs(W)*(cosha - sqrt(cosha*cosha-one)); | ||||
|   // FIXME Need a Lattice acosh | ||||
|   { | ||||
|   autoView(cosha_v,cosha,CpuRead); | ||||
|   autoView(a_v,a,CpuWrite); | ||||
|   for(int idx=0;idx<_grid->lSites();idx++){ | ||||
|     Coordinate lcoor(Nd); | ||||
|     Tcomplex cc; | ||||
|     //    RealD sgn; | ||||
|     _grid->LocalIndexToLocalCoor(idx,lcoor); | ||||
|     peekLocalSite(cc,cosha_v,lcoor); | ||||
|     assert((double)real(cc)>=1.0); | ||||
|     assert(fabs((double)imag(cc))<=1.0e-15); | ||||
|     cc = ScalComplex(::acosh(real(cc)),0.0); | ||||
|     pokeLocalSite(cc,a_v,lcoor); | ||||
|   }} | ||||
|    | ||||
|   Wea = ( exp( a) * abs(W)  ); | ||||
|   Wema= ( exp(-a) * abs(W)  ); | ||||
|    | ||||
|   num   = num + ( one - Wema ) * mass * in; | ||||
|   denom= ( Wea - one ) + mass*mass * (one - Wema);  | ||||
|   | ||||
| @@ -4,13 +4,12 @@ Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/WilsonFermion.cc | ||||
|  | ||||
| Copyright (C) 2022 | ||||
| Copyright (C) 2015 | ||||
|  | ||||
| Author: Peter Boyle <pabobyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Fabian Joswig <fabian.joswig@ed.ac.uk> | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| @@ -60,9 +59,6 @@ WilsonFermion<Impl>::WilsonFermion(GaugeField &_Umu, GridCartesian &Fgrid, | ||||
|       _tmp(&Hgrid), | ||||
|       anisotropyCoeff(anis) | ||||
| { | ||||
|   Stencil.lo     = &Lebesgue; | ||||
|   StencilEven.lo = &LebesgueEvenOdd; | ||||
|   StencilOdd.lo  = &LebesgueEvenOdd; | ||||
|   // Allocate the required comms buffer | ||||
|   ImportGauge(_Umu); | ||||
|   if  (anisotropyCoeff.isAnisotropic){ | ||||
| @@ -79,6 +75,91 @@ WilsonFermion<Impl>::WilsonFermion(GaugeField &_Umu, GridCartesian &Fgrid, | ||||
|   StencilOdd.BuildSurfaceList(1,vol4); | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void WilsonFermion<Impl>::Report(void) | ||||
| { | ||||
|   RealD NP = _grid->_Nprocessors; | ||||
|   RealD NN = _grid->NodeCount(); | ||||
|   RealD volume = 1; | ||||
|   Coordinate latt = _grid->GlobalDimensions(); | ||||
|   for(int mu=0;mu<Nd;mu++) volume=volume*latt[mu]; | ||||
|  | ||||
|   if ( DhopCalls > 0 ) { | ||||
|     std::cout << GridLogMessage << "#### Dhop calls report " << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion Number of DhopEO Calls   : " << DhopCalls   << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion TotalTime   /Calls        : " << DhopTotalTime   / DhopCalls << " us" << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion CommTime    /Calls        : " << DhopCommTime    / DhopCalls << " us" << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion FaceTime    /Calls        : " << DhopFaceTime    / DhopCalls << " us" << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion ComputeTime1/Calls        : " << DhopComputeTime / DhopCalls << " us" << std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion ComputeTime2/Calls        : " << DhopComputeTime2/ DhopCalls << " us" << std::endl; | ||||
|  | ||||
|     // Average the compute time | ||||
|     _grid->GlobalSum(DhopComputeTime); | ||||
|     DhopComputeTime/=NP; | ||||
|     RealD mflops = 1320*volume*DhopCalls/DhopComputeTime/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call                : " << mflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per rank       : " << mflops/NP << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per node       : " << mflops/NN << std::endl; | ||||
|  | ||||
|     RealD Fullmflops = 1320*volume*DhopCalls/(DhopTotalTime)/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call (full)         : " << Fullmflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per rank (full): " << Fullmflops/NP << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per node (full): " << Fullmflops/NN << std::endl; | ||||
|  | ||||
|    } | ||||
|  | ||||
|   if ( DerivCalls > 0 ) { | ||||
|     std::cout << GridLogMessage << "#### Deriv calls report "<< std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion Number of Deriv Calls    : " <<DerivCalls <<std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion CommTime/Calls           : " <<DerivCommTime/DerivCalls<<" us" <<std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion ComputeTime/Calls        : " <<DerivComputeTime/DerivCalls<<" us" <<std::endl; | ||||
|     std::cout << GridLogMessage << "WilsonFermion Dhop ComputeTime/Calls   : " <<DerivDhopComputeTime/DerivCalls<<" us" <<std::endl; | ||||
|  | ||||
|     // how to count flops here? | ||||
|     RealD mflops = 144*volume*DerivCalls/DerivDhopComputeTime; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call               ? : " << mflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per node      ? : " << mflops/NP << std::endl; | ||||
|  | ||||
|     // how to count flops here? | ||||
|     RealD Fullmflops = 144*volume*DerivCalls/(DerivDhopComputeTime+DerivCommTime)/2; // 2 for red black counting | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call (full)        ? : " << Fullmflops << std::endl; | ||||
|     std::cout << GridLogMessage << "Average mflops/s per call per node (full) ? : " << Fullmflops/NP << std::endl;  } | ||||
|  | ||||
|   if (DerivCalls > 0 || DhopCalls > 0){ | ||||
|     std::cout << GridLogMessage << "WilsonFermion Stencil"    <<std::endl;  Stencil.Report(); | ||||
|     std::cout << GridLogMessage << "WilsonFermion StencilEven"<<std::endl;  StencilEven.Report(); | ||||
|     std::cout << GridLogMessage << "WilsonFermion StencilOdd" <<std::endl;  StencilOdd.Report(); | ||||
|   } | ||||
|   if ( DhopCalls > 0){ | ||||
|     std::cout << GridLogMessage << "WilsonFermion Stencil     Reporti()"    <<std::endl;  Stencil.Reporti(DhopCalls); | ||||
|     std::cout << GridLogMessage << "WilsonFermion StencilEven Reporti()"<<std::endl;  StencilEven.Reporti(DhopCalls); | ||||
|     std::cout << GridLogMessage << "WilsonFermion StencilOdd  Reporti()" <<std::endl;  StencilOdd.Reporti(DhopCalls); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<class Impl> | ||||
| void WilsonFermion<Impl>::ZeroCounters(void) { | ||||
|   DhopCalls       = 0; // ok | ||||
|   DhopCommTime    = 0; | ||||
|   DhopComputeTime = 0; | ||||
|   DhopComputeTime2= 0; | ||||
|   DhopFaceTime    = 0; | ||||
|   DhopTotalTime   = 0; | ||||
|  | ||||
|   DerivCalls       = 0; // ok | ||||
|   DerivCommTime    = 0; | ||||
|   DerivComputeTime = 0; | ||||
|   DerivDhopComputeTime = 0; | ||||
|  | ||||
|   Stencil.ZeroCounters(); | ||||
|   StencilEven.ZeroCounters(); | ||||
|   StencilOdd.ZeroCounters(); | ||||
|   Stencil.ZeroCountersi(); | ||||
|   StencilEven.ZeroCountersi(); | ||||
|   StencilOdd.ZeroCountersi(); | ||||
| } | ||||
|  | ||||
|  | ||||
| template <class Impl> | ||||
| void WilsonFermion<Impl>::ImportGauge(const GaugeField &_Umu) | ||||
| { | ||||
| @@ -238,6 +319,7 @@ template <class Impl> | ||||
| void WilsonFermion<Impl>::DerivInternal(StencilImpl &st, DoubledGaugeField &U, | ||||
|                                         GaugeField &mat, const FermionField &A, | ||||
|                                         const FermionField &B, int dag) { | ||||
|   DerivCalls++; | ||||
|   assert((dag == DaggerNo) || (dag == DaggerYes)); | ||||
|  | ||||
|   Compressor compressor(dag); | ||||
| @@ -246,8 +328,11 @@ void WilsonFermion<Impl>::DerivInternal(StencilImpl &st, DoubledGaugeField &U, | ||||
|   FermionField Atilde(B.Grid()); | ||||
|   Atilde = A; | ||||
|  | ||||
|   DerivCommTime-=usecond(); | ||||
|   st.HaloExchange(B, compressor); | ||||
|   DerivCommTime+=usecond(); | ||||
|  | ||||
|   DerivComputeTime-=usecond(); | ||||
|   for (int mu = 0; mu < Nd; mu++) { | ||||
|     //////////////////////////////////////////////////////////////////////// | ||||
|     // Flip gamma (1+g)<->(1-g) if dag | ||||
| @@ -255,6 +340,7 @@ void WilsonFermion<Impl>::DerivInternal(StencilImpl &st, DoubledGaugeField &U, | ||||
|     int gamma = mu; | ||||
|     if (!dag) gamma += Nd; | ||||
|  | ||||
|     DerivDhopComputeTime -= usecond(); | ||||
|     int Ls=1; | ||||
|     Kernels::DhopDirKernel(st, U, st.CommBuf(), Ls, B.Grid()->oSites(), B, Btilde, mu, gamma); | ||||
|  | ||||
| @@ -262,7 +348,9 @@ void WilsonFermion<Impl>::DerivInternal(StencilImpl &st, DoubledGaugeField &U, | ||||
|     // spin trace outer product | ||||
|     ////////////////////////////////////////////////// | ||||
|     Impl::InsertForce4D(mat, Btilde, Atilde, mu); | ||||
|     DerivDhopComputeTime += usecond(); | ||||
|   } | ||||
|   DerivComputeTime += usecond(); | ||||
| } | ||||
|  | ||||
| template <class Impl> | ||||
| @@ -309,6 +397,7 @@ void WilsonFermion<Impl>::DhopDerivEO(GaugeField &mat, const FermionField &U, co | ||||
| template <class Impl> | ||||
| void WilsonFermion<Impl>::Dhop(const FermionField &in, FermionField &out, int dag) | ||||
| { | ||||
|   DhopCalls+=2; | ||||
|   conformable(in.Grid(), _grid);  // verifies full grid | ||||
|   conformable(in.Grid(), out.Grid()); | ||||
|  | ||||
| @@ -320,6 +409,7 @@ void WilsonFermion<Impl>::Dhop(const FermionField &in, FermionField &out, int da | ||||
| template <class Impl> | ||||
| void WilsonFermion<Impl>::DhopOE(const FermionField &in, FermionField &out, int dag) | ||||
| { | ||||
|   DhopCalls++; | ||||
|   conformable(in.Grid(), _cbgrid);    // verifies half grid | ||||
|   conformable(in.Grid(), out.Grid());  // drops the cb check | ||||
|  | ||||
| @@ -332,6 +422,7 @@ void WilsonFermion<Impl>::DhopOE(const FermionField &in, FermionField &out, int | ||||
| template <class Impl> | ||||
| void WilsonFermion<Impl>::DhopEO(const FermionField &in, FermionField &out,int dag) | ||||
| { | ||||
|   DhopCalls++; | ||||
|   conformable(in.Grid(), _cbgrid);    // verifies half grid | ||||
|   conformable(in.Grid(), out.Grid());  // drops the cb check | ||||
|  | ||||
| @@ -396,12 +487,14 @@ void WilsonFermion<Impl>::DhopInternal(StencilImpl &st, LebesgueOrder &lo, | ||||
|                                        const FermionField &in, | ||||
|                                        FermionField &out, int dag) | ||||
| { | ||||
|   DhopTotalTime-=usecond(); | ||||
| #ifdef GRID_OMP | ||||
|   if ( WilsonKernelsStatic::Comms == WilsonKernelsStatic::CommsAndCompute ) | ||||
|     DhopInternalOverlappedComms(st,lo,U,in,out,dag); | ||||
|   else | ||||
| #endif | ||||
|     DhopInternalSerial(st,lo,U,in,out,dag); | ||||
|   DhopTotalTime+=usecond(); | ||||
| } | ||||
|  | ||||
| template <class Impl> | ||||
| @@ -410,7 +503,6 @@ void WilsonFermion<Impl>::DhopInternalOverlappedComms(StencilImpl &st, LebesgueO | ||||
| 						      const FermionField &in, | ||||
| 						      FermionField &out, int dag) | ||||
| { | ||||
|   GRID_TRACE("DhopOverlapped"); | ||||
|   assert((dag == DaggerNo) || (dag == DaggerYes)); | ||||
|  | ||||
|   Compressor compressor(dag); | ||||
| @@ -421,55 +513,53 @@ void WilsonFermion<Impl>::DhopInternalOverlappedComms(StencilImpl &st, LebesgueO | ||||
|   ///////////////////////////// | ||||
|   std::vector<std::vector<CommsRequest_t> > requests; | ||||
|   st.Prepare(); | ||||
|   { | ||||
|     GRID_TRACE("Gather"); | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.HaloGather(in,compressor); | ||||
|   } | ||||
|   DhopFaceTime+=usecond(); | ||||
|  | ||||
|   tracePush("Communication"); | ||||
|   DhopCommTime -=usecond(); | ||||
|   st.CommunicateBegin(requests); | ||||
|  | ||||
|   ///////////////////////////// | ||||
|   // Overlap with comms | ||||
|   ///////////////////////////// | ||||
|   { | ||||
|     GRID_TRACE("MergeSHM"); | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.CommsMergeSHM(compressor); | ||||
|   } | ||||
|   DhopFaceTime+=usecond(); | ||||
|  | ||||
|   ///////////////////////////// | ||||
|   // do the compute interior | ||||
|   ///////////////////////////// | ||||
|   int Opt = WilsonKernelsStatic::Opt; | ||||
|   DhopComputeTime-=usecond(); | ||||
|   if (dag == DaggerYes) { | ||||
|     GRID_TRACE("DhopDagInterior"); | ||||
|     Kernels::DhopDagKernel(Opt,st,U,st.CommBuf(),1,U.oSites(),in,out,1,0); | ||||
|   } else { | ||||
|     GRID_TRACE("DhopInterior"); | ||||
|     Kernels::DhopKernel(Opt,st,U,st.CommBuf(),1,U.oSites(),in,out,1,0); | ||||
|   } | ||||
|   DhopComputeTime+=usecond(); | ||||
|  | ||||
|   ///////////////////////////// | ||||
|   // Complete comms | ||||
|   ///////////////////////////// | ||||
|   st.CommunicateComplete(requests); | ||||
|   tracePop("Communication"); | ||||
|   DhopCommTime   +=usecond(); | ||||
|  | ||||
|   { | ||||
|     GRID_TRACE("Merge"); | ||||
|   DhopFaceTime-=usecond(); | ||||
|   st.CommsMerge(compressor); | ||||
|   } | ||||
|   DhopFaceTime+=usecond(); | ||||
|  | ||||
|   ///////////////////////////// | ||||
|   // do the compute exterior | ||||
|   ///////////////////////////// | ||||
|  | ||||
|   DhopComputeTime2-=usecond(); | ||||
|   if (dag == DaggerYes) { | ||||
|     GRID_TRACE("DhopDagExterior"); | ||||
|     Kernels::DhopDagKernel(Opt,st,U,st.CommBuf(),1,U.oSites(),in,out,0,1); | ||||
|   } else { | ||||
|     GRID_TRACE("DhopExterior"); | ||||
|     Kernels::DhopKernel(Opt,st,U,st.CommBuf(),1,U.oSites(),in,out,0,1); | ||||
|   } | ||||
|   DhopComputeTime2+=usecond(); | ||||
| }; | ||||
|  | ||||
|  | ||||
| @@ -479,22 +569,20 @@ void WilsonFermion<Impl>::DhopInternalSerial(StencilImpl &st, LebesgueOrder &lo, | ||||
|                                        const FermionField &in, | ||||
|                                        FermionField &out, int dag) | ||||
| { | ||||
|   GRID_TRACE("DhopSerial"); | ||||
|   assert((dag == DaggerNo) || (dag == DaggerYes)); | ||||
|   Compressor compressor(dag); | ||||
|   { | ||||
|     GRID_TRACE("HaloExchange"); | ||||
|   DhopCommTime-=usecond(); | ||||
|   st.HaloExchange(in, compressor); | ||||
|   } | ||||
|   DhopCommTime+=usecond(); | ||||
|  | ||||
|   DhopComputeTime-=usecond(); | ||||
|   int Opt = WilsonKernelsStatic::Opt; | ||||
|   if (dag == DaggerYes) { | ||||
|     GRID_TRACE("DhopDag"); | ||||
|     Kernels::DhopDagKernel(Opt,st,U,st.CommBuf(),1,U.oSites(),in,out); | ||||
|   } else { | ||||
|     GRID_TRACE("Dhop"); | ||||
|     Kernels::DhopKernel(Opt,st,U,st.CommBuf(),1,U.oSites(),in,out); | ||||
|   } | ||||
|   DhopComputeTime+=usecond(); | ||||
| }; | ||||
| /*Change ends */ | ||||
|  | ||||
| @@ -511,47 +599,11 @@ void WilsonFermion<Impl>::ContractConservedCurrent(PropagatorField &q_in_1, | ||||
|                                                    Current curr_type, | ||||
|                                                    unsigned int mu) | ||||
| { | ||||
|   if(curr_type != Current::Vector) | ||||
|   { | ||||
|     std::cout << GridLogError << "Only the conserved vector current is implemented so far." << std::endl; | ||||
|     exit(1); | ||||
|   } | ||||
|  | ||||
|   Gamma g5(Gamma::Algebra::Gamma5); | ||||
|   conformable(_grid, q_in_1.Grid()); | ||||
|   conformable(_grid, q_in_2.Grid()); | ||||
|   conformable(_grid, q_out.Grid()); | ||||
|   auto UGrid= this->GaugeGrid(); | ||||
|  | ||||
|   PropagatorField tmp_shifted(UGrid); | ||||
|   PropagatorField g5Lg5(UGrid); | ||||
|   PropagatorField R(UGrid); | ||||
|   PropagatorField gmuR(UGrid); | ||||
|  | ||||
|     Gamma::Algebra Gmu [] = { | ||||
|     Gamma::Algebra::GammaX, | ||||
|     Gamma::Algebra::GammaY, | ||||
|     Gamma::Algebra::GammaZ, | ||||
|     Gamma::Algebra::GammaT, | ||||
|   }; | ||||
|   Gamma gmu=Gamma(Gmu[mu]); | ||||
|  | ||||
|   g5Lg5=g5*q_in_1*g5; | ||||
|   tmp_shifted=Cshift(q_in_2,mu,1); | ||||
|   Impl::multLinkField(R,this->Umu,tmp_shifted,mu); | ||||
|   gmuR=gmu*R; | ||||
|  | ||||
|   q_out=adj(g5Lg5)*R; | ||||
|   q_out-=adj(g5Lg5)*gmuR; | ||||
|  | ||||
|   tmp_shifted=Cshift(q_in_1,mu,1); | ||||
|   Impl::multLinkField(g5Lg5,this->Umu,tmp_shifted,mu); | ||||
|   g5Lg5=g5*g5Lg5*g5; | ||||
|   R=q_in_2; | ||||
|   gmuR=gmu*R; | ||||
|  | ||||
|   q_out-=adj(g5Lg5)*R; | ||||
|   q_out-=adj(g5Lg5)*gmuR; | ||||
|   assert(0); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -565,51 +617,9 @@ void WilsonFermion<Impl>::SeqConservedCurrent(PropagatorField &q_in, | ||||
|                                               unsigned int tmax, | ||||
| 					      ComplexField &lattice_cmplx) | ||||
| { | ||||
|   if(curr_type != Current::Vector) | ||||
|   { | ||||
|     std::cout << GridLogError << "Only the conserved vector current is implemented so far." << std::endl; | ||||
|     exit(1); | ||||
|   } | ||||
|  | ||||
|   int tshift = (mu == Nd-1) ? 1 : 0; | ||||
|   unsigned int LLt    = GridDefaultLatt()[Tp]; | ||||
|   conformable(_grid, q_in.Grid()); | ||||
|   conformable(_grid, q_out.Grid()); | ||||
|   auto UGrid= this->GaugeGrid(); | ||||
|  | ||||
|   PropagatorField tmp(UGrid); | ||||
|   PropagatorField Utmp(UGrid); | ||||
|   PropagatorField L(UGrid); | ||||
|   PropagatorField zz (UGrid); | ||||
|   zz=Zero(); | ||||
|   LatticeInteger lcoor(UGrid); LatticeCoordinate(lcoor,Nd-1); | ||||
|  | ||||
|     Gamma::Algebra Gmu [] = { | ||||
|     Gamma::Algebra::GammaX, | ||||
|     Gamma::Algebra::GammaY, | ||||
|     Gamma::Algebra::GammaZ, | ||||
|     Gamma::Algebra::GammaT, | ||||
|   }; | ||||
|   Gamma gmu=Gamma(Gmu[mu]); | ||||
|  | ||||
|   tmp = Cshift(q_in,mu,1); | ||||
|   Impl::multLinkField(Utmp,this->Umu,tmp,mu); | ||||
|   tmp = ( Utmp*lattice_cmplx - gmu*Utmp*lattice_cmplx ); // Forward hop | ||||
|   tmp = where((lcoor>=tmin),tmp,zz); // Mask the time | ||||
|   q_out = where((lcoor<=tmax),tmp,zz); // Position of current complicated | ||||
|  | ||||
|   tmp = q_in *lattice_cmplx; | ||||
|   tmp = Cshift(tmp,mu,-1); | ||||
|   Impl::multLinkField(Utmp,this->Umu,tmp,mu+Nd); // Adjoint link | ||||
|   tmp = -( Utmp + gmu*Utmp ); | ||||
|   // Mask the time | ||||
|   if (tmax == LLt - 1 && tshift == 1){ // quick fix to include timeslice 0 if tmax + tshift is over the last timeslice | ||||
|     unsigned int t0 = 0; | ||||
|     tmp = where(((lcoor==t0) || (lcoor>=tmin+tshift)),tmp,zz); | ||||
|   } else { | ||||
|     tmp = where((lcoor>=tmin+tshift),tmp,zz); | ||||
|   } | ||||
|   q_out+= where((lcoor<=tmax+tshift),tmp,zz); // Position of current complicated | ||||
|   assert(0); | ||||
| } | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -73,6 +73,11 @@ accelerator_inline void get_stencil(StencilEntry * mem, StencilEntry &chip) | ||||
|     int perm= SE->_permute;					\ | ||||
|     auto tmp = coalescedReadPermute(in[SE->_offset],ptype,perm,lane);	\ | ||||
|     spProj(chi,tmp);						\ | ||||
|   } else if ( st.same_node[Dir] ) {				\ | ||||
|     chi = coalescedRead(buf[SE->_offset],lane);			\ | ||||
|   }								\ | ||||
|   acceleratorSynchronise();						\ | ||||
|   if (SE->_is_local || st.same_node[Dir] ) {			\ | ||||
|     Impl::multLink(Uchi, U[sU], chi, Dir, SE, st);		\ | ||||
|     Recon(result, Uchi);					\ | ||||
|   }								\ | ||||
| @@ -80,7 +85,7 @@ accelerator_inline void get_stencil(StencilEntry * mem, StencilEntry &chip) | ||||
|  | ||||
| #define GENERIC_STENCIL_LEG_EXT(Dir,spProj,Recon)		\ | ||||
|   SE = st.GetEntry(ptype, Dir, sF);				\ | ||||
|   if (!SE->_is_local ) {		\ | ||||
|   if ((!SE->_is_local) && (!st.same_node[Dir]) ) {		\ | ||||
|     auto chi = coalescedRead(buf[SE->_offset],lane);		\ | ||||
|     Impl::multLink(Uchi, U[sU], chi, Dir, SE, st);		\ | ||||
|     Recon(result, Uchi);					\ | ||||
| @@ -411,6 +416,19 @@ void WilsonKernels<Impl>::DhopDirKernel( StencilImpl &st, DoubledGaugeField &U,S | ||||
| #undef LoopBody | ||||
| } | ||||
|  | ||||
| #define KERNEL_CALL_TMP(A) \ | ||||
|   const uint64_t    NN = Nsite*Ls;					\ | ||||
|   auto U_p = & U_v[0];							\ | ||||
|   auto in_p = & in_v[0];						\ | ||||
|   auto out_p = & out_v[0];						\ | ||||
|   auto st_p = st_v._entries_p;						\ | ||||
|   auto st_perm = st_v._permute_type;					\ | ||||
|   accelerator_forNB( ss, NN, Simd::Nsimd(), {				\ | ||||
|       int sF = ss;							\ | ||||
|       int sU = ss/Ls;							\ | ||||
|       WilsonKernels<Impl>::A(st_perm,st_p,U_p,buf,sF,sU,in_p,out_p);	\ | ||||
|     });									\ | ||||
|   accelerator_barrier(); | ||||
|  | ||||
| #define KERNEL_CALLNB(A)						\ | ||||
|   const uint64_t    NN = Nsite*Ls;					\ | ||||
| @@ -422,34 +440,12 @@ void WilsonKernels<Impl>::DhopDirKernel( StencilImpl &st, DoubledGaugeField &U,S | ||||
|  | ||||
| #define KERNEL_CALL(A) KERNEL_CALLNB(A); accelerator_barrier(); | ||||
|  | ||||
| #define KERNEL_CALL_EXT(A)						\ | ||||
|   const uint64_t    NN = Nsite*Ls;					\ | ||||
|   const uint64_t    sz = st.surface_list.size();			\ | ||||
|   auto ptr = &st.surface_list[0];					\ | ||||
|   accelerator_forNB( ss, sz, Simd::Nsimd(), {				\ | ||||
|       int sF = ptr[ss];							\ | ||||
|       int sU = ss/Ls;							\ | ||||
|       WilsonKernels<Impl>::A(st_v,U_v,buf,sF,sU,in_v,out_v);		\ | ||||
|     });									 | ||||
|  | ||||
| #define ASM_CALL(A)							\ | ||||
|   thread_for( sss, Nsite, {						\ | ||||
|     int ss = st.lo->Reorder(sss);					\ | ||||
|   thread_for( ss, Nsite, {						\ | ||||
|     int sU = ss;							\ | ||||
|     int sF = ss*Ls;							\ | ||||
|     WilsonKernels<Impl>::A(st_v,U_v,buf,sF,sU,Ls,1,in_v,out_v);		\ | ||||
|   }); | ||||
| #define ASM_CALL_SLICE(A)						\ | ||||
|   auto grid = in.Grid() ;						\ | ||||
|   int nt = grid->LocalDimensions()[4];					\ | ||||
|   int nxyz = Nsite/nt ;							\ | ||||
|   for(int t=0;t<nt;t++){						\ | ||||
|   thread_for( sss, nxyz, {						\ | ||||
|     int ss = t*nxyz+sss;						\ | ||||
|     int sU = ss;							\ | ||||
|     int sF = ss*Ls;							\ | ||||
|     WilsonKernels<Impl>::A(st_v,U_v,buf,sF,sU,Ls,1,in_v,out_v);		\ | ||||
|     });} | ||||
|  | ||||
| template <class Impl> | ||||
| void WilsonKernels<Impl>::DhopKernel(int Opt,StencilImpl &st,  DoubledGaugeField &U, SiteHalfSpinor * buf, | ||||
| @@ -463,7 +459,11 @@ void WilsonKernels<Impl>::DhopKernel(int Opt,StencilImpl &st,  DoubledGaugeField | ||||
|  | ||||
|    if( interior && exterior ) { | ||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSite); return;} | ||||
| #ifdef SYCL_HACK      | ||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL_TMP(HandDhopSiteSycl);    return; } | ||||
| #else | ||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSite);    return;} | ||||
| #endif      | ||||
| #ifndef GRID_CUDA | ||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSite);    return;} | ||||
| #endif | ||||
| @@ -474,7 +474,6 @@ void WilsonKernels<Impl>::DhopKernel(int Opt,StencilImpl &st,  DoubledGaugeField | ||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteInt);    return;} | ||||
| #endif | ||||
|    } else if( exterior ) { | ||||
|      acceleratorFenceComputeStream(); | ||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSiteExt); return;} | ||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSiteExt);    return;} | ||||
| #ifndef GRID_CUDA | ||||
| @@ -500,13 +499,12 @@ void WilsonKernels<Impl>::DhopKernel(int Opt,StencilImpl &st,  DoubledGaugeField | ||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteDag);     return;} | ||||
| #endif | ||||
|    } else if( interior ) { | ||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALLNB(GenericDhopSiteDagInt); return;} | ||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALLNB(HandDhopSiteDagInt);    return;} | ||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSiteDagInt); return;} | ||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSiteDagInt);    return;} | ||||
| #ifndef GRID_CUDA | ||||
|      if (Opt == WilsonKernelsStatic::OptInlineAsm  ) {  ASM_CALL(AsmDhopSiteDagInt);     return;} | ||||
| #endif | ||||
|    } else if( exterior ) { | ||||
|      acceleratorFenceComputeStream(); | ||||
|      if (Opt == WilsonKernelsStatic::OptGeneric    ) { KERNEL_CALL(GenericDhopSiteDagExt); return;} | ||||
|      if (Opt == WilsonKernelsStatic::OptHandUnroll ) { KERNEL_CALL(HandDhopSiteDagExt);    return;} | ||||
| #ifndef GRID_CUDA | ||||
|   | ||||
| @@ -9,7 +9,6 @@ | ||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||
|     Author: Daniel Richtmann <daniel.richtmann@gmail.com> | ||||
|     Author: Mattia Bruno <mattia.bruno@cern.ch> | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
| @@ -33,12 +32,10 @@ | ||||
| #include <Grid/qcd/spin/Dirac.h> | ||||
| #include <Grid/qcd/action/fermion/CompactWilsonCloverFermion.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/CompactWilsonCloverFermionImplementation.h> | ||||
| #include <Grid/qcd/action/fermion/CloverHelpers.h> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class CompactWilsonCloverFermion<IMPLEMENTATION, CompactCloverHelpers<IMPLEMENTATION>>;  | ||||
| template class CompactWilsonCloverFermion<IMPLEMENTATION, CompactExpCloverHelpers<IMPLEMENTATION>>;  | ||||
| template class CompactWilsonCloverFermion<IMPLEMENTATION>;  | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| ../WilsonKernelsInstantiation.cc.master | ||||
| @@ -0,0 +1,51 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||
|  | ||||
| Copyright (C) 2015, 2020 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution | ||||
| directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||
|  | ||||
| #ifndef AVX512 | ||||
| #ifndef QPX | ||||
| #ifndef A64FX | ||||
| #ifndef A64FXFIXEDSIZE | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class WilsonKernels<IMPLEMENTATION>; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -1 +0,0 @@ | ||||
| ../WilsonKernelsInstantiation.cc.master | ||||
| @@ -0,0 +1,51 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||
|  | ||||
| Copyright (C) 2015, 2020 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution | ||||
| directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||
|  | ||||
| #ifndef AVX512 | ||||
| #ifndef QPX | ||||
| #ifndef A64FX | ||||
| #ifndef A64FXFIXEDSIZE | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class WilsonKernels<IMPLEMENTATION>; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -8,7 +8,6 @@ | ||||
|  | ||||
|     Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
|     Author: Guido Cossu <guido.cossu@ed.ac.uk> | ||||
|     Author: Mattia Bruno <mattia.bruno@cern.ch> | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
| @@ -32,12 +31,10 @@ | ||||
| #include <Grid/qcd/spin/Dirac.h> | ||||
| #include <Grid/qcd/action/fermion/WilsonCloverFermion.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonCloverFermionImplementation.h> | ||||
| #include <Grid/qcd/action/fermion/CloverHelpers.h> | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class WilsonCloverFermion<IMPLEMENTATION, CloverHelpers<IMPLEMENTATION>>;  | ||||
| template class WilsonCloverFermion<IMPLEMENTATION, ExpCloverHelpers<IMPLEMENTATION>>;  | ||||
| template class WilsonCloverFermion<IMPLEMENTATION>;  | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| ../WilsonKernelsInstantiation.cc.master | ||||
| @@ -0,0 +1,51 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||
|  | ||||
| Copyright (C) 2015, 2020 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution | ||||
| directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||
|  | ||||
| #ifndef AVX512 | ||||
| #ifndef QPX | ||||
| #ifndef A64FX | ||||
| #ifndef A64FXFIXEDSIZE | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class WilsonKernels<IMPLEMENTATION>; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -1 +0,0 @@ | ||||
| ../WilsonKernelsInstantiation.cc.master | ||||
| @@ -0,0 +1,51 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||
|  | ||||
| Copyright (C) 2015, 2020 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution | ||||
| directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||
|  | ||||
| #ifndef AVX512 | ||||
| #ifndef QPX | ||||
| #ifndef A64FX | ||||
| #ifndef A64FXFIXEDSIZE | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class WilsonKernels<IMPLEMENTATION>; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -1 +0,0 @@ | ||||
| ../WilsonKernelsInstantiation.cc.master | ||||
| @@ -0,0 +1,51 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||
|  | ||||
| Copyright (C) 2015, 2020 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution | ||||
| directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||
|  | ||||
| #ifndef AVX512 | ||||
| #ifndef QPX | ||||
| #ifndef A64FX | ||||
| #ifndef A64FXFIXEDSIZE | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class WilsonKernels<IMPLEMENTATION>; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
| @@ -1 +0,0 @@ | ||||
| ../WilsonKernelsInstantiation.cc.master | ||||
| @@ -0,0 +1,51 @@ | ||||
| /************************************************************************************* | ||||
|  | ||||
| Grid physics library, www.github.com/paboyle/Grid | ||||
|  | ||||
| Source file: ./lib/qcd/action/fermion/WilsonKernels.cc | ||||
|  | ||||
| Copyright (C) 2015, 2020 | ||||
|  | ||||
| Author: Peter Boyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Peter Boyle <peterboyle@Peters-MacBook-Pro-2.local> | ||||
| Author: paboyle <paboyle@ph.ed.ac.uk> | ||||
| Author: Nils Meyer <nils.meyer@ur.de> Regensburg University | ||||
|  | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU General Public License as published by | ||||
| the Free Software Foundation; either version 2 of the License, or | ||||
| (at your option) any later version. | ||||
|  | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
|  | ||||
| You should have received a copy of the GNU General Public License along | ||||
| with this program; if not, write to the Free Software Foundation, Inc., | ||||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  | ||||
| See the full license in the file "LICENSE" in the top level distribution | ||||
| directory | ||||
| *************************************************************************************/ | ||||
| /*  END LEGAL */ | ||||
| #include <Grid/qcd/action/fermion/FermionCore.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsImplementation.h> | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsHandImplementation.h> | ||||
|  | ||||
| #ifndef AVX512 | ||||
| #ifndef QPX | ||||
| #ifndef A64FX | ||||
| #ifndef A64FXFIXEDSIZE | ||||
| #include <Grid/qcd/action/fermion/implementation/WilsonKernelsAsmImplementation.h> | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| NAMESPACE_BEGIN(Grid); | ||||
|  | ||||
| #include "impl.h" | ||||
| template class WilsonKernels<IMPLEMENTATION>; | ||||
|  | ||||
| NAMESPACE_END(Grid); | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user