私のプログラムには、プロセスで開始され、プログラムが終了するまで残るスレッドがいくつかあります。これらのスレッドは、アプリの存続期間中にさまざまな負荷に遭遇し、時にはすべてが 100% で実行されることもあります。
デフォルトでは、Linux スレッド スケジューラは、マルチコア システム上のこれらのスレッドのアフィニティを非常に軽率に変更すると思います。グラフィカル プロセス モニター (gnome のもの) でバウンスするグラフを見ると、これが何らかのオーバーヘッドを構成しているのではないかと思わずにはいられません。
編集:明確に言えば、非常に安定した負荷の場合でも、スレッドは異なるコアにスケジュールされ、提供された画像では見えなくても、各スレッドに選択されたコアが頻繁に「スワップ」されることが非常に明白です。
この親和性の絶え間ない変化はパフォーマンスに悪影響を与えませんか?
では、なぜこのように実装されているのでしょうか? アフィニティを変更するとどのような利点があるのでしょうか?
私の推測は次のとおりです:
- ウェアレベリング - 1つのコアにすべての作業を集中させない
- 意図的ではない - 何らかのスマート アルゴリズムが負荷に応じて使用を最適化しようとしますが、オーバーヘッドがそれほど大きくないため、アフィニティを変更するよりもアフィニティを維持する方がよい場合があります。
答え1
すべてのスレッドを 1 つのコアで実行する場合には、1 つのコアを搭載した安価なハードウェアを購入してください。
スケジューラは、すべてのコアを最大限に活用しようとします。つまり、空き時間があるコアにスレッドをディスパッチするということです。スレッドをあるコアから別のコアに移動するとコストが少しかかるため、スケジューラはこれを回避しようとします。ただし、コアをアイドル状態にしないことの利点は、スレッドを移行するコストよりもはるかに大きいため、通常はそれほど気になりません。これは、スレッドがコア ローカル キャッシュよりも多くのメモリを使用する場合に特に当てはまります。スレッドが使用するメモリがコア ローカル キャッシュにない場合、別のコアに移行しても失われるものはほとんどありません。
Linux のような産業グレードのスケジューラを推測すると、通常はパフォーマンスが低下します。
示されたグラフは、さまざまなコアの負荷が最大ではなく、わずかに変動していることを示しています。これは、システム全体が CPU パワーではなく、現在実行中のタスクの I/O によって制限されているためと考えられます。スレッドが 1 つのコアから別のコアに移動する頻度については、何ら言及されていません。
答え2
ここで提供されるスナップショットは、カーネルのタイプ (バージョン) にも依存します。バージョン 2.4 の古いカーネルは親和性が低く、スレッドのピンポン動作が頻繁に発生してシステムのパフォーマンスに影響を及ぼしていました。カーネル バージョン 2.5 以降は親和性が比較的優れています。
マルチコア ベースのシステムでは、アフィニティを設定すると、コア間でスレッドを移動する際にキャッシュの無効化が発生するのを回避し、パフォーマンスを向上させることができます。
Linux ベースのマルチコア システムの場合、プロセスの場合は sched_setaffinity/taskset、スレッドの場合は pthread_setaffinity_np を使用して、アプリケーション/要件のタイプに基づいてスケジューラのアフィニティ動作 (自然アフィニティ) をオーバーライドできます。
カーネルシャークマルチコア システムとアフィニティの視覚的表現が改善されているようです。
また、hトップアフィニティを設定するための視覚的なサポートを提供します (スケジューラをオーバーライドするため)。