如果我使用31个区块,为什么CUDA减少失败?

如果我使用31个区块,为什么CUDA减少失败?,cuda,cub,Cuda,Cub,以下CUDA代码获取标签列表(0、1、2、3…),并查找这些标签的权重总和 为了加速计算,我使用了共享内存,这样每个线程都可以维护自己的运行总和。在计算结束时,我执行一个立方体块范围的缩减,然后向全局内存中添加一个原子 如果我使用的块少于30个,CPU和GPU对结果的看法是一致的,但如果我使用的块多于30个,CPU和GPU就不一致。这是为什么?我如何修复它 检查代码中的错误代码不会产生任何结果,cuda gdb和cuda memcheck不会显示任何未捕获的错误或内存问题 我使用的是NVCC v

以下CUDA代码获取标签列表(0、1、2、3…),并查找这些标签的权重总和

为了加速计算,我使用了共享内存,这样每个线程都可以维护自己的运行总和。在计算结束时,我执行一个立方体块范围的缩减,然后向全局内存中添加一个原子

如果我使用的块少于30个,CPU和GPU对结果的看法是一致的,但如果我使用的块多于30个,CPU和GPU就不一致。这是为什么?我如何修复它

检查代码中的错误代码不会产生任何结果,cuda gdb和cuda memcheck不会显示任何未捕获的错误或内存问题

我使用的是NVCC v10.1.243,运行的是Nvidia Quadro P2000

MWE
//使用nvcc-I/z/downloads/cub-1.8.0/cuda\u reduction.cu-arch=sm\u 61等编译
#包括
#包括
#包括
#包括
__全球\uuuuuu无效组\uuu夏季(
常量int32_t*常量标签,
常量浮点*常量权重,
常量int num_元素,
常量int num_类,
双*常数和,
uint32_t*常数计数
){
constexpr int num_threads=128;
断言(num_threads==blockDim.x);
//获取共享内存
外部共享内部s[];
double*常数和_shmem=(double*)s;
uint32_t*常量计数_shmem=(uint32_t*)和总和_shmem[num_threads*num_classes];
double*const my_sums=&sums_shmem[num_classes*threadIdx.x];
uint32_t*const my_counts=&counts_shmem[num_classes*threadIdx.x];

对于(inti=0;i当我在特斯拉V100上运行代码时,除了第一次测试之外,所有结果都是失败的

您在这里遇到了一个问题:

  for(int i=0;i<num_threads*num_classes;i+=num_threads){
    sums_shmem[i] = 0;
    counts_shmem[i] = 0;
  }
cudaSuccess
不是与运行时API一起使用的正确枚举令牌。您应该改用
cudaSuccess
(有两个实例)

我还认为你的错误比较容易引起麻烦:

if(std::abs(a[i]-b[i])>1e-4)

但这似乎不是一个问题。我通常希望在测试前看到一些扩展。

啊,我现在觉得很愚蠢。谢谢你为我指出这一点!顺便说一句:这似乎是解决问题的合理方法吗?这是合理的。我想可能有一种更快的方法。这里的一个潜在问题是你的共享内存使用率becomes是占用率的限制器,这可能会转化为性能的限制器。您使用的是cc 6.0或更新的GPU,它具有相当快的共享原子。根据我的测试,一个简单的共享原子缩减内核在我的特斯拉V100上运行快约2倍。
if(std::abs(a[i]-b[i])>1e-4)