1
0
mirror of https://github.com/paboyle/Grid.git synced 2025-06-16 14:57:05 +01:00

Adding reproducibility tests

This commit is contained in:
Guido Cossu
2016-11-21 09:52:07 +00:00
parent 036ec31c48
commit f1908c7bc9
2 changed files with 85 additions and 45 deletions

View File

@ -33,17 +33,21 @@ directory
namespace Grid { namespace Grid {
struct CG_state{ struct CG_state {
bool do_repro; bool do_repro;
std::vector<RealD> residuals; std::vector<RealD> residuals;
CG_state(){ CG_state() {
do_repro = false; do_repro = false;
residuals.clear();} residuals.clear();
}
void reset(){
do_repro = false;
residuals.clear();
}
}; };
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// Base classes for iterative processes based on operators // Base classes for iterative processes based on operators
// single input vec, single output vec. // single input vec, single output vec.
@ -57,7 +61,7 @@ class ConjugateGradient : public OperatorFunction<Field> {
RealD Tolerance; RealD Tolerance;
Integer MaxIterations; Integer MaxIterations;
bool ReproTest; bool ReproTest;
CG_state CGState; CG_state CGState;//to check reproducibility by repeating the CG
ConjugateGradient(RealD tol, Integer maxit, bool err_on_no_conv = true, ConjugateGradient(RealD tol, Integer maxit, bool err_on_no_conv = true,
bool ReproducibilityTest = false) bool ReproducibilityTest = false)
@ -199,8 +203,7 @@ class ConjugateGradient : public OperatorFunction<Field> {
} }
// Clear state // Clear state
CGState.residuals.clear(); CGState.reset();
CGState.do_repro = false;
return; return;
} }
} }

View File

