如何在不使用CUDA原子的情况下进行总和计算
问题描述:
在下面的代码中,如何计算sum_array值而不使用atomicAdd。如何在不使用CUDA原子的情况下进行总和计算
内核方法
__global__ void calculate_sum(int width,
int height,
int *pntrs,
int2 *sum_array)
{
int row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;
if (row >= height || col >= width) return;
int idx = pntrs[ row * width + col ];
//atomicAdd(&sum_array[ idx ].x, col);
//atomicAdd(&sum_array[ idx ].y, row);
sum_array[ idx ].x += col;
sum_array[ idx ].y += row;
}
启动内核
dim3 dimBlock(16, 16);
dim3 dimGrid((width + (dimBlock.x - 1))/dimBlock.x,
(height + (dimBlock.y - 1))/dimBlock.y);
答
降低对于这类问题的通用名称。请参阅presentation以获得进一步说明,或使用Google进行其他示例。
解决此问题的一般方法是在线程块内部创建并行总和的全局内存段并将结果存储在全局内存中。之后,将部分结果复制到CPU内存空间,使用CPU对部分结果进行求和,然后将结果复制回GPU内存。您可以通过对部分结果执行另一个并行总和来避免对内存的处理。
另一种方法是对CUDA使用高度优化的库,例如Thrust或CUDPP,其中包含执行这些功能的函数。
答
我CUDA是非常非常生疏,但是这是大概你如何做到这一点(“Cuda的用例”,我强烈建议您阅读提供):
https://developer.nvidia.com/content/cuda-example-introduction-general-purpose-gpu-programming-0
- 对你需要总结的数组进行更好的分区:CUDA中的线程是轻量级的,但不是那么多,以至于你可以只产生两个总和,并希望获得任何性能优势。
- 在这一点上,每个线程都将负责总结一部分数据:创建一个与线程数量一样大的共享int数组,其中每个线程将保存其计算的部分总和。
- 同步线程,减少共享内存阵列:
(请把它作为伪)
// Code to sum over a slice, essentially a loop over each thread subset
// and accumulate over "localsum" (a local variable)
...
// Save the result in the shared memory
partial[threadidx] = localsum;
// Synchronize the threads:
__syncthreads();
// From now on partial is filled with the result of all computations: you can reduce partial
// we'll do it the illiterate way, using a single thread (it can be easily parallelized)
if(threadidx == 0) {
for(i = 1; i < nthreads; ++i) {
partial[0] += partial[i];
}
}
和您去:局部[0]会牵着你的总和(或计算)。
请参阅“CUDA示例”中的dot产品示例,以获得关于该主题和约O(log(n))运行的约简算法的更严格讨论。
希望这会有所帮助