私は軽量プロセスを試してきました。デフォルトでは、複製機能が呼び出され、複製されたLWPに新しいPIDが割り当てられます。これは素晴らしい動作します。これにより、そのLWPのすべてのサブスレッドを識別できます。私が持っている小さな問題はパフォーマンスです。パフォーマンスが大幅に低下しました(処理速度が30%遅くなりました)。今私はLWPを予約し、優先順位を割り当てることが可能であることを読んでいます(私もそれを試みませんでした)。これはパフォーマンスに役立ちますか?
straceを実行したときに私が感じたことの1つは、Futexの使用量が8〜10倍爆発的に増加したことです。 LWPがこれの主な理由になるのでしょうか?理解できる部分はコンテキスト切り替えが爆発的に増加したものですが、LWPは同じメモリ空間を共有するため、Futexの使用によって爆発が起こらないと思います。
LWPを使用または使用することを決定する際に従うべきヒントやベストプラクティスはありますか?
パフォーマンスの観点からフォークする方が良いオプションですか、それとも悪いオプションですか?
ベストアンサー1
straceを実行したときに私が感じたことの1つは、Futexの使用量が8〜10倍爆発的に増加したことです。 LWPがこれの主な理由になるのでしょうか? [...]、しかしLWPは同じメモリ空間を共有するので、Futexの使用量は爆発的に増やすべきではありません。
はい、LWPを使用すると、おそらくFutexesの使用量が増えます。これは、実際には同じメモリを共有する異なるスレッドの同期という正確なケースを意味するためです。
Futexesは、共有メモリがあるときにすべてのロック操作の遅いパスに使用され、LWPまたはスレッドは、ロックがロック解除されたことを知らせるまでカーネルにブロックします。
クイックパスはアトミック操作を使用します(CPUはカウンタをアトミックに増加または減少させ、最初にロックされたか最後にロック解除されたかを検出できます)。したがって、高速パスでシステムコールを実行する必要はありません。
ロック競合が増加するということは、より多くのFutex操作が発生することを意味します。これは、システム呼び出し自体が原因であるだけでなく、Futexが呼び出されたときに一部のLWPまたはスレッドがリソースを待ち、スリープ状態にあることを意味するため、パフォーマンスに影響します。狂うことができます。
glibc のコードはマルチスレッドまたは LWP の使用を認識するため、コードに明示的なロックがない場合でもシステムライブラリにロックがあるため、ロック競合が発生し、次のようにプログラムが遅くなる可能性があります。 。
パフォーマンスが大幅に低下しました(処理速度が30%遅くなりました)。
メモリを共有するスレッドが多い場合のもう1つの要因は、おおよそのロックがあるいくつかのカーネルメモリ構造があり、ロック競合もある可能性があることです。
特にmmap_sem
、より多くのメモリ領域をプロセスにマッピングするたびに、書き込みのためにその領域をロックする必要があります。 (特にmalloc()
友達とより多くのメモリを割り当てる可能これをトリガーします。 )
今私はLWPを予約し、優先順位を割り当てることが可能であることを読んでいます(私もそれを試みませんでした)。これはパフォーマンスに役立ちますか?
たぶん...言うのは難しいです。ベンチマークする必要があります。
表示されているものがロック競合であり、コードパスを介して一般化(単一またはいくつかのLWPにローカライズされていない)されている場合、これは役に立ちません。
あなたはそれを使用することができますperf
ツールLinuxで一連のプロセスパフォーマンスを理解するのに役立ちます。ホットスポットを表示し、カーネルホットスポットが存在するかどうかを表示することもできます。
LWPを使用または使用することを決定する際に従うべきヒントやベストプラクティスはありますか?
LWPやスレッドの場合、多数を使用すると、malloc()
カーネルに関連する問題(メモリマップの拡張により潜在的な競合が発生するmmap_sem
)とユーザー空間の問題(単一スタジアムを使用するという意味)があるため、実装が非常に重要になります。スレッド(スペースを保存するにはロックする必要があります)。
多数のスレッドを使用する場合のパフォーマンスを向上させるために、いくつかの malloc ライブラリが作成されました。例えば、tcmallocまたはジャマルロック。これを採用するのは一般的に簡単であり(追加のライブラリにリンクするだけです)、実際にボトルネックが発生した場合にパフォーマンスが大幅に向上する可能性があります。いつものように、ベンチマークでこれが役立つことを確認してください。
パフォーマンスの観点からフォークする方が良いオプションですか、それとも悪いオプションですか?
おそらくより良いでしょう。話すのは難しいです。特定のケースでより良いことを確認するには、ベンチマークが必要です。
LWPと同様に、ベンチマークで実際に価値があることを確認する必要があります。
前述のように、LWPまたはスレッド間で共有メモリを使用すると(または同じメモリを共有するより多くのLWPまたはスレッドがある場合)、ロック競合の可能性が高くなります(直接明示的なロックがない場合でも、glibcとカーネルはこれを行います。 ) LWP 実際に速度が遅くなる可能性が高い。
私はマルチスレッドアプリケーションが遅すぎる状況を直接目撃しました。開発者は40スレッドの代わりに単一スレッドを使用するように変更しました。アプリケーションの速度が突然1,000%速くなりました。 90%の時間がロック競合に費やされることがわかりました!