1. ホーム
  2. multithreading

[解決済み] ロックされていないミューテックスをロックすることは、どの程度効率的ですか?ミューテックスのコストは?

2022-05-05 14:10:12

質問

低レベル言語(C、C++、その他)で。低レベル言語(C++など)では、(pthreadやネイティブシステムライブラリが提供するような)たくさんのミューテックスを持つか、オブジェクトに対して1つだけ持つかのどちらかを選択する必要があるんだ。

ミューテックスをロックするのはどの程度効率的ですか?つまり、どれだけのアセンブラ命令があり、どれだけの時間がかかるか(ミューテックスがアンロックされた場合)?

ミューテックスのコストはどれくらいですか?本当にあっても問題ないのでしょうか? たくさん のミューテックスが必要ですか?それとも、私のコードに、私が持っているのと同じくらい多くのミューテックス変数を放り込めばいいのでしょうか? int というような変数があり、それは本当に重要ではないのでしょうか?

(ハードによってどの程度の違いがあるのか分かりませんが)。もしあれば、それも知りたいです。しかし、私は一般的なハードウェアに興味があるのです)

要は、オブジェクト全体をカバーする単一のミューテックスではなく、オブジェクトの一部だけをカバーする多数のミューテックスを使用することで、多くのブロックを安全にすることができるのです。そして、私はこのことについてどこまでやるべきか悩んでいます。つまり、どれだけ複雑で、どれだけ多くのミューテックスを必要とするとしても、本当に可能な限りあらゆるブロックを安全にしようとすべきなのでしょうか?


ロックに関するWebKitsのブログ記事(2016年)です。 はこの質問と非常に関係があり、スピンロック、アダプティブロック、フーテックスなどの違いについて説明しています。

どのように解決するのですか?

<ブロッククオート

私は、たくさんのミューテックスを持つか、1つのオブジェクトに1つのミューテックスを持つかのどちらかを選択しなければなりません。

もし多くのスレッドがあり、オブジェクトへのアクセスが頻繁に起こるのであれば、複数のロックがあれば並列性が高まります。ロックが増えるということは、ロックのデバッグが増えるということですから、保守性は犠牲になります。

ミューテックスをロックすることは、どの程度効率的ですか?つまり、どれだけのアセンブラ命令がありそうで、どれだけの時間がかかるか(ミューテックスがアンロックされた場合)?

正確なアセンブラ命令は、最もオーバーヘッドの少ない ミューテックス - メモリ/キャッシュのコヒーレンシー 保証が主なオーバーヘッドとなります。そして、特定のロックがかかる頻度が少ないほど良いのです。

ミューテックスは大きく分けて2つの部分から構成されています(簡略化しすぎ)。(1) ロックされているかどうかを示すフラグと、(2) 待ち行列です。

フラグの変更はわずか数命令で、通常はシステムコールなしで行われます。もしミューテックスがロックされていれば、システムコールが呼び出したスレッドを待ち行列に追加し、待ち時間を開始します。待ち行列が空の場合、ロックを解除するのは簡単ですが、待ち行列の一つを呼び出すためにシステムコールが必要です。(システムによっては、安価で高速なシステムコールがミューテックスの実装に使用され、競合が発生した場合にのみ低速な(通常の)システムコールになります)。

ロックされていないMutexをロックするのは本当に安上がりです。無競争でロック解除するのも安い。

<ブロッククオート

ミューテックスのコストはどれくらいですか?本当にたくさんのmutexを持つことは問題なのでしょうか?それとも、int変数と同じだけmutex変数をコードに放り込めば、本当に問題ないのでしょうか?

あなたのコードに好きなだけmutex変数を投入することができます。アプリケーションが割り当てることのできるメモリの量によってのみ制限されます。

まとめ ユーザースペースのロック(特にミューテックス)は安価で、システムの制限を受けません。しかし、その数が多すぎると、デバッグには悪夢となる。簡単な表です。

  1. ロックが少ないと競合が多くなり(遅いシステムコール、CPUストール)、並列性が低くなる
  2. ロックが少ないということは、マルチスレッドの問題のデバッグに問題がないことを意味します。
  3. ロックが多いほど、競合が少なく、並列度が高くなる
  4. ロックが多いほど、デットロックが発生する可能性が高くなります。

アプリケーションのためのバランスの取れたロックスキームを見つけ、維持する必要があります。一般的に、#2 と#3 のバランスを取る必要があります。


(*) ロックされる頻度が低いミューテックスの問題は、アプリケーションでロックが多すぎる場合、キャッシュコヒーレンシーを保証するために他のCPUのデータキャッシュからミューテックスメモリをフラッシュするために、CPU/コア間のトラフィックが多くなることです。キャッシュのフラッシュは軽量な割り込みのようなもので、CPU によって透過的に処理されますが、いわゆる 客席 ("stall"で検索してください)。

そして失速は、ロックコードの実行を遅くするもので、多くの場合、アプリケーションが遅い理由を明らかにすることなく実行されます。(CPU/コア間トラフィックの統計情報を提供するアーキテクチャもありますが、そうでないものもあります)。

この問題を回避するため、一般に多くのロックを使用し、ロック競合の確率を下げ、失速を回避することができます。これが、システムの制限を受けない安価なユーザ空間ロックが存在する理由です。