2

10,000 個の同時タスクの完了を追跡する int の配列があります。値は 1 または 0 です。この配列が Bit の配列であり、各同時スレッドが interlocked.CompareExchange (または同様のもの) を使用すると、より効率的だと思います。 ) 単一のビットを変更します。

Interlocked に「ビット」のオーバーロードがない場合、これにどのようにアプローチすればよいですか?

4

4 に答える 4

3

ループ内でそれを偽造することはできますがInterlocked.CompareExchange(ref int, int, int)、より効率的だとは思いません:

private static void SetBit(ref int valueToUpdate, int bitToSet)
{
   while (true)
   {
      int oldValue = valueToUpdate;
      int newValue = oldValue | bitToSet;
      int result = Interlocked.CompareExchange(ref valueToUpdate, newValue, oldValue);
      if (result == oldValue) break;
   }
}
于 2012-11-27T14:25:45.280 に答える
1

を使用してビットでそれを行うことはできないと思いますInterlockedints各ビットが独自の 内にあるように、 の配列に切り替える必要があると思いますint

Interlocked.CompareExchangeint等しいかどうかのみを比較しますが、ビットへの他の変更を保護するために他の同時実行戦略を使用しない限り、実行できないビットの1つだけを比較する必要がありintます。

于 2012-11-27T14:21:07.957 に答える
1

並行タスクの完了を追跡するには、スレッドセーフな構造が必要です。したがって、インターロックされたコンストラクトは常にロックよりも高速です (ロックを必要としないため) 。 -classの静的メソッドを整数で使用する必要があります (たとえば、0 に相当し 1 に相当します)。Interlockedfalsetrue

Jeffrey Richter は、彼の著書「C# による CLR」の第 28 章「プリミティブ スレッド同期コンストラクト」で説明していることと同じことを行います。彼は、彼の Wintellect.PowerThreading ライブラリにも Interlocked コンストラクトに基づく独自のロックの実装を紹介し、優れた説明と、彼自身の実装と .net フレームワークに含まれている実装の時間比較を提供しています。

于 2012-11-27T14:25:38.433 に答える
1

まず、いいえ、すべてのインターロック機能はメモリ アドレスで動作し、個々のビットはアドレス指定できません。

代わりに何をすべきか?

2 つのオプションを調査します。

  • 配列をまったく気にしないでください。単純なカウンターをInterlockedIncrement用意し、タスクが完了するたびにそれを行います。すべてのタスクが完了したかどうかを確認するには、値がまだ 10,000 に達しているかどうかを確認します。
  • または、(false) データ共有を最小限に抑えるために配列を使用します。しかし、それを密集させようとするべきではありません。反対方向に進みます。各エントリが個別の CPU キャッシュ ラインで終了することを確認して、並行して実行されているタスクが同じキャッシュ ラインをめぐって争わないようにします。(そして、タスクはすべて別々の場所に書き込むため、高価なインターロック操作で「完了」フラグを設定する必要さえありません。)

どれが一番速いかわかりません。パフォーマンスが重要な場合は、ベンチマークしてください。:)

于 2012-11-27T18:55:09.450 に答える