From 07ee87ff5abcefd09ea07937909bcd26bde31296 Mon Sep 17 00:00:00 2001 From: Peter Boyle Date: Tue, 1 Jan 2019 15:00:33 +0000 Subject: [PATCH] GPU happy. Still need to prevent hand kernels being callable under NVCC --- .../qcd/action/fermion/FourierAcceleratedPV.h | 2 +- .../fermion/ImprovedStaggeredFermion.cc | 4 ++-- .../fermion/ImprovedStaggeredFermion5D.cc | 10 ++++---- Grid/qcd/action/fermion/StaggeredKernels.cc | 6 ++--- Grid/qcd/action/fermion/StaggeredKernels.h | 4 ++-- .../qcd/action/fermion/StaggeredKernelsAsm.cc | 8 +++---- .../action/fermion/StaggeredKernelsHand.cc | 4 ++-- .../qcd/action/fermion/WilsonCloverFermion.cc | 6 +++-- Grid/qcd/action/fermion/WilsonFermion5D.cc | 12 +++++----- Grid/qcd/action/fermion/WilsonKernels.h | 12 +++++----- .../qcd/action/fermion/WilsonKernelsAsmBody.h | 6 +++-- Grid/qcd/action/fermion/WilsonKernelsGpu.cc | 18 +++++++------- Grid/qcd/action/fermion/WilsonKernelsHand.cc | 24 +++++++++++++++++++ .../fermion/WilsonKernelsHandGparity.cc | 16 ++++++------- 14 files changed, 81 insertions(+), 51 deletions(-) diff --git a/Grid/qcd/action/fermion/FourierAcceleratedPV.h b/Grid/qcd/action/fermion/FourierAcceleratedPV.h index 36bb30f2..bf23ff75 100644 --- a/Grid/qcd/action/fermion/FourierAcceleratedPV.h +++ b/Grid/qcd/action/fermion/FourierAcceleratedPV.h @@ -163,7 +163,7 @@ class FourierAcceleratedPV { for (int sidx=0;sidx::DerivInternal(StencilImpl &st, DoubledGauge auto B_v = B.View(); auto Btilde_v = Btilde.View(); thread_loop( (int sss = 0; sss < B.Grid()->oSites(); sss++), { - Kernels::DhopDir(st, U_v, UUU_v, st.CommBuf(), sss, sss, B_v, Btilde_v, mu,1); + Kernels::DhopDirKernel(st, U_v, UUU_v, st.CommBuf(), sss, sss, B_v, Btilde_v, mu,1); }); // Force in three link terms @@ -380,7 +380,7 @@ void ImprovedStaggeredFermion::DhopDir(const FermionField &in, FermionFiel auto in_v = in.View(); auto out_v = out.View(); thread_loop( (int sss = 0; sss < in.Grid()->oSites(); sss++) , { - Kernels::DhopDir(Stencil, Umu_v, UUUmu_v, Stencil.CommBuf(), sss, sss, in_v, out_v, dir, disp); + Kernels::DhopDirKernel(Stencil, Umu_v, UUUmu_v, Stencil.CommBuf(), sss, sss, in_v, out_v, dir, disp); }); }; diff --git a/Grid/qcd/action/fermion/ImprovedStaggeredFermion5D.cc b/Grid/qcd/action/fermion/ImprovedStaggeredFermion5D.cc index 882f0e8f..63d44599 100644 --- a/Grid/qcd/action/fermion/ImprovedStaggeredFermion5D.cc +++ b/Grid/qcd/action/fermion/ImprovedStaggeredFermion5D.cc @@ -233,7 +233,7 @@ void ImprovedStaggeredFermion5D::DhopDir(const FermionField &in, FermionFi for(int s=0;s::DhopInternalSerialComms(StencilImpl & st, auto in_v = in.View(); auto out_v = out.View(); if (dag == DaggerYes) { - parallel_for (int ss = 0; ss < U.Grid()->oSites(); ss++) { + thread_loop( (int ss = 0; ss < U.Grid()->oSites(); ss++), { int sU=ss; Kernels::DhopSiteDag(st, lo, U_v, UUU_v, st.CommBuf(), LLs, sU,in_v, out_v); - } + }); } else { - parallel_for (int ss = 0; ss < U.Grid()->oSites(); ss++) { + thread_loop( (int ss = 0; ss < U.Grid()->oSites(); ss++) ,{ int sU=ss; Kernels::DhopSite(st,lo,U_v,UUU_v,st.CommBuf(),LLs,sU,in_v,out_v); - } + }); } DhopComputeTime += usecond(); DhopTotalTime += usecond(); diff --git a/Grid/qcd/action/fermion/StaggeredKernels.cc b/Grid/qcd/action/fermion/StaggeredKernels.cc index fa2cf155..01cf3bc5 100644 --- a/Grid/qcd/action/fermion/StaggeredKernels.cc +++ b/Grid/qcd/action/fermion/StaggeredKernels.cc @@ -170,7 +170,7 @@ void StaggeredKernels::DhopSiteGenericExt(StencilImpl &st, LebesgueOrder & SiteSpinor *buf, int LLs, int sU, const FermionFieldView &in, FermionFieldView &out,int dag) { const SiteSpinor *chi_p; - SiteSpinor chi; + // SiteSpinor chi; SiteSpinor Uchi; StencilEntry *SE; int ptype; @@ -276,8 +276,8 @@ void StaggeredKernels::DhopSite(StencilImpl &st, LebesgueOrder &lo, Double }; template -void StaggeredKernels::DhopDir( StencilImpl &st, DoubledGaugeFieldView &U, DoubledGaugeFieldView &UUU, SiteSpinor *buf, int sF, - int sU, const FermionFieldView &in, FermionFieldView &out, int dir, int disp) +void StaggeredKernels::DhopDirKernel( StencilImpl &st, DoubledGaugeFieldView &U, DoubledGaugeFieldView &UUU, SiteSpinor *buf, int sF, + int sU, const FermionFieldView &in, FermionFieldView &out, int dir, int disp) { // Disp should be either +1,-1,+3,-3 // What about "dag" ? diff --git a/Grid/qcd/action/fermion/StaggeredKernels.h b/Grid/qcd/action/fermion/StaggeredKernels.h index e833a093..6ef0ab9d 100644 --- a/Grid/qcd/action/fermion/StaggeredKernels.h +++ b/Grid/qcd/action/fermion/StaggeredKernels.h @@ -49,8 +49,8 @@ template class StaggeredKernels : public FermionOperator , pub public: - void DhopDir(StencilImpl &st, DoubledGaugeFieldView &U, DoubledGaugeFieldView &UUU, SiteSpinor * buf, - int sF, int sU, const FermionFieldView &in, FermionFieldView &out, int dir,int disp); + void DhopDirKernel(StencilImpl &st, DoubledGaugeFieldView &U, DoubledGaugeFieldView &UUU, SiteSpinor * buf, + int sF, int sU, const FermionFieldView &in, FermionFieldView &out, int dir,int disp); /////////////////////////////////////////////////////////////////////////////////////// // Generic Nc kernels diff --git a/Grid/qcd/action/fermion/StaggeredKernelsAsm.cc b/Grid/qcd/action/fermion/StaggeredKernelsAsm.cc index 3eafb610..bdccfb9a 100644 --- a/Grid/qcd/action/fermion/StaggeredKernelsAsm.cc +++ b/Grid/qcd/action/fermion/StaggeredKernelsAsm.cc @@ -963,10 +963,10 @@ template <> void StaggeredKernels::DhopSiteAsm(StencilImpl &st, SiteSpinor *buf, int LLs, \ int sU, const FermionFieldView &in, FermionFieldView &out,int dag); -KERNEL_INSTANTIATE(StaggeredKernels,DhopSiteAsm,StaggeredImplD); -KERNEL_INSTANTIATE(StaggeredKernels,DhopSiteAsm,StaggeredImplF); -KERNEL_INSTANTIATE(StaggeredKernels,DhopSiteAsm,StaggeredVec5dImplD); -KERNEL_INSTANTIATE(StaggeredKernels,DhopSiteAsm,StaggeredVec5dImplF); +//KERNEL_INSTANTIATE(StaggeredKernels,DhopSiteAsm,StaggeredImplD); +//KERNEL_INSTANTIATE(StaggeredKernels,DhopSiteAsm,StaggeredImplF); +//KERNEL_INSTANTIATE(StaggeredKernels,DhopSiteAsm,StaggeredVec5dImplD); +//KERNEL_INSTANTIATE(StaggeredKernels,DhopSiteAsm,StaggeredVec5dImplF); NAMESPACE_END(Grid); diff --git a/Grid/qcd/action/fermion/StaggeredKernelsHand.cc b/Grid/qcd/action/fermion/StaggeredKernelsHand.cc index eefd4d40..4af25d48 100644 --- a/Grid/qcd/action/fermion/StaggeredKernelsHand.cc +++ b/Grid/qcd/action/fermion/StaggeredKernelsHand.cc @@ -247,7 +247,7 @@ void StaggeredKernels::DhopSiteHandInt(StencilImpl &st, LebesgueOrder &lo, Simd U_22; SiteSpinor result; - int offset,local,perm, ptype; + int offset, ptype, local, perm; StencilEntry *SE; int skew; @@ -323,7 +323,7 @@ void StaggeredKernels::DhopSiteHandExt(StencilImpl &st, LebesgueOrder &lo, Simd U_22; SiteSpinor result; - int offset,local,perm, ptype; + int offset, ptype, local, perm; StencilEntry *SE; int skew; diff --git a/Grid/qcd/action/fermion/WilsonCloverFermion.cc b/Grid/qcd/action/fermion/WilsonCloverFermion.cc index d64185ba..aadb7af4 100644 --- a/Grid/qcd/action/fermion/WilsonCloverFermion.cc +++ b/Grid/qcd/action/fermion/WilsonCloverFermion.cc @@ -109,8 +109,10 @@ void WilsonCloverFermion::ImportGauge(const GaugeField &_Umu) 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++) - EigenCloverOp(a + j * DimRep, b + k * DimRep) = Qx()(j, k)(a, b); + for (int b = 0; b < DimRep; b++){ + auto zz = Qx()(j, k)(a, b); + EigenCloverOp(a + j * DimRep, b + k * DimRep) = std::complex(zz); + } // if (site==0) std::cout << "site =" << site << "\n" << EigenCloverOp << std::endl; EigenInvCloverOp = EigenCloverOp.inverse(); diff --git a/Grid/qcd/action/fermion/WilsonFermion5D.cc b/Grid/qcd/action/fermion/WilsonFermion5D.cc index 0447dae2..e5ad750f 100644 --- a/Grid/qcd/action/fermion/WilsonFermion5D.cc +++ b/Grid/qcd/action/fermion/WilsonFermion5D.cc @@ -104,8 +104,8 @@ WilsonFermion5D::WilsonFermion5D(GaugeField &_Umu, assert(FiveDimRedBlackGrid._simd_layout[0]==nsimd); for(int d=0;d<4;d++){ - assert(FourDimGrid._simd_layout[d]=1); - assert(FourDimRedBlackGrid._simd_layout[d]=1); + assert(FourDimGrid._simd_layout[d]==1); + assert(FourDimRedBlackGrid._simd_layout[d]==1); assert(FiveDimRedBlackGrid._simd_layout[d+1]==1); } @@ -528,14 +528,14 @@ void WilsonFermion5D::DhopInternalSerialComms(StencilImpl & st, LebesgueOr auto U_v = U.View(); int Opt = WilsonKernelsStatic::Opt; if (dag == DaggerYes) { - Kernels::DhopDag(Opt,st,U,st.CommBuf(),LLs,U_v.size(),in,out); + Kernels::DhopDagKernel(Opt,st,U,st.CommBuf(),LLs,U_v.size(),in,out); // parallel_for (int ss = 0; ss < U.Grid()->oSites(); ss++) { // int sU = ss; // int sF = LLs * sU; // Kernels::DhopSiteDag(st,lo,U,st.CommBuf(),sF,sU,LLs,1,in,out); // } } else { - Kernels::Dhop(Opt,st,U,st.CommBuf(),LLs,U_v.size(),in,out); + Kernels::DhopKernel(Opt,st,U,st.CommBuf(),LLs,U_v.size(),in,out); // parallel_for (int ss = 0; ss < U.Grid()->oSites(); ss++) { // int sU = ss; // int sF = LLs * sU; @@ -672,7 +672,7 @@ void WilsonFermion5D::MomentumSpacePropagatorHt_5d(FermionField &out,const for(int idx=0;idx<_grid->lSites();idx++){ Coordinate lcoor(Nd); Tcomplex cc; - RealD sgn; + // RealD sgn; _grid->LocalIndexToLocalCoor(idx,lcoor); peekLocalSite(cc,cosha,lcoor); assert((double)real(cc)>=1.0); @@ -867,7 +867,7 @@ void WilsonFermion5D::MomentumSpacePropagatorHt(FermionField &out,const Fe for(int idx=0;idx<_grid->lSites();idx++){ Coordinate lcoor(Nd); Tcomplex cc; - RealD sgn; + // RealD sgn; _grid->LocalIndexToLocalCoor(idx,lcoor); peekLocalSite(cc,cosha,lcoor); assert((double)real(cc)>=1.0); diff --git a/Grid/qcd/action/fermion/WilsonKernels.h b/Grid/qcd/action/fermion/WilsonKernels.h index c12b8c2f..10bee5c0 100644 --- a/Grid/qcd/action/fermion/WilsonKernels.h +++ b/Grid/qcd/action/fermion/WilsonKernels.h @@ -52,12 +52,12 @@ public: public: - static void Dhop(int Opt,StencilImpl &st, DoubledGaugeField &U, SiteHalfSpinor * buf, - int Ls, int Nsite, const FermionField &in, FermionField &out, - int interior=1,int exterior=1) ; - static void DhopDag(int Opt,StencilImpl &st, DoubledGaugeField &U, SiteHalfSpinor * buf, - int Ls, int Nsite, const FermionField &in, FermionField &out, - int interior=1,int exterior=1) ; + static void DhopKernel(int Opt,StencilImpl &st, DoubledGaugeField &U, SiteHalfSpinor * buf, + int Ls, int Nsite, const FermionField &in, FermionField &out, + int interior=1,int exterior=1) ; + static void DhopDagKernel(int Opt,StencilImpl &st, DoubledGaugeField &U, SiteHalfSpinor * buf, + int Ls, int Nsite, const FermionField &in, FermionField &out, + int interior=1,int exterior=1) ; template static accelerator typename std::enable_if::type diff --git a/Grid/qcd/action/fermion/WilsonKernelsAsmBody.h b/Grid/qcd/action/fermion/WilsonKernelsAsmBody.h index 0cecf42a..9f38bfc8 100644 --- a/Grid/qcd/action/fermion/WilsonKernelsAsmBody.h +++ b/Grid/qcd/action/fermion/WilsonKernelsAsmBody.h @@ -137,9 +137,11 @@ int nmax=U.oSites(); for(int site=0;site=nmax) ssn=0; - int sUn=lo.Reorder(ssn); + // int sUn=lo.Reorder(ssn); + int sUn=ssn; LOCK_GAUGE(0); #else int sU =ssU; diff --git a/Grid/qcd/action/fermion/WilsonKernelsGpu.cc b/Grid/qcd/action/fermion/WilsonKernelsGpu.cc index 5d849401..632138f1 100644 --- a/Grid/qcd/action/fermion/WilsonKernelsGpu.cc +++ b/Grid/qcd/action/fermion/WilsonKernelsGpu.cc @@ -303,9 +303,9 @@ GPU_EMPTY(GparityWilsonImplD); GPU_EMPTY(GparityWilsonImplDF); template -void WilsonKernels::Dhop(int Opt,StencilImpl &st, DoubledGaugeField &U, SiteHalfSpinor * buf, - int Ls, int Nsite, const FermionField &in, FermionField &out, - int interior,int exterior) +void WilsonKernels::DhopKernel(int Opt,StencilImpl &st, DoubledGaugeField &U, SiteHalfSpinor * buf, + int Ls, int Nsite, const FermionField &in, FermionField &out, + int interior,int exterior) { auto U_v = U.View(); auto in_v = in.View(); @@ -319,7 +319,8 @@ void WilsonKernels::Dhop(int Opt,StencilImpl &st, DoubledGaugeField &U, S // uint64_t lane = cur % nsimd; cur = cur / nsimd; uint64_t s = cur%Ls; - uint64_t sF = cur; cur = cur / Ls; + // uint64_t sF = cur; + cur = cur / Ls; uint64_t sU = cur; WilsonKernels::GpuDhopSite(st_v,U_v[sU],buf,Ls,s,sU,in_v,out_v); }); @@ -332,9 +333,9 @@ void WilsonKernels::Dhop(int Opt,StencilImpl &st, DoubledGaugeField &U, S } } template - void WilsonKernels::DhopDag(int Opt,StencilImpl &st, DoubledGaugeField &U, SiteHalfSpinor * buf, - int Ls, int Nsite, const FermionField &in, FermionField &out, - int interior,int exterior) + void WilsonKernels::DhopDagKernel(int Opt,StencilImpl &st, DoubledGaugeField &U, SiteHalfSpinor * buf, + int Ls, int Nsite, const FermionField &in, FermionField &out, + int interior,int exterior) { auto U_v = U.View(); auto in_v = in.View(); @@ -349,7 +350,8 @@ void WilsonKernels::Dhop(int Opt,StencilImpl &st, DoubledGaugeField &U, S // uint64_t lane = cur % nsimd; cur = cur / nsimd; uint64_t s = cur%Ls; - uint64_t sF = cur; cur = cur / Ls; + //uint64_t sF = cur; + cur = cur / Ls; uint64_t sU = cur; WilsonKernels::GpuDhopSiteDag(st_v,U_v,buf,Ls,s,sU,in_v,out_v); }); diff --git a/Grid/qcd/action/fermion/WilsonKernelsHand.cc b/Grid/qcd/action/fermion/WilsonKernelsHand.cc index 2046dc05..73fd3ae7 100644 --- a/Grid/qcd/action/fermion/WilsonKernelsHand.cc +++ b/Grid/qcd/action/fermion/WilsonKernelsHand.cc @@ -453,6 +453,7 @@ template void WilsonKernels::HandDhopSite(StencilView &st, DoubledGaugeFieldView &U,SiteHalfSpinor *buf, int ss,int sU,const FermionFieldView &in, FermionFieldView &out) { +#ifndef GRID_NVCC // T==0, Z==1, Y==2, Z==3 expect 1,2,2,2 simd layout etc... typedef typename Simd::scalar_type S; typedef typename Simd::vector_type V; @@ -471,12 +472,16 @@ WilsonKernels::HandDhopSite(StencilView &st, DoubledGaugeFieldView &U,Site HAND_STENCIL_LEG(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); HAND_STENCIL_LEG(TP_PROJ,0,Tm,TP_RECON_ACCUM); HAND_RESULT(ss); +#else + assert(0); +#endif } template void WilsonKernels::HandDhopSiteDag(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor *buf, int ss,int sU,const FermionFieldView &in, FermionFieldView &out) { +#ifndef GRID_NVCC typedef typename Simd::scalar_type S; typedef typename Simd::vector_type V; @@ -494,12 +499,16 @@ void WilsonKernels::HandDhopSiteDag(StencilView &st,DoubledGaugeFieldView HAND_STENCIL_LEG(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); HAND_STENCIL_LEG(TM_PROJ,0,Tm,TM_RECON_ACCUM); HAND_RESULT(ss); +#else + assert(0); +#endif } template void WilsonKernels::HandDhopSiteInt(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor *buf, int ss,int sU,const FermionFieldView &in, FermionFieldView &out) { +#ifndef GRID_NVCC // T==0, Z==1, Y==2, Z==3 expect 1,2,2,2 simd layout etc... typedef typename Simd::scalar_type S; typedef typename Simd::vector_type V; @@ -518,12 +527,16 @@ WilsonKernels::HandDhopSiteInt(StencilView &st,DoubledGaugeFieldView &U,Si HAND_STENCIL_LEG_INT(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); HAND_STENCIL_LEG_INT(TP_PROJ,0,Tm,TP_RECON_ACCUM); HAND_RESULT(ss); +#else + assert(0); +#endif } template void WilsonKernels::HandDhopSiteDagInt(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor *buf, int ss,int sU,const FermionFieldView &in, FermionFieldView &out) { +#ifndef GRID_NVCC typedef typename Simd::scalar_type S; typedef typename Simd::vector_type V; @@ -541,12 +554,16 @@ void WilsonKernels::HandDhopSiteDagInt(StencilView &st,DoubledGaugeFieldVi HAND_STENCIL_LEG_INT(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); HAND_STENCIL_LEG_INT(TM_PROJ,0,Tm,TM_RECON_ACCUM); HAND_RESULT(ss); +#else + assert(0); +#endif } template void WilsonKernels::HandDhopSiteExt(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor *buf, int ss,int sU,const FermionFieldView &in, FermionFieldView &out) { +#ifndef GRID_NVCC // T==0, Z==1, Y==2, Z==3 expect 1,2,2,2 simd layout etc... typedef typename Simd::scalar_type S; typedef typename Simd::vector_type V; @@ -566,12 +583,16 @@ WilsonKernels::HandDhopSiteExt(StencilView &st,DoubledGaugeFieldView &U,Si HAND_STENCIL_LEG_EXT(ZP_PROJ,1,Zm,ZP_RECON_ACCUM); HAND_STENCIL_LEG_EXT(TP_PROJ,0,Tm,TP_RECON_ACCUM); HAND_RESULT_EXT(ss); +#else + assert(0); +#endif } template void WilsonKernels::HandDhopSiteDagExt(StencilView &st,DoubledGaugeFieldView &U,SiteHalfSpinor *buf, int ss,int sU,const FermionFieldView &in, FermionFieldView &out) { +#ifndef GRID_NVCC typedef typename Simd::scalar_type S; typedef typename Simd::vector_type V; @@ -590,6 +611,9 @@ void WilsonKernels::HandDhopSiteDagExt(StencilView &st,DoubledGaugeFieldVi HAND_STENCIL_LEG_EXT(ZM_PROJ,1,Zm,ZM_RECON_ACCUM); HAND_STENCIL_LEG_EXT(TM_PROJ,0,Tm,TM_RECON_ACCUM); HAND_RESULT_EXT(ss); +#else + assert(0); +#endif } ////////////// Wilson ; uses this implementation ///////////////////// diff --git a/Grid/qcd/action/fermion/WilsonKernelsHandGparity.cc b/Grid/qcd/action/fermion/WilsonKernelsHandGparity.cc index 081fa79b..66d5218b 100644 --- a/Grid/qcd/action/fermion/WilsonKernelsHandGparity.cc +++ b/Grid/qcd/action/fermion/WilsonKernelsHandGparity.cc @@ -931,13 +931,13 @@ template void WilsonKernels::HandDhopSiteExt(StencilView &st, DoubledGaugeFie template void WilsonKernels::HandDhopSiteDagExt(StencilView &st, DoubledGaugeFieldView &U,SiteHalfSpinor *buf, \ int ss,int sU,const FermionFieldView &in, FermionFieldView &out); -INSTANTIATE_THEM(GparityWilsonImplF); -INSTANTIATE_THEM(GparityWilsonImplD); -INSTANTIATE_THEM(GparityWilsonImplFH); -INSTANTIATE_THEM(GparityWilsonImplDF); -INSTANTIATE_THEM(DomainWallVec5dImplFH); -INSTANTIATE_THEM(DomainWallVec5dImplDF); -INSTANTIATE_THEM(ZDomainWallVec5dImplFH); -INSTANTIATE_THEM(ZDomainWallVec5dImplDF); +//INSTANTIATE_THEM(GparityWilsonImplF); +//INSTANTIATE_THEM(GparityWilsonImplD); +//INSTANTIATE_THEM(GparityWilsonImplFH); +//INSTANTIATE_THEM(GparityWilsonImplDF); +//INSTANTIATE_THEM(DomainWallVec5dImplFH); +//INSTANTIATE_THEM(DomainWallVec5dImplDF); +//INSTANTIATE_THEM(ZDomainWallVec5dImplFH); +//INSTANTIATE_THEM(ZDomainWallVec5dImplDF); NAMESPACE_END(Grid);