web-dev-qa-db-ja.com

なぜstd :: atomic <bool>はvolatile boolよりもずっと遅いのですか?

私は長年、スレッド実行制御にvolatile boolを使用してきましたが、うまくいきました。

// in my class declaration
volatile bool stop_;

-----------------

// In the thread function
while (!stop_)
{
     do_things();
}

さて、c ++ 11がアトミック操作のサポートを追加したので、代わりにそれを試してみることにしました

// in my class declaration
std::atomic<bool> stop_;

-----------------

// In the thread function
while (!stop_)
{
     do_things();
}

しかし、それはvolatile boolよりも数桁遅いです!

私が書いた簡単なテストケースは、volatile boolアプローチで完了するのに約1秒かかります。 std::atomic<bool>で、しかし、私は約10分間待ってあきらめました!

loadstorememory_order_relaxedフラグを使用して同じ効果を得ようとしました。

私のプラットフォーム:Windows 7 64ビットMinGW gcc 4.6.x

私が間違っているのは何ですか?

[〜#〜] upd [〜#〜]

はい、volatileは変数をスレッドセーフにしません。私の質問は、揮発性についてではなく、アトミックがとてつもなく遅い理由です。

PD2 @all、コメントありがとうございます-今夜、マシンに着いたら、すべての提案を試してみます。

34
user1773602

「Olaf Dietsche」のコード

 USE ATOMIC
 real   0m1.958s
 user   0m1.957s
 sys    0m0.000s

 USE VOLATILE
 real   0m1.966s
 user   0m1.953s
 sys    0m0.010s

GCC SMALLER 4.7を使用している場合

http://gcc.gnu.org/gcc-4.7/changes.html

C++ 11/C11メモリモデルを指定するアトミック操作のサポートが追加されました。これらの新しい__atomicルーチンは、既存の__sync組み込みルーチンを置き換えます。

アトミックサポートは、メモリブロックでも利用できます。メモリブロックがサポートされている整数型と同じサイズとアライメントである場合、ロックフリー命令が使用されます。ロックフリーをサポートしていないアトミック操作は、関数呼び出しとして残されます。ライブラリ関数のセットは、GCC atomic wikiの「External Atomics Library」セクションで利用できます。

そうそう..唯一の解決策はGCC 4.7にアップグレードすることです

31
KoKuToru

これに興味があるので、Ubuntu 12.04、AMD 2.3 GHz、gcc 4.6.3で自分でテストしました。

#if 1
#include <atomic>
std::atomic<bool> stop_(false);
#else
volatile bool stop_ = false;
#endif

int main(int argc, char **argv)
{
    long n = 1000000000;
    while (!stop_) {
        if (--n < 0)
            stop_ = true;
    }

    return 0;
}

g++ -g -std=c++0x -O3 a.cppでコンパイル

ただし、@ alegunaと同じ結論:

  • ちょうどbool

    実際の0m0.004s
    ユーザー0m0.000s
    sys 0m0.004s

  • volatile bool

    $ time ./a.out
    実際の0m1.413s
    ユーザー0m1.368s
    sys 0m0.008s

  • std::atomic<bool>

    $ time ./a.out
    実際の0m32.550s
    ユーザー0m32.466s
    sys 0m0.008s

  • std::atomic<int>

    $ time ./a.out
    実際の0m32.091s
    ユーザー0m31.958s
    sys 0m0.012s

12
Olaf Dietsche

私の推測では、これはハードウェアの質問です。 volatileを記述するとき、変数について何も想定しないようコンパイラーに指示しますが、私が理解しているように、ハードウェアはそれを通常の変数として扱います。これは、変数が常にキャッシュにあることを意味します。アトミックを使用する場合、特別なハードウェア命令を使用します。これは、変数が使用されるたびにメインメモリからフェッチされることを意味する可能性があります。タイミングの違いは、この説明と一致しています。

2
Olle Lindeberg