/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/simd/Grid_gpu.h Copyright (C) 2021 Author: Peter Boyle 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 */ //---------------------------------------------------------------------- /*! @file Grid_gpu_rrii.h*/ //---------------------------------------------------------------------- ////////////////////////////// // fp16 ////////////////////////////// #ifdef GRID_CUDA #include #endif #ifdef GRID_HIP #include #endif #if !defined(GRID_HIP) && !defined(GRID_CUDA) namespace Grid { typedef struct { uint16_t x;} half; } #endif namespace Grid { accelerator_inline float half2float(half h) { float f; #if defined(GRID_CUDA) || defined(GRID_HIP) f = __half2float(h); #else Grid_half hh; hh.x = h.x; f= sfw_half_to_float(hh); #endif return f; } accelerator_inline half float2half(float f) { half h; #if defined(GRID_CUDA) || defined(GRID_HIP) h = __float2half(f); #else Grid_half hh = sfw_float_to_half(f); h.x = hh.x; #endif return h; } } #define COALESCE_GRANULARITY ( GEN_SIMD_WIDTH ) namespace Grid { //////////////////////////////////////////////////////////////////////// // Real vector //////////////////////////////////////////////////////////////////////// template struct GpuVector { _datum rrrr[_N]; static const int N = _N; typedef _datum datum; }; template inline accelerator GpuVector operator*(const GpuVector l,const GpuVector r) { GpuVector ret; for(int i=0;i inline accelerator GpuVector operator-(const GpuVector l,const GpuVector r) { GpuVector ret; for(int i=0;i inline accelerator GpuVector operator+(const GpuVector l,const GpuVector r) { GpuVector ret; for(int i=0;i inline accelerator GpuVector operator/(const GpuVector l,const GpuVector r) { GpuVector ret; for(int i=0;i struct GpuComplexVector { _datum rrrr[_N]; _datum iiii[_N]; static const int N = _N; typedef _datum datum; }; template inline accelerator GpuComplexVector operator*(const GpuComplexVector l,const GpuComplexVector r) { GpuComplexVector ret; for(int i=0;i inline accelerator GpuComplexVector operator-(const GpuComplexVector l,const GpuComplexVector r) { GpuComplexVector ret; for(int i=0;i inline accelerator GpuComplexVector operator+(const GpuComplexVector l,const GpuComplexVector r) { GpuComplexVector ret; for(int i=0;i inline accelerator GpuComplexVector operator/(const GpuComplexVector l,const GpuComplexVector r) { GpuComplexVector ret; for(int i=0;i GpuVectorRH; typedef GpuComplexVector GpuVectorCH; typedef GpuVector GpuVectorRF; typedef GpuComplexVector GpuVectorCF; typedef GpuVector GpuVectorRD; typedef GpuComplexVector GpuVectorCD; typedef GpuVector GpuVectorI; namespace Optimization { struct Vsplat{ //Complex float accelerator_inline GpuVectorCF operator()(float a, float b){ GpuVectorCF ret; for(int i=0;i accelerator_inline void operator()(GpuVector a, P* Fp){ GpuVector *vF = (GpuVector *)Fp; *vF = a; } template accelerator_inline void operator()(GpuComplexVector a, P* Fp){ GpuComplexVector *vF = (GpuComplexVector *)Fp; *vF = a; } }; struct Vstream{ template accelerator_inline void operator()(P* F,GpuVector a){ GpuVector *vF = (GpuVector *)F; *vF = a; } template accelerator_inline void operator()(P* F,GpuComplexVector a){ GpuComplexVector *vF = (GpuComplexVector *)F; *vF = a; } }; struct Vset{ // Complex float accelerator_inline GpuVectorCF operator()(Grid::ComplexF *a){ typedef GpuVectorCF vec; vec ret; for(int i=0;i struct Reduce{ //Need templated class to overload output type //General form must generate error if compiled accelerator_inline Out_type operator()(In_type in){ printf("Error, using wrong Reduce function\n"); exit(1); return 0; } }; ///////////////////////////////////////////////////// // Arithmetic operations ///////////////////////////////////////////////////// struct Sum{ //Real float accelerator_inline GpuVectorRF operator()(GpuVectorRF a,GpuVectorRF b){ return a+b; } accelerator_inline GpuVectorRD operator()(GpuVectorRD a,GpuVectorRD b){ return a+b; } accelerator_inline GpuVectorCF operator()(GpuVectorCF a,GpuVectorCF b){ return a+b; } accelerator_inline GpuVectorCD operator()(GpuVectorCD a,GpuVectorCD b){ return a+b; } accelerator_inline GpuVectorI operator()(GpuVectorI a,GpuVectorI b){ return a+b; } }; struct Sub{ accelerator_inline GpuVectorRF operator()(GpuVectorRF a,GpuVectorRF b){ return a-b; } accelerator_inline GpuVectorRD operator()(GpuVectorRD a,GpuVectorRD b){ return a-b; } accelerator_inline GpuVectorCF operator()(GpuVectorCF a,GpuVectorCF b){ return a-b; } accelerator_inline GpuVectorCD operator()(GpuVectorCD a,GpuVectorCD b){ return a-b; } accelerator_inline GpuVectorI operator()(GpuVectorI a,GpuVectorI b){ return a-b; } }; struct MultRealPart{ accelerator_inline GpuVectorCF operator()(GpuVectorCF a,GpuVectorCF b){ typedef GpuVectorCF vec; vec ret; for(int i=0;i static accelerator_inline GpuVector<_N,_datum> PermuteN(GpuVector<_N,_datum> &in) { typedef GpuVector<_N,_datum> vec; vec out; unsigned int _mask = vec::N >> (n + 1); for(int i=0;i static accelerator_inline GpuComplexVector<_N,_datum> PermuteN(GpuComplexVector<_N,_datum> &in) { typedef GpuComplexVector<_N,_datum> vec; vec out; unsigned int _mask = vec::N >> (n + 1); for(int i=0;i static accelerator_inline vec Permute0(vec in) { return PermuteN<0,vec::N,typename vec::datum>(in); } template static accelerator_inline vec Permute1(vec in) { return PermuteN<1,vec::N,typename vec::datum>(in); } template static accelerator_inline vec Permute2(vec in) { return PermuteN<2,vec::N,typename vec::datum>(in); } template static accelerator_inline vec Permute3(vec in) { return PermuteN<3,vec::N,typename vec::datum>(in); } }; struct PrecisionChange { //////////////////////////////////////////////////////////////////////////////////// // Single / Half //////////////////////////////////////////////////////////////////////////////////// static accelerator_inline GpuVectorCH StoH (GpuVectorCF a,GpuVectorCF b) { int N = GpuVectorCF::N; GpuVectorCH h; for(int i=0;i static accelerator_inline void ExchangeN(GpuVector<_N,_datum> &out1, GpuVector<_N,_datum> &out2, GpuVector<_N,_datum> &in1, GpuVector<_N,_datum> &in2 ) { typedef GpuVector<_N,_datum> vec; unsigned int mask = vec::N >> (n + 1); for(int i=0;i static accelerator_inline void ExchangeN(GpuComplexVector<_N,_datum> &out1, GpuComplexVector<_N,_datum> &out2, GpuComplexVector<_N,_datum> &in1, GpuComplexVector<_N,_datum> &in2 ) { typedef GpuComplexVector<_N,_datum> vec; unsigned int mask = vec::N >> (n + 1); for(int i=0;i static accelerator_inline void Exchange0(vec &out1,vec &out2,vec &in1,vec &in2){ ExchangeN<0>(out1,out2,in1,in2); }; template static accelerator_inline void Exchange1(vec &out1,vec &out2,vec &in1,vec &in2){ ExchangeN<1>(out1,out2,in1,in2); }; template static accelerator_inline void Exchange2(vec &out1,vec &out2,vec &in1,vec &in2){ ExchangeN<2>(out1,out2,in1,in2); }; template static accelerator_inline void Exchange3(vec &out1,vec &out2,vec &in1,vec &in2){ ExchangeN<3>(out1,out2,in1,in2); }; }; struct Rotate{ template static accelerator_inline vec tRotate(vec in){ return rotate(in, n); } template static accelerator_inline GpuComplexVector<_N,_datum> rotate_template(GpuComplexVector<_N,_datum> &in, int n) { typedef GpuComplexVector<_N,_datum> vec; vec out; for(int i=0;i static accelerator_inline GpuVector<_N,_datum> rotate_template(GpuVector<_N,_datum> &in, int n) { typedef GpuVector<_N,_datum> vec; vec out; for(int i=0;i accelerator_inline Grid::ComplexF Reduce::operator()(GpuVectorCF in) { Grid::ComplexF greduce(in.rrrr[0],in.iiii[0]); for(int i=1;i accelerator_inline Grid::ComplexD Reduce::operator()(GpuVectorCD in) { Grid::ComplexD greduce(in.rrrr[0],in.iiii[0]); for(int i=1;i accelerator_inline Grid::RealF Reduce::operator()(GpuVectorRF in) { RealF ret = in.rrrr[0]; for(int i=1;i accelerator_inline Grid::RealD Reduce::operator()(GpuVectorRD in) { RealD ret = in.rrrr[0]; for(int i=1;i accelerator_inline Integer Reduce::operator()(GpuVectorI in) { Integer ret = in.rrrr[0]; for(int i=1;i using ReduceSIMD = Optimization::Reduce; // Arithmetic operations typedef Optimization::Sum SumSIMD; typedef Optimization::Sub SubSIMD; typedef Optimization::Div DivSIMD; typedef Optimization::Mult MultSIMD; typedef Optimization::MultComplex MultComplexSIMD; typedef Optimization::MultRealPart MultRealPartSIMD; typedef Optimization::MaddRealPart MaddRealPartSIMD; typedef Optimization::Conj ConjSIMD; typedef Optimization::TimesMinusI TimesMinusISIMD; typedef Optimization::TimesI TimesISIMD; }