Implementation of Long Atomic Int

Implementation of Long Atomic Int

本文关键字:Int Atomic Long of Implementation      更新时间:2023-10-16

我想使用计数通常为2^40的原子计数器(多线程计算),因此我不能直接使用32位int原子计数器。我还没有c++11(我会迁移到它,但还没有,因为这对我来说是有成本的),我必须在32位和64位平台上编译。我目前使用QT,所以我可以使用QAtomicInt。

我是这么想的:

(initialization...)
QAtomicInt counterLo = 0;
QAtomicInt counterHi = 0;

void increment()
{
    int before = counterLo.fetchAndAddOrdered(1);
    if(before==INT_MAX)
    {
        counterHi.fetchAndAddOrdered(1); //Increment high word
        counterLo.fetchAndAddOrdered(INT_MAX);    //Increments low word to -1
        counterLo.fetchAndAddOrdered(1);   //Increments low word to 0
    }         
}
uint64_t value()
{
    //Wait until the low word is non-negative
    int lo = counterLow;
    while(lo<0)
        lo = counterLow;
    return (uint64_t)counterHi * ((uint64_t)INT_MAX+1) + (uint64_t)lo;
}

正确吗?我已经尝试用互斥锁来制作计数器,但是我损失了大约10%的性能。每秒大约被调用100万次,在8个线程之间共享(蒙特卡罗模拟的示例计数器)

谢谢!

这不是完全原子化的,参见下面的例子:

  • hi=0,lo=INT_MAX
  • T1呼叫value(),接lo=INT_MAX,中断
  • T2调用increment()将hi递增到1
  • T1恢复并读取counterHi,获得1,返回值2^32 + INT_MAX

这可能不是您想要的。难道不能分割样本空间,让每个线程计算n/8个项目而不争用锁吗?

当然这不是原子的。原子操作序列可能被中断。我建议使用保护(互斥锁或临界区)