/************************************************************************************* Grid physics library, www.github.com/paboyle/Grid Source file: ./lib/cshift/Cshift_common.h Copyright (C) 2015 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 */ #ifndef _GRID_CSHIFT_COMMON_H_ #define _GRID_CSHIFT_COMMON_H_ NAMESPACE_BEGIN(Grid); /////////////////////////////////////////////////////////////////// // Gather for when there is no need to SIMD split /////////////////////////////////////////////////////////////////// template void Gather_plane_simple (const Lattice &rhs,commVector &buffer,int dimension,int plane,int cbmask, int off=0) { int rd = rhs._grid->_rdimensions[dimension]; if ( !rhs._grid->CheckerBoarded(dimension) ) { cbmask = 0x3; } int so=plane*rhs._grid->_ostride[dimension]; // base offset for start of plane int e1=rhs._grid->_slice_nblock[dimension]; int e2=rhs._grid->_slice_block[dimension]; int stride=rhs._grid->_slice_stride[dimension]; if ( cbmask == 0x3 ) { thread_loop_collapse( (int n=0;n > table; for(int n=0;nCheckerBoardFromOindex(o+b); if ( ocb &cbmask ) { table.push_back(std::pair (bo++,o+b)); } } } thread_loop( (int i=0;i void Gather_plane_extract(const Lattice &rhs,std::vector pointers,int dimension,int plane,int cbmask) { int rd = rhs._grid->_rdimensions[dimension]; if ( !rhs._grid->CheckerBoarded(dimension) ) { cbmask = 0x3; } int so = plane*rhs._grid->_ostride[dimension]; // base offset for start of plane int e1=rhs._grid->_slice_nblock[dimension]; int e2=rhs._grid->_slice_block[dimension]; int n1=rhs._grid->_slice_stride[dimension]; if ( cbmask ==0x3){ thread_loop_collapse( (int n=0;n(temp,pointers,offset); } }); } else { // Case of SIMD split AND checker dim cannot currently be hit, except in // Test_cshift_red_black code. std::cout << " Dense packed buffer WARNING " <CheckerBoardFromOindex(o+b); int offset = b+n*e2; if ( ocb & cbmask ) { vobj temp =rhs._odata[so+o+b]; extract(temp,pointers,offset); } } }); } } ////////////////////////////////////////////////////// // Scatter for when there is no need to SIMD split ////////////////////////////////////////////////////// template void Scatter_plane_simple (Lattice &rhs,commVector &buffer, int dimension,int plane,int cbmask) { int rd = rhs._grid->_rdimensions[dimension]; if ( !rhs._grid->CheckerBoarded(dimension) ) { cbmask=0x3; } int so = plane*rhs._grid->_ostride[dimension]; // base offset for start of plane int e1=rhs._grid->_slice_nblock[dimension]; int e2=rhs._grid->_slice_block[dimension]; int stride=rhs._grid->_slice_stride[dimension]; if ( cbmask ==0x3 ) { thread_loop_collapse( (int n=0;n_slice_stride[dimension]; int bo =n*rhs._grid->_slice_block[dimension]; rhs._odata[so+o+b]=buffer[bo+b]; } }); } else { std::vector > table; int bo=0; for(int n=0;n_slice_stride[dimension]; int ocb=1<CheckerBoardFromOindex(o+b);// Could easily be a table lookup if ( ocb & cbmask ) { table.push_back(std::pair (so+o+b,bo++)); } } } thread_loop( (int i=0;i void Scatter_plane_merge(Lattice &rhs,std::vector pointers,int dimension,int plane,int cbmask) { int rd = rhs._grid->_rdimensions[dimension]; if ( !rhs._grid->CheckerBoarded(dimension) ) { cbmask=0x3; } int so = plane*rhs._grid->_ostride[dimension]; // base offset for start of plane int e1=rhs._grid->_slice_nblock[dimension]; int e2=rhs._grid->_slice_block[dimension]; if(cbmask ==0x3 ) { thread_loop_collapse( (int n=0;n_slice_stride[dimension]; int offset = b+n*rhs._grid->_slice_block[dimension]; merge(rhs._odata[so+o+b],pointers,offset); } }); } else { // Case of SIMD split AND checker dim cannot currently be hit, except in // Test_cshift_red_black code. // std::cout << "Scatter_plane merge assert(0); think this is buggy FIXME "<< std::endl;// think this is buggy FIXME std::cout<<" Unthreaded warning -- buffer is not densely packed ??"<_slice_stride[dimension]; int offset = b+n*rhs._grid->_slice_block[dimension]; int ocb=1<CheckerBoardFromOindex(o+b); if ( ocb&cbmask ) { merge(rhs._odata[so+o+b],pointers,offset); } } } } } ////////////////////////////////////////////////////// // local to node block strided copies ////////////////////////////////////////////////////// template void Copy_plane(Lattice& lhs,const Lattice &rhs, int dimension,int lplane,int rplane,int cbmask) { int rd = rhs._grid->_rdimensions[dimension]; if ( !rhs._grid->CheckerBoarded(dimension) ) { cbmask=0x3; } int ro = rplane*rhs._grid->_ostride[dimension]; // base offset for start of plane int lo = lplane*lhs._grid->_ostride[dimension]; // base offset for start of plane int e1=rhs._grid->_slice_nblock[dimension]; // clearly loop invariant for icpc int e2=rhs._grid->_slice_block[dimension]; int stride = rhs._grid->_slice_stride[dimension]; if(cbmask == 0x3 ){ thread_loop_collapse( (int n=0;nCheckerBoardFromOindex(o); if ( ocb&cbmask ) { //lhs._odata[lo+o]=rhs._odata[ro+o]; vstream(lhs._odata[lo+o],rhs._odata[ro+o]); } } }); } } template void Copy_plane_permute(Lattice& lhs,const Lattice &rhs, int dimension,int lplane,int rplane,int cbmask,int permute_type) { int rd = rhs._grid->_rdimensions[dimension]; if ( !rhs._grid->CheckerBoarded(dimension) ) { cbmask=0x3; } int ro = rplane*rhs._grid->_ostride[dimension]; // base offset for start of plane int lo = lplane*lhs._grid->_ostride[dimension]; // base offset for start of plane int e1=rhs._grid->_slice_nblock[dimension]; int e2=rhs._grid->_slice_block [dimension]; int stride = rhs._grid->_slice_stride[dimension]; thread_loop_collapse( (int n=0;nCheckerBoardFromOindex(o+b); if ( ocb&cbmask ) { permute(lhs._odata[lo+o+b],rhs._odata[ro+o+b],permute_type); } } }); } ////////////////////////////////////////////////////// // Local to node Cshift ////////////////////////////////////////////////////// template void Cshift_local(Lattice& ret,const Lattice &rhs,int dimension,int shift) { int sshift[2]; sshift[0] = rhs._grid->CheckerBoardShiftForCB(rhs.checkerboard,dimension,shift,Even); sshift[1] = rhs._grid->CheckerBoardShiftForCB(rhs.checkerboard,dimension,shift,Odd); if ( sshift[0] == sshift[1] ) { Cshift_local(ret,rhs,dimension,shift,0x3); } else { Cshift_local(ret,rhs,dimension,shift,0x1);// if checkerboard is unfavourable take two passes Cshift_local(ret,rhs,dimension,shift,0x2);// both with block stride loop iteration } } template Lattice Cshift_local(Lattice &ret,const Lattice &rhs,int dimension,int shift,int cbmask) { GridBase *grid = rhs._grid; int fd = grid->_fdimensions[dimension]; int rd = grid->_rdimensions[dimension]; int ld = grid->_ldimensions[dimension]; int gd = grid->_gdimensions[dimension]; int ly = grid->_simd_layout[dimension]; // Map to always positive shift modulo global full dimension. shift = (shift+fd)%fd; // the permute type ret.checkerboard = grid->CheckerBoardDestination(rhs.checkerboard,shift,dimension); int permute_dim =grid->PermuteDim(dimension); int permute_type=grid->PermuteType(dimension); int permute_type_dist; for(int x=0;x_ostride[dimension]; int cb= (cbmask==0x2)? Odd : Even; int sshift = grid->CheckerBoardShiftForCB(rhs.checkerboard,dimension,shift,cb); int sx = (x+sshift)%rd; // FIXME : This must change where we have a // Rotate slice. // Document how this works ; why didn't I do this when I first wrote it... // wrap is whether sshift > rd. // num is sshift mod rd. // // shift 7 // // XoXo YcYc // oXoX cYcY // XoXo YcYc // oXoX cYcY // // sshift -- // // XX YY ; 3 // XX YY ; 0 // XX YY ; 3 // XX YY ; 0 // int permute_slice=0; if(permute_dim){ int wrap = sshift/rd; wrap=wrap % ly; int num = sshift%rd; if ( x< rd-num ) permute_slice=wrap; else permute_slice = (wrap+1)%ly; if ( (ly>2) && (permute_slice) ) { assert(permute_type & RotateBit); permute_type_dist = permute_type|permute_slice; } else { permute_type_dist = permute_type; } } if ( permute_slice ) Copy_plane_permute(ret,rhs,dimension,x,sx,cbmask,permute_type_dist); else Copy_plane(ret,rhs,dimension,x,sx,cbmask); } return ret; } NAMESPACE_END(Grid); #endif