我要分配一个cuda全局内存数组。我有总结的核心:
__device__ float R_d = 0;
__global__ void perform_summation(float* A, int N){
int idx = blockDim.x*blockIdx.x+threadIdx.x;
extern __shared__ float sharedArray [];
float result[]; //THIS IS THE THING i TRIED TO CREATE
if(idx < N){
sharedArray[threadIdx.x] = A[idx];
// }else{
// sharedArray[threadIdx.x] = 0 ;
// }
for (unsigned int stride = 1; stride < blockDim.x; stride *= 2) {
__syncthreads();
if(threadIdx.x % (2*stride) == 0){
sharedArray[threadIdx.x]+=sharedArray[threadIdx.x+stride];
}
}
}
if(idx % blockDim.x == 0){
// R_d += sharedArray[threadIdx.x];
result[blockIdx.x] = sharedArray[threadIdx.x];
}
for (int i = 0; i < gridDim.x; ++i) {
R_d += result[i];
}
}
总结y内核采用数组并通过map reduce方法找到元素的总和。每个块将相关元素放入共享内存并对内部的所有数据求和,而不是将结果放入我尝试创建的全局数组中。在决赛中,我将总结全局数组的所有数字以找到最后的答案。
作为第一种方法,我没有使用全局数组来收集每个块的结果,我只是将块的结果加到变量R_d
中,但它不起作用,只显示来自最后一块作为结果。我想因为我没有同步。块之间的最后一个块会覆盖最后的所有值。这是我在内核结束时第一次尝试所做的事情
f(idx < N){
sharedArray[threadIdx.x] = A[idx];
// }else{
// sharedArray[threadIdx.x] = 0 ;
// }
for (unsigned int stride = 1; stride < blockDim.x; stride *= 2) {
__syncthreads();
if(threadIdx.x % (2*stride) == 0){
sharedArray[threadIdx.x]+=sharedArray[threadIdx.x+stride];
}
}
if(threadIdx.x == 0){
R_d += sharedArray[threadIdx.x];
}
}
所以我实际上有两个问题。如何在设备内存中为我提出的第一个解决方案定义全局内存数组,对于仅使用R_d
变量的第二个解决方案是否有任何解决方案?
答案 0 :(得分:1)
您可以通过cudaMalloc:
在全局设备内存中分配数组cudaMalloc((void **)&ptr, size);
但你不想在内核中执行此操作,在调用内核并将指针传递给内核之前,请执行此操作。
关于减少,请看these nVidia slides,它解释得很好。基本上,它取决于您使用的块和线程数。可以说有几个街区。因此,在共享内存中定义一个数组:
__shared__ float cache[BLOCK_THREADS];
为每个块分配共享内存,因此我们将每个块中的值与cache
中的第一个元素相加。
__syncthreads();
int step = (BLOCK_THREADS >> 1); //the same result as BLOCK_THREADS/2
while(step > 0) {
if (threadInBlock < step) {
cache[threadInBlock] += cache[threadInBlock + step];
}
__syncthreads();
step = (step >> 1);
}
因此,这将每个块中的所有元素加总为cache[0]
。现在我们可以再次使用简化,或者我们可以将每个块的所有总和与原子操作相加。如果块数明显少于每个块的线程数,那就没问题。
__syncthreads();
if (threadInBlock == 0) {
atomicAdd(result, cache[0]);
}
请注意,result
是指向全局内存中单个值的指针。另请注意,这仅在BLOCK_THREADS
为2的幂时才有效 - 这很常见,因为每个块的线程数应为32的倍数(与warp对齐)。