mirror of
https://github.com/paboyle/Grid.git
synced 2024-11-10 07:55:35 +00:00
Better reduction for GPUs
This commit is contained in:
parent
fe9edf8526
commit
0b905a72dd
@ -23,7 +23,7 @@ unsigned int nextPow2(Iterator x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Iterator>
|
template <class Iterator>
|
||||||
void getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator &threads, Iterator &blocks) {
|
int getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator &threads, Iterator &blocks) {
|
||||||
|
|
||||||
int device;
|
int device;
|
||||||
#ifdef GRID_CUDA
|
#ifdef GRID_CUDA
|
||||||
@ -37,13 +37,13 @@ void getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator
|
|||||||
Iterator sharedMemPerBlock = gpu_props[device].sharedMemPerBlock;
|
Iterator sharedMemPerBlock = gpu_props[device].sharedMemPerBlock;
|
||||||
Iterator maxThreadsPerBlock = gpu_props[device].maxThreadsPerBlock;
|
Iterator maxThreadsPerBlock = gpu_props[device].maxThreadsPerBlock;
|
||||||
Iterator multiProcessorCount = gpu_props[device].multiProcessorCount;
|
Iterator multiProcessorCount = gpu_props[device].multiProcessorCount;
|
||||||
|
/*
|
||||||
std::cout << GridLogDebug << "GPU has:" << std::endl;
|
std::cout << GridLogDebug << "GPU has:" << std::endl;
|
||||||
std::cout << GridLogDebug << "\twarpSize = " << warpSize << std::endl;
|
std::cout << GridLogDebug << "\twarpSize = " << warpSize << std::endl;
|
||||||
std::cout << GridLogDebug << "\tsharedMemPerBlock = " << sharedMemPerBlock << std::endl;
|
std::cout << GridLogDebug << "\tsharedMemPerBlock = " << sharedMemPerBlock << std::endl;
|
||||||
std::cout << GridLogDebug << "\tmaxThreadsPerBlock = " << maxThreadsPerBlock << std::endl;
|
std::cout << GridLogDebug << "\tmaxThreadsPerBlock = " << maxThreadsPerBlock << std::endl;
|
||||||
std::cout << GridLogDebug << "\tmultiProcessorCount = " << multiProcessorCount << std::endl;
|
std::cout << GridLogDebug << "\tmultiProcessorCount = " << multiProcessorCount << std::endl;
|
||||||
|
*/
|
||||||
if (warpSize != WARP_SIZE) {
|
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;
|
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);
|
exit(EXIT_FAILURE);
|
||||||
@ -53,12 +53,12 @@ void getNumBlocksAndThreads(const Iterator n, const size_t sizeofsobj, Iterator
|
|||||||
threads = warpSize;
|
threads = warpSize;
|
||||||
if ( threads*sizeofsobj > sharedMemPerBlock ) {
|
if ( threads*sizeofsobj > sharedMemPerBlock ) {
|
||||||
std::cout << GridLogError << "The object is too large for the shared memory." << std::endl;
|
std::cout << GridLogError << "The object is too large for the shared memory." << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
return 0;
|
||||||
}
|
}
|
||||||
while( 2*threads*sizeofsobj < sharedMemPerBlock && 2*threads <= maxThreadsPerBlock ) threads *= 2;
|
while( 2*threads*sizeofsobj < sharedMemPerBlock && 2*threads <= maxThreadsPerBlock ) threads *= 2;
|
||||||
// keep all the streaming multiprocessors busy
|
// keep all the streaming multiprocessors busy
|
||||||
blocks = nextPow2(multiProcessorCount);
|
blocks = nextPow2(multiProcessorCount);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class sobj, class Iterator>
|
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
|
// Possibly promote to double and sum
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
template <class vobj>
|
template <class vobj>
|
||||||
inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites)
|
inline typename vobj::scalar_objectD sumD_gpu_internal(const vobj *lat, Integer osites)
|
||||||
{
|
{
|
||||||
typedef typename vobj::scalar_objectD sobj;
|
typedef typename vobj::scalar_objectD sobj;
|
||||||
typedef decltype(lat) Iterator;
|
typedef decltype(lat) Iterator;
|
||||||
@ -208,6 +208,7 @@ inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites)
|
|||||||
|
|
||||||
Integer numThreads, numBlocks;
|
Integer numThreads, numBlocks;
|
||||||
getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks);
|
getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks);
|
||||||
|
|
||||||
Integer smemSize = numThreads * sizeof(sobj);
|
Integer smemSize = numThreads * sizeof(sobj);
|
||||||
|
|
||||||
Vector<sobj> buffer(numBlocks);
|
Vector<sobj> buffer(numBlocks);
|
||||||
@ -218,6 +219,41 @@ inline typename vobj::scalar_objectD sumD_gpu(const vobj *lat, Integer osites)
|
|||||||
auto result = buffer_v[0];
|
auto result = buffer_v[0];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
template <class vobj>
|
||||||
|
inline typename vobj::scalar_objectD sumD_gpu(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);
|
||||||
|
|
||||||
|
Integer nsimd= vobj::Nsimd();
|
||||||
|
Integer size = osites*nsimd;
|
||||||
|
Integer numThreads, numBlocks;
|
||||||
|
int ok = getNumBlocksAndThreads(size, sizeof(sobj), numThreads, numBlocks);
|
||||||
|
|
||||||
|
if ( ok ) {
|
||||||
|
ret = sumD_gpu_internal(lat,osites);
|
||||||
|
} else {
|
||||||
|
std::cout << GridLogWarning << " dropping to summing word by word for large object size "<<sizeof(vobj)<<std::endl;
|
||||||
|
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_internal(tbuf,osites);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Return as same precision as input performing reduction in double precision though
|
// Return as same precision as input performing reduction in double precision though
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user