競合の有無にかかわらず、ロックと比較してアトミック/インターロック変数はどのくらい高速ですか?

たまたま、低レベルの速度テストがたくさんあります。ただし、速度が正確に何を意味するのかは、正確に何をしているかに大きく依存するため (操作自体とは関係なくても)、非常に不確実です。

以下は、AMD 64 ビット Phenom II X6 3.2Ghz の数値です。私は Intel チップでもこれを実行しましたが、時間は大きく異なります (これも、正確に何を行っているかによって異なります)。

GCC __sync_fetch_and_add は、完全に隔離されたアトミックな追加であり、平均 16ns、最小時間 4ns です。最小時間の方がおそらく真実に近いでしょう (ただし、それでも多少のオーバーヘッドはあります)。

競合していない pthread ミューテックス (boost による) は 14ns (最小値でもあります) です。他の何かがミューテックスをロックしている場合、実際には時間は増加しますが、現在競合していないわけではないため、これも少し短すぎることに注意してください (キャッシュ同期が発生するため)。

失敗した try_lock は 9ns です。

x86_64ではこれは単なる通常の交換操作であるため、私は単純な古いatomic incを持っていません。可能な最小時間に近い可能性が高いため、1 ~ 2ns です。

条件変数で待機なしで通知を呼び出すと、25 ns です (何かが約 304 ns 待機している場合)。

ただし、すべてのロックは特定の CPU 順序保証を引き起こすため、変更したメモリの量 (ストア バッファに収まるものは何でも) によって、そのような操作にかかる時間が変わります。そして明らかに、最悪の時期であるミューテックスで競合が発生した場合。実際にスレッドの切り替えが発生しない場合でも、Linux カーネルへの復帰には数百ナノ秒かかる場合があります。これは通常、アトミックロックがカーネル呼び出しをまったく含まないため、パフォーマンスが優れている場所です。平均的なケースのパフォーマンスは、最悪のケースでもあります。待機中のスレッドがある場合、Mutex のロック解除でもオーバーヘッドが発生しますが、アトミックでは発生しません。

注:このような測定を行うと問題が発生するため、結果は常に疑わしいものになります。私のテストでは、CPU 速度を固定し、スレッドの CPU アフィニティを設定し、他のプロセスを実行せず、大きな結果セットを平均することで、変動を最小限に抑えようとしています。


さまざまなプラットフォームでこれを測定する目的で、GitHub にプロジェクトがあります。残念ながら、修士論文の後、これをフォローアップする時間がありませんでしたが、少なくとも基本的なコードはそこにあります.

__sync_fetch_and_add と比較して、pthread と OpenMP ロックを測定します。

私の記憶では、ロックとアトミック操作の間にはかなり大きな違いがあると予想していましたが (~1 桁)、実際の違いは非常に小さいことが判明しました。

ただし、現在私のシステムで測定すると、私の最初の推測を反映した結果が得られます。つまり、(pthreads または OpenMP が使用されているかどうかに関係なく) アトミック操作は約 5 倍高速であり、1 つのロックされたインクリメント操作には約 35ns かかります (これにはロックの取得が含まれます)。 、インクリメントを実行し、ロックを解除します)。


ロックの実装に依存し、システムにも依存します。アトミック変数は、ロックと同じ方法で実際に競合することはできません (取得-解放セマンティクスを使用している場合でも)。これがアトミック性の全体的なポイントです。ストアを伝播するためにバスをロックします (メモリに応じて)バリア モード) ですが、それは実装の詳細です。

ただし、ほとんどのユーザー モード ロックはラップされたアトミック op です。x86 および x64 でのアトミック op を使用した高性能でスケーラブルなロックに関する数値については、Intel のこの記事を参照してください (Windows の CriticalSection との比較)。 残念ながら、SWR ロックの統計は見つかりませんが、常に自分のシステム/環境のプロファイルを作成する必要があります)。