C++ 用于bool实现的atomicCAS

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

我试图找出Cuda的实现中是否存在缺陷(现已删除),比如
atomicCAS
for
bool
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;
}