我正在与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;
}
输出
count: 0
count: 0
有什么问题?
提前致谢!
答案 0 :(得分:8)
您应该将cuda_count
传递给您的内核函数。除此之外,所有线程都试图增加相同的内存位置。其效果尚未明确定义(至少有一次写入会成功,但不止一次可以)。
你需要通过只让一个线程执行工作来防止这种情况:
__global__ void inc(int *foo) {
if (blockIdx.x == 0 && threadIdx.x == 0)
++*foo;
}
(未测试的)
答案 1 :(得分: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;
}
输出:
count: 0
count: 2500
感谢您让我意识到我犯的错误。
答案 2 :(得分:0)
您的代码的问题在于您将设备内核指针传递给指向count的指针。不指向计数。一个'&amp;'太多了
这一行
inc <<< 100, 25 >>> (&count);
应该是
inc <<< 100, 25 >>> (count);