【发布时间】:2020-03-31 13:10:58
【问题描述】:
大家好,我正在尝试使用网格步长方法和原子函数来进行多块缩减。
我知道执行此操作的通常方法是启动两个内核或按照this 说明中的指示使用lastblock 方法。(或this 教程)
但是,我认为这也可以通过使用带有原子代码的网格步幅来完成。
正如我测试的那样,它工作得很好..
直到 some 数字,它给出了错误的答案。 (这很奇怪)
我测试了一些“n”,发现 n = 1234565、1234566、1234567 的答案有误。
这是我做 n 和 1 的全部代码。所以答案应该是 n。
任何帮助或评论表示赞赏。
#include<iostream>
__global__ void stride_sum(const double* input,
const int size,
double* sumOut){
extern __shared__ double sm[];
unsigned int tid = threadIdx.x;
unsigned int i = blockDim.x * blockIdx.x + tid;
//doing grid loop using stride method.
for(unsigned int s=i;
s<size;
s+=blockDim.x*gridDim.x){
sm[tid] = input[i];
__syncthreads();
//doing parallel reduction.
for(unsigned int ss = blockDim.x/2;ss>0;ss>>=1){
if(tid<ss && tid+ss<size) sm[tid] += sm[tid+ss];
__syncthreads();
}
//atomically add results to sumOut.
if(tid==0) atomicAdd(sumOut, sm[0]);
}
}
int main(){
unsigned int n = 1234567;
int blockSize = 4;
int nBlocks = (n + blockSize - 1) / blockSize;
int sharedMemory = sizeof(double)*blockSize;
double *data, *sum;
cudaMallocManaged(&data, sizeof(double)*n);
cudaMallocManaged(&sum, sizeof(double));
std::fill_n(data,n,1.);
std::fill_n(sum,1,0.);
stride_sum<<<nBlocks, blockSize, sharedMemory>>>(data,n,sum);
cudaDeviceSynchronize();
printf("res: 10.f \n",sum[0]);
cudaFree(data);
cudaFree(sum);
return 0;
}
【问题讨论】: