0

ミューテックスのさまざまなバリアントを試したところ、ついに2つの最速のプリミティブに到達しました。

1つはInterlockedExchangeベース(よく知られた方法)です

Access:
  while InterlockedExchange(AccessFlag, 1) <> 0 do
Release:
  InterlockedExchange(AccessFlag, 0)

もう1つはイベントベースです。

Init:
  Event = CreateEvent(Null, false, true, Null);
Access:
  WaitForSingleObject(Event, INFINITE)
Release:
  SetEvent(Event)

InterlockedExchangedベースは常に最速でしたが、障害が発生した場合にスリープ状態にならないという問題がありました。一方、単一の物理プロセッサ(コア)または複数のコアのいずれかで大きく機能しました。シングルコアテストの小さな利点は、ループ内にSleep(0)を追加しても失敗がなかったことです。

イベントベースはスリープ中の待機に最適ですが、パフォーマンスを測定したところ、このタイプのミューテックスで動作するいくつかのスレッドは、単一の物理プロセッサ上にある場合(SetThreadAffinityMaskが同じ値で呼び出されるか、単一のコアコンピュータ)異なるプロセッサよりも。プロセッサーのタイプに応じて、これはx4(iCore 5)からx8(Xeon)まで変化しました。

Xeonからのいくつかの統計

3スレッド、それぞれが変数を10(10,000,000ステップ)ずつ増加させ、増加するたびにミューテックスを使用して変数にアクセスします。

  • マルチプロセッサ、InterlockedExcchangeベース

    344ミリ秒/Msあたり:87,209 / whileループの失敗:2,487,376(3スレッドからの合計ステップの8%、Sleep(0)は存在しますが、マルチプロセッサスレッドではおそらく役に立たない)

  • マルチプロセッサ、イベントベース

    6187ミリ秒/Msあたり:4,848

  • シングルプロセッサ、InterlockedExcchangeベース

    281ミリ秒/Msあたり:106,761 / whileループの失敗:0(ループ内のSleep(0));

  • シングルプロセッサ、イベントベース

    765ミリ秒/Msあたり:39,215

実際のコア間同期にはある程度のペナルティがあると思います。しかし、私は、InterlockedExchangeメソッドの完璧なパフォーマンスを、イベントベースのアプローチの正確さ(「作業しない場合はスリープ」)と「結び付け」たいと思います。これは可能ですか?

4

1 に答える 1

1

これを行う一般的な方法の 1 つは、試行回数を制限して CAS ステップをスピンすることだと思います。条件が適時に真にならない場合は、「より高価な」イベント ベースのソリューションのオーバーヘッドが発生します。

于 2012-12-24T08:35:50.593 に答える