块级原子写

时间:2011-07-07 16:40:16

标签: c++ c cuda gpu gpgpu

是否可以在块级别进行原子写入? 作为一个例子考虑以下内容:

__global__ kernel (int atomic)
{
    atomic+=blockid.x; //should be atomic for each block
}

3 个答案:

答案 0 :(得分:3)

您可以在CUDA中执行一些原子操作。请参阅“CUDA编程指南”中的Apendix B.11原子功能。即:

__global__ void kernel (int *result)
{
    atomicAdd(result, blockIdx.x); // 
}

您还可以交换变量的值

__global__ void kernel (int *result)
{
    atomicExch(result, blockIdx.x); // 
}

这两个例子都在全局记忆中运作。

  

在共享内存上运行的原子函数和在64位字上运行的原子函数仅适用于1.2及以上计算能力的设备。

问候。

答案 1 :(得分:0)

您可以在共享内存上执行原子操作,但不能在代码片段中尝试执行此操作:您的内核int参数是特定于线程的变量;即使所有线程都获得了你在发布时给出的相同价值,它们也不会将它存储在共享内存中 - 并且以原子方式对其进行操作毫无意义。

如果您已将int *传递给某个缓冲区,那么它将成为全局内存中的缓冲区。您可以对全局内存中的数据执行设备范围的原子操作,如@ pQB' answer中所述。但是你问过块级原子操作......这对全局数据并没有多大意义。但是,如果你的一个线程写入某个全局地址,则所有__threadfence_block()都可以停止,直到该写入的效果对块中的所有其他线程可见。

CUDA中也支持适当的块级原子,但是 - 在共享内存上。在this Parallel4All blog entry或相关section CUDA Programming Guide中了解如何使用共享内存。

如果你有一些__shared__ int x,你可以使用与全局原子相同的语法对它执行块级原子操作:atomicAdd(&x, 7)将原子地将123添加到x的值。但是 - 请记住块中的所有线程都会这样做,并且您当然不希望一次尝试多达1024个原子写入。通常你会有像

这样的东西
__shared__ some_buffer[NumFoosPerBar];

// ...

if (check_condition()) { 
     int foo_index = get_thread_foo_index_for(threadIdx.x);
     atomicAdd(&some_buffer[foo_index], 7);
}

可能有多个线程写入同一位置,但不一定。当你期望多次写入时 - 不要使用原子,而是对要写入的值执行某种减少。

答案 2 :(得分:-2)

虽然不清楚你对块/块级别的意思,但听起来你只需要一个原子添加。 那些可以在#include <asm/atomic.h>的内核中找到,你的代码将是

__global__ kernel (int atomic)
{
    atomic_add(blockid.x,&atomic);
}

atomic必须是atomic_t类型,而blockid.x必须是int。