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アトミックは与えました

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 に答える