0

通常は 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% 低下しています。これは 1 秒間に約 100 万回呼び出され、8 つのスレッド間で共有されます (モンテカルロ シミュレーションのサンプル カウンター)。

ありがとう!

4

2 に答える 2

1

もちろん、これはアトミックではありません。アトミック操作のシーケンスを中断できます。保護 (ミューテックスまたはクリティカル セクション) を使用することをお勧めします。

于 2013-03-19T11:25:47.610 に答える
1

これは全体的にアトミックではありません。次の例を参照してください。

  • hi=0,lo=INT_MAX
  • T1 コールvalue()、取得lo=INT_MAX、中断
  • T2 コールはincrement()hi を 1 にインクリメントします
  • T1 が再開して を読み取りcounterHi、1 を取得し、2^32 + INT_MAX の値を返します。

これはおそらくあなたが望むものではありません。サンプル スペースを分割して、各スレッドがロックを競合することなく n/8 項目を計算できるようにすることはできませんか?

于 2013-03-19T11:17:50.053 に答える