GPGPU Programming in Haskell with Accelerate
Trevor L. McDonell University of New South Wales
@tlmcdonell tmcdonell@cse.unsw.edu.au https://github.com/AccelerateHS
Friday, 17 May 13
GPGPU Programming in Haskell with Accelerate Trevor L. McDonell - - PowerPoint PPT Presentation
GPGPU Programming in Haskell with Accelerate Trevor L. McDonell University of New South Wales @tlmcdonell tmcdonell@cse.unsw.edu.au https://github.com/AccelerateHS Friday, 17 May 13 What is GPGPU Programming? General Purpose Programming
@tlmcdonell tmcdonell@cse.unsw.edu.au https://github.com/AccelerateHS
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
struct ¡SharedMemory { ¡ ¡ ¡ ¡__device__ ¡inline ¡operator ¡float ¡*() ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡extern ¡__shared__ ¡int ¡__smem[]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡return ¡(float ¡*)__smem; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡__device__ ¡inline ¡operator ¡const ¡float ¡*() ¡const ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡extern ¡__shared__ ¡int ¡__smem[]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡return ¡(float ¡*)__smem; ¡ ¡ ¡ ¡} }; template ¡<unsigned ¡int ¡blockSize, ¡bool ¡nIsPow2> __global__ ¡void reduce_kernel(float ¡*g_idata, ¡float ¡*g_odata, ¡unsigned ¡int ¡n) { ¡ ¡ ¡ ¡float ¡*sdata ¡= ¡SharedMemory(); ¡ ¡ ¡ ¡unsigned ¡int ¡tid ¡ ¡ ¡ ¡ ¡ ¡= ¡threadIdx.x; ¡ ¡ ¡ ¡unsigned ¡int ¡i ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡= ¡blockIdx.x*blockSize*2 ¡+ ¡threadIdx.x; ¡ ¡ ¡ ¡unsigned ¡int ¡gridSize ¡= ¡blockSize*2*gridDim.x; ¡ ¡ ¡ ¡float ¡sum ¡= ¡0; ¡ ¡ ¡ ¡while ¡(i ¡< ¡n) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sum ¡+= ¡g_idata[i]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(nIsPow2 ¡|| ¡i ¡+ ¡blockSize ¡< ¡n) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sum ¡+= ¡g_idata[i+blockSize]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡i ¡+= ¡gridSize; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum; ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡512) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡256) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡256]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡256) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡128) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡128]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡128) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡ ¡64) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡ ¡64]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(tid ¡< ¡32) ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡volatile ¡float ¡*smem ¡= ¡sdata; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡64) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡32]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡32) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡16]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡16) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡8]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡8) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡4]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡4) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡2]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡2) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡1]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(tid ¡== ¡0) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡g_odata[blockIdx.x] ¡= ¡sdata[0]; } void ¡getNumBlocksAndThreads(int ¡n, ¡int ¡maxBlocks, ¡int ¡maxThreads, ¡int ¡&blocks, ¡int ¡&threads) { ¡ ¡ ¡ ¡cudaDeviceProp ¡prop; ¡ ¡ ¡ ¡int ¡device; ¡ ¡ ¡ ¡checkCudaErrors(cudaGetDevice(&device)); ¡ ¡ ¡ ¡checkCudaErrors(cudaGetDeviceProperties(&prop, ¡device)); ¡ ¡ ¡ ¡threads ¡= ¡(n ¡< ¡maxThreads*2) ¡? ¡nextPow2((n ¡+ ¡1)/ ¡2) ¡: ¡maxThreads; ¡ ¡ ¡ ¡blocks ¡ ¡= ¡(n ¡+ ¡(threads ¡* ¡2 ¡-‑ ¡1)) ¡/ ¡(threads ¡* ¡2); ¡ ¡ ¡ ¡if ¡(blocks ¡> ¡prop.maxGridSize[0]) ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡blocks ¡ ¡/= ¡2; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡threads ¡*= ¡2; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡blocks ¡= ¡min(maxBlocks, ¡blocks); } float reduce(int ¡n, ¡float ¡*d_idata, ¡float ¡*d_odata) { ¡ ¡ ¡ ¡int ¡threads ¡ ¡ ¡ ¡= ¡0; ¡ ¡ ¡ ¡int ¡blocks ¡ ¡ ¡ ¡ ¡= ¡0; ¡ ¡ ¡ ¡int ¡maxThreads ¡= ¡256; ¡ ¡ ¡ ¡int ¡maxBlocks ¡ ¡= ¡64; ¡ ¡ ¡ ¡int ¡size ¡ ¡ ¡ ¡ ¡ ¡ ¡= ¡n ¡ ¡ ¡ ¡while ¡(size ¡> ¡1) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡getNumBlocksAndThreads(size, ¡maxBlocks, ¡maxThreads, ¡blocks, ¡threads); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡int ¡smemSize ¡= ¡(threads ¡<= ¡32) ¡? ¡2 ¡* ¡threads ¡* ¡sizeof(float) ¡: ¡threads ¡* ¡sizeof(float); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡dim3 ¡dimBlock(threads, ¡1, ¡1); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡dim3 ¡dimGrid(blocks, ¡1, ¡1); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(isPow2(size)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡switch ¡(threads) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡512: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<512, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡256: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<256, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡128: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<128, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡64: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡64, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡32: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡32, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡16: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡16, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡8: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡8, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡4: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡4, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡2: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡2, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡1: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡1, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡else ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡switch ¡(threads) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡512: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<512, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡256: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<256, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡128: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<128, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡64: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡64, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡32: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡32, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡16: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡16, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡8: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡8, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡4: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡4, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡2: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡2, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡1: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡1, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡size ¡= ¡(size ¡+ ¡(threads*2-‑1)) ¡/ ¡(threads*2); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡float ¡sum; ¡ ¡ ¡ ¡checkCudaErrors(cudaMemcpy(&sum, ¡d_odata, ¡sizeof(float), ¡cudaMemcpyDeviceToHost)); }
Friday, 17 May 13
struct ¡SharedMemory { ¡ ¡ ¡ ¡__device__ ¡inline ¡operator ¡float ¡*() ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡extern ¡__shared__ ¡int ¡__smem[]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡return ¡(float ¡*)__smem; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡__device__ ¡inline ¡operator ¡const ¡float ¡*() ¡const ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡extern ¡__shared__ ¡int ¡__smem[]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡return ¡(float ¡*)__smem; ¡ ¡ ¡ ¡} }; template ¡<unsigned ¡int ¡blockSize, ¡bool ¡nIsPow2> __global__ ¡void reduce_kernel(float ¡*g_idata, ¡float ¡*g_odata, ¡unsigned ¡int ¡n) { ¡ ¡ ¡ ¡float ¡*sdata ¡= ¡SharedMemory(); ¡ ¡ ¡ ¡unsigned ¡int ¡tid ¡ ¡ ¡ ¡ ¡ ¡= ¡threadIdx.x; ¡ ¡ ¡ ¡unsigned ¡int ¡i ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡= ¡blockIdx.x*blockSize*2 ¡+ ¡threadIdx.x; ¡ ¡ ¡ ¡unsigned ¡int ¡gridSize ¡= ¡blockSize*2*gridDim.x; ¡ ¡ ¡ ¡float ¡sum ¡= ¡0; ¡ ¡ ¡ ¡while ¡(i ¡< ¡n) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sum ¡+= ¡g_idata[i]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(nIsPow2 ¡|| ¡i ¡+ ¡blockSize ¡< ¡n) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sum ¡+= ¡g_idata[i+blockSize]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡i ¡+= ¡gridSize; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum; ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡512) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡256) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡256]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡256) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡128) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡128]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡128) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡ ¡64) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡ ¡64]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(tid ¡< ¡32) ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡volatile ¡float ¡*smem ¡= ¡sdata; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡64) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡32]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡32) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡16]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡16) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡8]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡8) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡4]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡4) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡2]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡2) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡1]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(tid ¡== ¡0) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡g_odata[blockIdx.x] ¡= ¡sdata[0]; } void ¡getNumBlocksAndThreads(int ¡n, ¡int ¡maxBlocks, ¡int ¡maxThreads, ¡int ¡&blocks, ¡int ¡&threads) { ¡ ¡ ¡ ¡cudaDeviceProp ¡prop; ¡ ¡ ¡ ¡int ¡device; ¡ ¡ ¡ ¡checkCudaErrors(cudaGetDevice(&device)); ¡ ¡ ¡ ¡checkCudaErrors(cudaGetDeviceProperties(&prop, ¡device)); ¡ ¡ ¡ ¡threads ¡= ¡(n ¡< ¡maxThreads*2) ¡? ¡nextPow2((n ¡+ ¡1)/ ¡2) ¡: ¡maxThreads; ¡ ¡ ¡ ¡blocks ¡ ¡= ¡(n ¡+ ¡(threads ¡* ¡2 ¡-‑ ¡1)) ¡/ ¡(threads ¡* ¡2); ¡ ¡ ¡ ¡if ¡(blocks ¡> ¡prop.maxGridSize[0]) ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡blocks ¡ ¡/= ¡2; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡threads ¡*= ¡2; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡blocks ¡= ¡min(maxBlocks, ¡blocks); } float reduce(int ¡n, ¡float ¡*d_idata, ¡float ¡*d_odata) { ¡ ¡ ¡ ¡int ¡threads ¡ ¡ ¡ ¡= ¡0; ¡ ¡ ¡ ¡int ¡blocks ¡ ¡ ¡ ¡ ¡= ¡0; ¡ ¡ ¡ ¡int ¡maxThreads ¡= ¡256; ¡ ¡ ¡ ¡int ¡maxBlocks ¡ ¡= ¡64; ¡ ¡ ¡ ¡int ¡size ¡ ¡ ¡ ¡ ¡ ¡ ¡= ¡n ¡ ¡ ¡ ¡while ¡(size ¡> ¡1) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡getNumBlocksAndThreads(size, ¡maxBlocks, ¡maxThreads, ¡blocks, ¡threads); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡int ¡smemSize ¡= ¡(threads ¡<= ¡32) ¡? ¡2 ¡* ¡threads ¡* ¡sizeof(float) ¡: ¡threads ¡* ¡sizeof(float); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡dim3 ¡dimBlock(threads, ¡1, ¡1); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡dim3 ¡dimGrid(blocks, ¡1, ¡1); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(isPow2(size)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡switch ¡(threads) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡512: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<512, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡256: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<256, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡128: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<128, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡64: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡64, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡32: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡32, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡16: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡16, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡8: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡8, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡4: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡4, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡2: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡2, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡1: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡1, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡else ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡switch ¡(threads) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡512: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<512, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡256: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<256, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡128: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<128, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡64: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡64, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡32: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡32, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡16: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡16, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡8: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡8, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡4: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡4, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡2: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡2, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡1: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡1, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡size ¡= ¡(size ¡+ ¡(threads*2-‑1)) ¡/ ¡(threads*2); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡float ¡sum; ¡ ¡ ¡ ¡checkCudaErrors(cudaMemcpy(&sum, ¡d_odata, ¡sizeof(float), ¡cudaMemcpyDeviceToHost)); }
Friday, 17 May 13
struct ¡SharedMemory { ¡ ¡ ¡ ¡__device__ ¡inline ¡operator ¡float ¡*() ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡extern ¡__shared__ ¡int ¡__smem[]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡return ¡(float ¡*)__smem; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡__device__ ¡inline ¡operator ¡const ¡float ¡*() ¡const ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡extern ¡__shared__ ¡int ¡__smem[]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡return ¡(float ¡*)__smem; ¡ ¡ ¡ ¡} }; template ¡<unsigned ¡int ¡blockSize, ¡bool ¡nIsPow2> __global__ ¡void reduce_kernel(float ¡*g_idata, ¡float ¡*g_odata, ¡unsigned ¡int ¡n) { ¡ ¡ ¡ ¡float ¡*sdata ¡= ¡SharedMemory(); ¡ ¡ ¡ ¡unsigned ¡int ¡tid ¡ ¡ ¡ ¡ ¡ ¡= ¡threadIdx.x; ¡ ¡ ¡ ¡unsigned ¡int ¡i ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡= ¡blockIdx.x*blockSize*2 ¡+ ¡threadIdx.x; ¡ ¡ ¡ ¡unsigned ¡int ¡gridSize ¡= ¡blockSize*2*gridDim.x; ¡ ¡ ¡ ¡float ¡sum ¡= ¡0; ¡ ¡ ¡ ¡while ¡(i ¡< ¡n) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sum ¡+= ¡g_idata[i]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(nIsPow2 ¡|| ¡i ¡+ ¡blockSize ¡< ¡n) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sum ¡+= ¡g_idata[i+blockSize]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡i ¡+= ¡gridSize; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum; ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡512) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡256) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡256]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡256) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡128) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡128]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡128) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(tid ¡< ¡ ¡64) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sdata[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡sdata[tid ¡+ ¡ ¡64]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡__syncthreads(); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(tid ¡< ¡32) ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡volatile ¡float ¡*smem ¡= ¡sdata; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡64) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡32]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡32) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡16]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡16) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡8]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡8) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡4]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡4) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡2]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(blockSize ¡>= ¡ ¡ ¡2) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡smem[tid] ¡= ¡sum ¡= ¡sum ¡+ ¡smem[tid ¡+ ¡ ¡1]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡if ¡(tid ¡== ¡0) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡g_odata[blockIdx.x] ¡= ¡sdata[0]; } void ¡getNumBlocksAndThreads(int ¡n, ¡int ¡maxBlocks, ¡int ¡maxThreads, ¡int ¡&blocks, ¡int ¡&threads) { ¡ ¡ ¡ ¡cudaDeviceProp ¡prop; ¡ ¡ ¡ ¡int ¡device; ¡ ¡ ¡ ¡checkCudaErrors(cudaGetDevice(&device)); ¡ ¡ ¡ ¡checkCudaErrors(cudaGetDeviceProperties(&prop, ¡device)); ¡ ¡ ¡ ¡threads ¡= ¡(n ¡< ¡maxThreads*2) ¡? ¡nextPow2((n ¡+ ¡1)/ ¡2) ¡: ¡maxThreads; ¡ ¡ ¡ ¡blocks ¡ ¡= ¡(n ¡+ ¡(threads ¡* ¡2 ¡-‑ ¡1)) ¡/ ¡(threads ¡* ¡2); ¡ ¡ ¡ ¡if ¡(blocks ¡> ¡prop.maxGridSize[0]) ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡blocks ¡ ¡/= ¡2; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡threads ¡*= ¡2; ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡blocks ¡= ¡min(maxBlocks, ¡blocks); } float reduce(int ¡n, ¡float ¡*d_idata, ¡float ¡*d_odata) { ¡ ¡ ¡ ¡int ¡threads ¡ ¡ ¡ ¡= ¡0; ¡ ¡ ¡ ¡int ¡blocks ¡ ¡ ¡ ¡ ¡= ¡0; ¡ ¡ ¡ ¡int ¡maxThreads ¡= ¡256; ¡ ¡ ¡ ¡int ¡maxBlocks ¡ ¡= ¡64; ¡ ¡ ¡ ¡int ¡size ¡ ¡ ¡ ¡ ¡ ¡ ¡= ¡n ¡ ¡ ¡ ¡while ¡(size ¡> ¡1) ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡getNumBlocksAndThreads(size, ¡maxBlocks, ¡maxThreads, ¡blocks, ¡threads); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡int ¡smemSize ¡= ¡(threads ¡<= ¡32) ¡? ¡2 ¡* ¡threads ¡* ¡sizeof(float) ¡: ¡threads ¡* ¡sizeof(float); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡dim3 ¡dimBlock(threads, ¡1, ¡1); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡dim3 ¡dimGrid(blocks, ¡1, ¡1); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡if ¡(isPow2(size)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡switch ¡(threads) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡512: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<512, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡256: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<256, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡128: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<128, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡64: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡64, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡32: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡32, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡16: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡16, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡8: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡8, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡4: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡4, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡2: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡2, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡1: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡1, ¡true><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡else ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡switch ¡(threads) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡512: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<512, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡256: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<256, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡128: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel<128, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡64: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡64, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡32: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡32, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡16: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡16, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡8: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡8, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡4: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡4, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡2: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡2, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡case ¡ ¡1: ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡reduce_kernel< ¡ ¡1, ¡false><<< ¡dimGrid, ¡dimBlock, ¡smemSize ¡>>>(d_idata, ¡d_odata, ¡size); ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡break; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡size ¡= ¡(size ¡+ ¡(threads*2-‑1)) ¡/ ¡(threads*2); ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡float ¡sum; ¡ ¡ ¡ ¡checkCudaErrors(cudaMemcpy(&sum, ¡d_odata, ¡sizeof(float), ¡cudaMemcpyDeviceToHost)); }
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Tesla T10 (240 cores @ 1.3 GHz) vs. Xenon E5405 (2GHz)
Friday, 17 May 13
Tesla T10 (240 cores @ 1.3 GHz) vs. Xenon E5405 (2GHz)
Friday, 17 May 13
Tesla T10 (240 cores @ 1.3 GHz) vs. Xenon E5405 (2GHz)
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
... d6b821d937a4170b3c4f8ad93495575d: ¡saitek1 d0e52829bf7962ee0aa90550ffdcccaa: ¡laura1230 494a8204b800c41b2da763f9bbbcc462: ¡lina03 d8ff07c52a95b30800809758f84ce28c: ¡Jenny10 e81bed02faa9892f8360c705241191ae: ¡carmen89 46f7d75718029de99dd81fd907034bc9: ¡mellon22 0dd3c176cf34486ec00b526b6920b782: ¡helena04 9351c4bc8c8ba17b58d5a6a1f839f356: ¡85548554 9c36c5599f40d08f874559ac824d091a: ¡585123456 4b4dce6c91b429e8360aa65f97342e90: ¡5678go 3aa561d4c17d9d58443fc15d10cc86ae: ¡momo55 Recovered ¡150/1000 ¡(15.00 ¡%) ¡digests ¡in ¡59.45 ¡s, ¡185.03 ¡MHash/sec
Friday, 17 May 13
Compile with NVIDIA’s compiler & load onto the GPU Copy result back to Haskell Transform Accelerate program into CUDA program
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Arrays in Arrays out
Friday, 17 May 13
Arrays in Arrays out
Friday, 17 May 13
Arrays in Arrays out
Friday, 17 May 13
Arrays in Arrays out
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
f ¡0 f ¡1 f ¡2 f ¡3 f ¡4 f ¡5 f ¡6 f ¡7 f ¡8 f ¡9
Friday, 17 May 13
f ¡0 f ¡1 f ¡2 f ¡3 f ¡4 f ¡5 f ¡6 f ¡7 f ¡8 f ¡9
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
http://xkcd.com/365/
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13
Friday, 17 May 13