2

我正在对与原子相关的 Linux 上的 g++ 4.4.6 进行一些研究。我有一个简单的循环,我用它来估计在原子上执行 fetch_add(1) 所需的时间。

atomic<int> ia;
ia.store(0);
timespec start,stop;
clock_gettime(CLOCK_REALTIME, &start);
while (ia < THE_MAX)
{
    //++ia;
    ia.fetch_add(1);
}
clock_gettime(CLOCK_REALTIME, &stop);

我惊讶地发现以下运行了大约一半的时间:

volatile int ia=0;
timespec start,stop;
clock_gettime(CLOCK_REALTIME, &start);
while (ia < THE_MAX)
{
    __sync_fetch_and_add( &ia, 1 );
}
clock_gettime(CLOCK_REALTIME, &stop);

我拆开了它——并不是说我非常擅长 x86 汇编器——我看到了这个主要区别。生成的 C++11 原子调用

call    _ZNVSt9__atomic213__atomic_baseIiE9fetch_addEiSt12memory_order

而 gcc atomic 给出了

lock addl   $1, (%eax)

我希望 g++ 能给我最好的选择,所以我认为我对正在发生的事情的理解有一些严重的辍学。任何人都清楚为什么 C++ 调用的生成不如 gcc 原子调用吗?(也许这只是 g++ 4.4 不太成熟的问题......)。谢谢。

4

1 回答 1

3

这只是 GCC 版本和优化的问题。例如,使用 gcc 4.6.3 和 -O3,我得到一个lock addfor atomic<int>::fetch_add

#include <atomic>
void j(std::atomic<int>& ia)
{
        ia.fetch_add(1);
} 

产量(对于带有 -O3 和 gcc-4.6.3 的 x86_64):

.LFB382:
    .cfi_startproc
    lock addl       $1, (%rdi)
    ret
    .cfi_endproc
于 2012-09-20T20:57:14.587 回答