@ -31,6 +31,25 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
#define GRID_LATTICE_REDUCTION_H #define GRID_LATTICE_REDUCTION_H
namespace Grid { namespace Grid {
template <class T>
struct ReproducibilityState {
int n_call;
bool do_check;
std::vector<std::vector<T, alignedAllocator<T> > > th_states;
void reset(){
th_states.clear();
do_check = false;
n_call = 0;
}
ReproducibilityState(){
reset();
}
};
#ifdef GRID_WARN_SUBOPTIMAL #ifdef GRID_WARN_SUBOPTIMAL
#warning "Optimisation alert all these reduction loops are NOT threaded " #warning "Optimisation alert all these reduction loops are NOT threaded "
#endif #endif
@ -39,9 +58,12 @@ namespace Grid {
// Deterministic Reduction operations // Deterministic Reduction operations
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
template<class vobj> inline RealD norm2(const Lattice<vobj> &arg){ template<class vobj> inline RealD norm2(const Lattice<vobj> &arg){
ComplexD nrm = innerProduct(arg,arg); ComplexD nrm = innerProduct(arg,arg);
return std::real(nrm); return std::real(nrm);
} }
template<class vobj> template<class vobj>
inline ComplexD innerProduct(const Lattice<vobj> &left,const Lattice<vobj> &right) inline ComplexD innerProduct(const Lattice<vobj> &left,const Lattice<vobj> &right)
@ -54,24 +76,39 @@ namespace Grid {
std::vector<vector_type,alignedAllocator<vector_type> > sumarray(grid->SumArraySize()); std::vector<vector_type,alignedAllocator<vector_type> > sumarray(grid->SumArraySize());
for(int i=0;i<grid->SumArraySize();i++){ for(int i=0;i<grid->SumArraySize();i++){
sumarray[i]=zero; sumarray[i]=zero;
} }
PARALLEL_FOR_LOOP // accumulation done in the same precision ad vobj...
// may need to froce higher precision
PARALLEL_FOR_LOOP
for(int thr=0;thr<grid->SumArraySize();thr++){ for(int thr=0;thr<grid->SumArraySize();thr++){
int nwork, mywork, myoff; int nwork, mywork, myoff;
GridThread::GetWork(left._grid->oSites(),thr,mywork,myoff); GridThread::GetWork(left._grid->oSites(),thr,mywork,myoff);
decltype(innerProduct(left._odata[0],right._odata[0])) vnrm=zero; // private to thread; sub summation decltype(innerProduct(left._odata[0],right._odata[0])) vnrm=zero; // private to thread; sub summation
for(int ss=myoff;ss<mywork+myoff; ss++){ for(int ss=myoff;ss<mywork+myoff; ss++){
vnrm = vnrm + innerProduct(left._odata[ss],right._odata[ss]); vnrm = vnrm + innerProduct(left._odata[ss],right._odata[ss]);
} }
sumarray[thr]=TensorRemove(vnrm) ; sumarray[thr]=TensorRemove(vnrm) ;
} }
/*
if (repr.do_check){
if (sumarray!=repr.th_states[n_call]){
std::cout << GridLogMessage << "Reproducibility failure on node " << grid->ThisRank() << std::endl;
exit(1);
}
}
} else {
repr.th_states.push_back(sumarray);//save threads state
repr.n_call +=1;
}
*/
vector_type vvnrm; vvnrm=zero; // sum across threads vector_type vvnrm; vvnrm=zero; // sum across threads
for(int i=0;i<grid->SumArraySize();i++){ for(int i=0;i<grid->SumArraySize();i++){
vvnrm = vvnrm+sumarray[i]; vvnrm = vvnrm+sumarray[i];
} }
nrm = Reduce(vvnrm);// sum across simd nrm = Reduce(vvnrm);// sum across simd
right._grid->GlobalSum(nrm); right._grid->GlobalSum(nrm);
@ -79,26 +116,26 @@ PARALLEL_FOR_LOOP
} }
template<class Op,class T1> template<class Op,class T1>
inline auto sum(const LatticeUnaryExpression<Op,T1> & expr) inline auto sum(const LatticeUnaryExpression<Op,T1> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second))))::scalar_object ->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second))))::scalar_object
{ {
return sum(closure(expr)); return sum(closure(expr));
} }
template<class Op,class T1,class T2> template<class Op,class T1,class T2>
inline auto sum(const LatticeBinaryExpression<Op,T1,T2> & expr) inline auto sum(const LatticeBinaryExpression<Op,T1,T2> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second)),eval(0,std::get<1>(expr.second))))::scalar_object ->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second)),eval(0,std::get<1>(expr.second))))::scalar_object
{ {
return sum(closure(expr)); return sum(closure(expr));
} }
template<class Op,class T1,class T2,class T3> template<class Op,class T1,class T2,class T3>
inline auto sum(const LatticeTrinaryExpression<Op,T1,T2,T3> & expr) inline auto sum(const LatticeTrinaryExpression<Op,T1,T2,T3> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second)), ->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second)),
eval(0,std::get<1>(expr.second)), eval(0,std::get<1>(expr.second)),
eval(0,std::get<2>(expr.second)) eval(0,std::get<2>(expr.second))
))::scalar_object ))::scalar_object
{ {
return sum(closure(expr)); return sum(closure(expr));
} }
@ -111,24 +148,24 @@ PARALLEL_FOR_LOOP
std::vector<vobj,alignedAllocator<vobj> > sumarray(grid->SumArraySize()); std::vector<vobj,alignedAllocator<vobj> > sumarray(grid->SumArraySize());
for(int i=0;i<grid->SumArraySize();i++){ for(int i=0;i<grid->SumArraySize();i++){
sumarray[i]=zero; sumarray[i]=zero;
} }
PARALLEL_FOR_LOOP PARALLEL_FOR_LOOP
for(int thr=0;thr<grid->SumArraySize();thr++){ for(int thr=0;thr<grid->SumArraySize();thr++){
int nwork, mywork, myoff; int nwork, mywork, myoff;
GridThread::GetWork(grid->oSites(),thr,mywork,myoff); GridThread::GetWork(grid->oSites(),thr,mywork,myoff);
vobj vvsum=zero; vobj vvsum=zero;
for(int ss=myoff;ss<mywork+myoff; ss++){ for(int ss=myoff;ss<mywork+myoff; ss++){
vvsum = vvsum + arg._odata[ss]; vvsum = vvsum + arg._odata[ss];
} }
sumarray[thr]=vvsum; sumarray[thr]=vvsum;
} }
vobj vsum=zero; // sum across threads vobj vsum=zero; // sum across threads
for(int i=0;i<grid->SumArraySize();i++){ for(int i=0;i<grid->SumArraySize();i++){
vsum = vsum+sumarray[i]; vsum = vsum+sumarray[i];
} }
typedef typename vobj::scalar_object sobj; typedef typename vobj::scalar_object sobj;
@ -138,7 +175,7 @@ PARALLEL_FOR_LOOP
extract(vsum,buf); extract(vsum,buf);
for(int i=0;i<Nsimd;i++) ssum = ssum + buf[i]; for(int i=0;i<Nsimd;i++) ssum = ssum + buf[i];
arg._grid->GlobalSum(ssum); arg._grid->GlobalSum(ssum);
return ssum; return ssum;
} }
@ -146,23 +183,23 @@ PARALLEL_FOR_LOOP
template<class vobj> inline void sliceSum(const Lattice<vobj> &Data,std::vector<typename vobj::scalar_object> &result,int orthogdim) template<class vobj> inline void sliceSum(const Lattice<vobj> &Data,std::vector<typename vobj::scalar_object> &result,int orthogdim)
{ {
typedef typename vobj::scalar_object sobj; typedef typename vobj::scalar_object sobj;
GridBase *grid = Data._grid; GridBase *grid = Data._grid;
assert(grid!=NULL); assert(grid!=NULL);
// FIXME // FIXME
// std::cout<<GridLogMessage<<"WARNING ! SliceSum is unthreaded "<<grid->SumArraySize()<<" threads "<<std::endl; // std::cout<<GridLogMessage<<"WARNING ! SliceSum is unthreaded "<<grid->SumArraySize()<<" threads "<<std::endl;
const int Nd = grid->_ndimension; const int Nd = grid->_ndimension;
const int Nsimd = grid->Nsimd(); const int Nsimd = grid->Nsimd();
assert(orthogdim >= 0); assert(orthogdim >= 0);
assert(orthogdim < Nd); assert(orthogdim < Nd);
int fd=grid->_fdimensions[orthogdim]; int fd=grid->_fdimensions[orthogdim];
int ld=grid->_ldimensions[orthogdim]; int ld=grid->_ldimensions[orthogdim];
int rd=grid->_rdimensions[orthogdim]; int rd=grid->_rdimensions[orthogdim];
std::vector<vobj,alignedAllocator<vobj> > lvSum(rd); // will locally sum vectors first std::vector<vobj,alignedAllocator<vobj> > lvSum(rd); // will locally sum vectors first
std::vector<sobj> lsSum(ld,zero); // sum across these down to scalars std::vector<sobj> lsSum(ld,zero); // sum across these down to scalars