ミューテックスのさまざまなバリアントを試したところ、ついに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メソッドの完璧なパフォーマンスを、イベントベースのアプローチの正確さ(「作業しない場合はスリープ」)と「結び付け」たいと思います。これは可能ですか?