Pri*_*alj 1 multithreading cuda gpu thread-safety shared-memory
我是CUDA的初学者.我这里有一个由2个线程执行的内核.所有线程都应将结果保存到共享变量中.三个完成后,结果sum应该是12但我得到6!
__global__ void kernel (..)
{
int i=blockDim.x*blockIdx.x+threadIdx.x;
__shared__ double sum;
...
if(i==0)
sum=0.0;
__syncthreads();
if(i<=1)
sum+= 2.0*3.0;
__syncthreads();
//sum should be 12 here, but I get 6. Why?
}
Run Code Online (Sandbox Code Playgroud)
叫做
test<<<1,2>>>(..);
Run Code Online (Sandbox Code Playgroud)
您的代码中存在内存竞争.这个:
sum+= 2.0*3.0;
Run Code Online (Sandbox Code Playgroud)
可能允许多个线程同时累积到总和.在您的示例中,两个线程都试图同时加载和存储在同一地址.这是CUDA中未定义的行为.
避免此问题的常用方法是重新设计算法.只是没有多个线程写入相同的内存位置.有一个非常广泛描述的共享内存减少技术,您可以使用它来累积共享内存数组的总和而无需内存竞争.
或者,存在可用于串行化存储器访问的原子存储器访问原语.你的例子是双精度浮点,我很确定没有内在的原子添加函数.编程指南包括用于双精度的用户空间原子添加的示例.取决于您的硬件,它可能在共享内存变量上可用,也可能不可用,因为64位共享内存原子操作仅在计算能力2.x和3.x设备上受支持.在任何情况下,都应该谨慎使用原子内存操作,因为序列化内存访问会大大降低性能.