初学者CUDA - 简单的var增量不起作用

Ren*_*ues 6 c++ cuda

我正在与CUDA合作开展一个项目.为了掌握它,我有以下代码.

#include <iostream>

using namespace std;

__global__ void inc(int *foo) {
  ++(*foo);
}

int main() {
  int count = 0, *cuda_count;
  cudaMalloc((void**)&cuda_count, sizeof(int));
  cudaMemcpy(cuda_count, &count, sizeof(int), cudaMemcpyHostToDevice);
  cout << "count: " << count << '\n';
  inc <<< 100, 25 >>> (&count);
  cudaMemcpy(&count, cuda_count, sizeof(int), cudaMemcpyDeviceToHost);
  cudaFree(cuda_count);
  cout << "count: " << count << '\n';
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是

count: 0
count: 0
Run Code Online (Sandbox Code Playgroud)

有什么问题?

提前致谢!

Kon*_*lph 8

你应该传递cuda_count给你的内核函数.除此之外,所有线程都试图增加相同的内存位置.其效果尚未明确定义(至少一次写入会成功,但不止一次可以).

您需要通过仅让一个线程执行工作来防止这种情况:

__global__ void inc(int *foo) {
  if (blockIdx.x == 0 && threadIdx.x == 0)
    ++*foo;
}
Run Code Online (Sandbox Code Playgroud)

(另)

  • @Renato:这不是CUDA的工作方式.请参阅我更新的答案:从不同的线程写入相同的内存位置只是未定义.你想要的是一个所谓的聚集操作.实现这一点并非易事. (5认同)
  • Konrad的修复确保只有带有`threadIdx.x == 0`的线程才会尝试增加变量,但是由于你启动了很多块,你将拥有许多带有该索引的线程.尝试`blockIdx.x == 0 && threadIdx.x == 0`.话虽如此,可能值得查看一些SDK示例,以便更清楚地了解这一切是如何工作的...... (3认同)

Ren*_*ues 7

我找到了解决方案.我只需要使用原子函数,即在不受其他线程干扰的情况下执行的函数.换句话说,在操作完成之前,没有其他线程可以访问特定地址.

码:

#include <iostream>

using namespace std;

__global__ void inc(int *foo) {
  atomicAdd(foo, 1);
}

int main() {
  int count = 0, *cuda_count;
  cudaMalloc((void**)&cuda_count, sizeof(int));
  cudaMemcpy(cuda_count, &count, sizeof(int), cudaMemcpyHostToDevice);
  cout << "count: " << count << '\n';
  inc <<< 100, 25 >>> (cuda_count);
  cudaMemcpy(&count, cuda_count, sizeof(int), cudaMemcpyDeviceToHost);
  cudaFree(cuda_count);
  cout << "count: " << count << '\n';
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

count: 0
count: 2500
Run Code Online (Sandbox Code Playgroud)

感谢您让我意识到我提交的错误.