是否可以在块级别进行原子写入? 作为一个例子考虑以下内容:
__global__ kernel (int atomic)
{
atomic+=blockid.x; //should be atomic for each block
}
答案 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。