C++ 用于bool实现的atomicCAS
我试图找出Cuda的实现中是否存在缺陷(现已删除),比如C++ 用于bool实现的atomicCAS,c++,cuda,C++,Cuda,我试图找出Cuda的实现中是否存在缺陷(现已删除),比如atomicCASforbools。答案中的代码(重新格式化): 预期输出为0,但实际输出为1 我有一个关于如何修复它的建议,但不是100%确定它是线程安全的: static __inline__ __device__ bool atomicCAS(bool *address, bool compare, bool val) { unsigned long long addr = (unsigned long long)addres
atomicCAS
forbool
s。答案中的代码(重新格式化):
预期输出为0,但实际输出为1
我有一个关于如何修复它的建议,但不是100%确定它是线程安全的:
static __inline__ __device__ bool atomicCAS(bool *address, bool compare, bool val)
{
unsigned long long addr = (unsigned long long)address;
unsigned pos = addr & 3; // byte position within the int
int *int_addr = (int *)(addr - pos); // int-aligned address
int old = *int_addr, assumed, ival;
do
{
if(*address != compare) // If we expected that bool to be different, then
break; // stop trying to update it and just return it's current value
assumed = old;
if(val)
ival = old | (1 << (8 * pos));
else
ival = old & (~((0xFFU) << (8 * pos)));
old = atomicCAS(int_addr, assumed, ival);
} while(assumed != old);
return (bool)(old & ((0xFFU) << (8 * pos)));
}
static\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
{
无符号长地址=(无符号长)地址;
unsigned pos=addr&3;//整数中的字节位置
int*int_addr=(int*)(addr-pos);//与int对齐的地址
int old=*int_addr,假定,ival;
做
{
if(*address!=compare)//如果我们期望bool是不同的,那么
break;//停止尝试更新它,只返回它的当前值
假定=旧;
if(val)
ival=old |(1非常感谢@RobertCrovella;第一个代码示例确实包含错误,第二个代码示例修复了错误,但不是线程安全的(有关详细信息,请参阅问题注释)。线程安全修复:
static __inline__ __device__ bool atomicCAS(bool *address, bool compare, bool val)
{
unsigned long long addr = (unsigned long long)address;
unsigned pos = addr & 3; // byte position within the int
int *int_addr = (int *)(addr - pos); // int-aligned address
int old = *int_addr, assumed, ival;
bool current_value;
do
{
current_value = (bool)(old & ((0xFFU) << (8 * pos)));
if(current_value != compare) // If we expected that bool to be different, then
break; // stop trying to update it and just return it's current value
assumed = old;
if(val)
ival = old | (1 << (8 * pos));
else
ival = old & (~((0xFFU) << (8 * pos)));
old = atomicCAS(int_addr, assumed, ival);
} while(assumed != old);
return current_value;
}
static\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
{
无符号长地址=(无符号长)地址;
unsigned pos=addr&3;//整数中的字节位置
int*int_addr=(int*)(addr-pos);//与int对齐的地址
int old=*int_addr,假定,ival;
布尔电流_值;
做
{
当前_值=(bool)(old&((0xFFU)多亏了@RobertCrovella;第一个代码示例确实包含错误,第二个代码示例修复了错误,但不是线程安全的(有关详细信息,请参阅问题注释)。线程安全修复:
static __inline__ __device__ bool atomicCAS(bool *address, bool compare, bool val)
{
unsigned long long addr = (unsigned long long)address;
unsigned pos = addr & 3; // byte position within the int
int *int_addr = (int *)(addr - pos); // int-aligned address
int old = *int_addr, assumed, ival;
bool current_value;
do
{
current_value = (bool)(old & ((0xFFU) << (8 * pos)));
if(current_value != compare) // If we expected that bool to be different, then
break; // stop trying to update it and just return it's current value
assumed = old;
if(val)
ival = old | (1 << (8 * pos));
else
ival = old & (~((0xFFU) << (8 * pos)));
old = atomicCAS(int_addr, assumed, ival);
} while(assumed != old);
return current_value;
}
static\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
{
无符号长地址=(无符号长)地址;
unsigned pos=addr&3;//整数中的字节位置
int*int_addr=(int*)(addr-pos);//与int对齐的地址
int old=*int_addr,假定,ival;
布尔电流_值;
做
{
当前_值=(bool)(old&(0xFFU)是的,您是正确的。上一个答案中的实现不是正确的atomicCAS
(我认为它基本上是在做atomicExch
)此方案不是线程安全的。假设执行原子读取的线程将*int\u addr
读入旧的s线程进入do
循环并读取*地址
,发现它与比较
匹配。然后线程将继续使用旧的
值作为假定的
,这不再是我们想要的。解决方案是使用假定的
(即旧的
)值,并从中提取必要的bool
,用于if
测试。@RobertCrovella哇,我明白了。这太完美了。谢谢。我的库为所有简单的整数类型(以及float和double)实现了一个通用的kat::atomic::compare_and_swap()
-在必要的时候对上述技术进行泛化。但是,它还没有得到充分的测试。我将仔细检查我的实现与您在这里所做的操作;并且您可能希望考虑使用它。是的,您是正确的。在前一个答案中的实现不是一个正确的<代码> AddiICCAS < /代码>。(我认为它基本上是在做atomicExch
)此方案不是线程安全的。假设执行原子读取的线程将*int\u addr
读入旧的s线程进入do
循环并读取*地址
,发现它与比较
匹配。然后线程将继续使用旧的
值作为假定的
,这不再是我们想要的。解决方案是使用假定的
(即旧的
)值,并从中提取必要的bool
,用于if
测试。@RobertCrovella哇,我明白了。这太完美了。谢谢。我的库为所有简单的整数类型(以及float和double)实现了一个通用的kat::atomic::compare_and_swap()
-在必要的时候对上述技术进行泛化。但是,它还没有得到充分的测试。我将再次检查我的实现与您在这里所做的情况,并且您可能希望考虑使用它。
static __inline__ __device__ bool atomicCAS(bool *address, bool compare, bool val)
{
unsigned long long addr = (unsigned long long)address;
unsigned pos = addr & 3; // byte position within the int
int *int_addr = (int *)(addr - pos); // int-aligned address
int old = *int_addr, assumed, ival;
bool current_value;
do
{
current_value = (bool)(old & ((0xFFU) << (8 * pos)));
if(current_value != compare) // If we expected that bool to be different, then
break; // stop trying to update it and just return it's current value
assumed = old;
if(val)
ival = old | (1 << (8 * pos));
else
ival = old & (~((0xFFU) << (8 * pos)));
old = atomicCAS(int_addr, assumed, ival);
} while(assumed != old);
return current_value;
}