正如我从此链接http://www.cuvilib.com/Reduction.pdf
中的NVIDIA指令中读到的,对于大于blockSize
的数组,我应该启动多个简化内核来实现全局同步。确定启动还原内核的次数的一般方法是什么?我尝试如下,但我需要Malloc 2额外的指针,这需要大量的处理时间。
我的工作是将数组d_logLuminance
简化为一个最小值min_logLum
void your_histogram_and_prefixsum(const float* const d_logLuminance,
float &min_logLum,
const size_t numRows,
const size_t numCols)
{
const dim3 blockSize(512);
unsigned int pixel = numRows*numCols;
const dim3 gridSize(pixel/blockSize.x+1);
//Reduction kernels to find max and min value
float *d_tempMin, *d_min;
checkCudaErrors(cudaMalloc((void**) &d_tempMin, sizeof(float)*pixel));
checkCudaErrors(cudaMalloc((void**) &d_min, sizeof(float)*pixel));
checkCudaErrors(cudaMemcpy(d_min, d_logLuminance, sizeof(float)*pixel, cudaMemcpyDeviceToDevice));
dim3 subGrid = gridSize;
for(int reduceLevel = pixel; reduceLevel > 0; reduceLevel /= blockSize.x) {
checkCudaErrors(cudaMemcpy(d_tempMin, d_min, sizeof(float)*pixel, cudaMemcpyDeviceToDevice));
reduceMin<<<subGrid,blockSize,blockSize.x*sizeof(float)>>>(d_tempMin, d_min);
cudaDeviceSynchronize(); checkCudaErrors(cudaGetLastError());
subGrid.x = subGrid.x / blockSize.x + 1;
}
checkCudaErrors(cudaMemcpy(&min_logLum, d_min, sizeof(float), cudaMemcpyDeviceToHost));
std::cout<< "Min value = " << min_logLum << std::endl;
checkCudaErrors(cudaFree(d_tempMin));
checkCudaErrors(cudaFree(d_min));
}
如果你好奇,这是我的缩减内核:
__global__
void reduceMin(const float* const g_inputRange,
float* g_outputRange)
{
extern __shared__ float sdata[];
unsigned int tid = threadIdx.x;
unsigned int i = blockDim.x * blockIdx.x + threadIdx.x;
sdata[tid] = g_inputRange[i];
__syncthreads();
for(unsigned int s = blockDim.x/2; s > 0; s >>= 1){
if (tid < s){
sdata[tid] = min(sdata[tid],sdata[tid+s]);
}
__syncthreads();
}
if(tid == 0){
g_outputRange[blockIdx.x] = sdata[0];
}
}
答案 0 :(得分:0)
有很多方法可以对猫进行换肤,但是如果你想最小化内核启动,最多只需要两次内核启动就可以完成。
第一个内核启动由多个块组成,这些块对应于设备支持的每个块的线程数。较新的设备将支持1024个旧设备,512。
第一个内核中的每个(最多512或1024个)块都将参与全局内存中所有数据元素的网格循环求和。
然后,这些块中的每一个都将进行部分缩减并将部分结果写入全局内存。这些部分结果将有512或1024个。
第二个内核启动将由一个块中的512或1024个线程组成。每个线程将从全局内存中获取一个部分结果,然后该单个块中的线程将协同地将部分结果减少为单个最终结果,并将其写回全局内存。
“网格循环和”在简化#7 here中描述为“多个添加/线程”。本文档中描述的所有减少都可以在NVIDIA reduction sample code
中找到