我可以在x86 / x86_64上原子地递增16位计数器吗?

时间:2009-10-09 05:53:44

标签: performance assembly x86 atomic x86-64

我希望通过将现有的32位计数器转换为16位计数器来节省内存。该计数器以原子方式递增/递减。如果我这样做:

  1. 我在x86 / x86_64上对atomic_inc(uint16_t x)使用了哪些指令?
  2. 这在多处理器x86 / x86_64机器中是否可靠?
  3. 对于这些架构,是否需要为这些架构付出性能损失?
  4. 如果(3)是,那么预期的性能损失是多少?
  5. 感谢您的评论!

4 个答案:

答案 0 :(得分:4)

这是一个使用GCC程序集扩展的程序,作为Steve的Delphi答案的替代方法:

uint16_t atomic_inc(uint16_t volatile* ptr)
{
    uint16_t value(1);
    __asm__("lock xadd %w0, %w1" : "+r" (value) : "m" (*ptr));
    return ++value;
}

将-1更改为-1,将++更改为--以减少。

答案 1 :(得分:3)

这是一个有效的Delphi函数:

function LockedInc( var Target :WORD ) :WORD;
asm
        mov     ecx, eax
        mov     ax, 1
   Lock xadd    [ecx], ax
        Inc     eax
end;

我想你可以把它转换成你需要的任何语言。

答案 2 :(得分:0)

执行原子增加的最简单方法如下(这是内联ASM):

asm
  lock inc dword ptr Counter;
end;

其中J是整数。这将直接增加Counter在其内存位置。

我用暴力测试了它,它100%工作。

答案 3 :(得分:-1)

回答其他三个问题:

  1. 没有找到以2
  2. 开头的编号列表的方法
  3. 是的,这在多处理器环境中是可靠的
  4. 是的,会有性能下降
  5. “lock”前缀锁定总线,不仅用于处理器,还用于任何外部硬件,可能需要通过DMA(大容量存储,图形......)访问总线。因此它很慢,通常约为100个时钟周期,但可能更昂贵。但是,如果你有“兆字节”的计数器,很可能,你将面临缓存未命中,在这种情况下你将不得不等待约100个时钟(内存访问时间),如果页面未命中,几个一百,所以锁的开销可能无关紧要。