我已将锁定纹理标准化为img0
.
锁类型 1:
线程扭曲有一个共享程序计数器。如果单个线程抢到了锁,warp 中的其他线程仍然会卡在循环中。实际上,这可以编译,但会导致死锁。
例子:堆栈溢出, OpenGL.org
while (imageAtomicExchange(img0,coord,1u)==1u);
//<critical section>
memoryBarrier();
imageAtomicExchange(img0,coord,0);
锁类型 2:
为了解决类型 1 的问题,可以改为有条件地写入。在下面,我有时将循环编写为 do-while 循环,但 while 循环也无法正常工作。
锁类型2.1:
首先尝试的是一个简单的循环。显然,由于优化错误,这可能会导致崩溃(我最近没有尝试过)。
例子:NVIDIA
bool have_written = false;
while (true) {
bool can_write = (imageAtomicExchange(img0,coord,1u)!=1u);
if (can_write) {
//<critical section>
memoryBarrier();
imageAtomicExchange(img0,coord,0);
break;
}
}
锁类型2.2:
上面的例子使用imageAtomicExchange(...)
,这可能不是人们尝试的第一件事。最直观的就是imageAtomicCompSwap(...)
。不幸的是,由于优化错误,这不起作用。否则它(应该)是健全的。
例子:堆栈溢出
bool have_written = false;
do {
bool can_write = (imageAtomicCompSwap(img0,coord,0u,1u)==0u);
if (can_write) {
//<critical section>
memoryBarrier();
imageAtomicExchange(img0,coord,0);
have_written = true;
}
} while (!have_written);
锁类型2.3:
从以下位置切换回来imageAtomicCompSwap(...)
to imageAtomicExchange(...)
是另一种常见的变体。与2.1的区别在于循环终止的方式。这对我来说不能正常工作。
例子:堆栈溢出, 堆栈溢出
bool have_written = false;
do {
bool can_write = (imageAtomicExchange(img0,coord,1u)!=1u);
if (can_write) {
//<critical section>
memoryBarrier();
imageAtomicExchange(img0,coord,0);
have_written = true;
}
} while (!have_written);