負荷分散シナリオの詳細な分析

この記事に登場するカーネル コードは Linux5.4.28 のものですが、長さを減らすためにコードの引用は避けていますので、興味のある方はコードと合わせてこの記事も読んでみてください。

1. 負荷分散方法はいくつありますか?

Linux にはいくつかの種類のロード バランサがあります。

実は、カーネル ロード バランサーには 2 種類あり (この記事では特に CFS タスクについて言及しています)、1 つはビジーな CPU 用に用意された定期バランサーで、ビジーな CPU 上の CFS タスクのバランスをとるために使用されます。アイドル状態の CPU にはアイドル バランサも用意されており、ビジー状態の CPU とアイドル状態の CPU のタスクのバランスをとるために使用されます。アイドルバランサにはnohzアイドルバランサと新型アイドルバランサの2種類があります。

定期的なロード バランス (定期的なロード バランスまたはティック ロード バランス) とは、ティック中にシステムのロード バランシング ステータスを定期的に検出し、システム内で最も負荷の高いドメイン、グループ、CPU を見つけて、それらで実行可能なタスクをプルすることを指します。システム負荷をバランスのとれた状態に保つために使用されます。定期的な負荷分散は、ビジーな CPU 間でのみ分散できます。システム内のアイドル状態の CPU を「ドライ」にしたい場合は、アイドル状態の負荷分散を使用する必要があります。

NOHZ ロード バランスとは、他の CPU がアイドル状態になり、現在の CPU タスクが重すぎることを意味します。ロード バランシングのために ipi を通じて他のアイドル状態の CPU をウェイクアップする必要があります。なぜ NOHZ ロードバランスと呼ばれるのでしょうか? これは、このバランサーがカーネルが NOHZ (つまりティックレス モード) で構成されている場合にのみ有効になるためです。CPU がアイドル状態になった後も定期的なティックを維持している場合は、ティック ロード バランスを通じてロード バランシングを完了でき、アイドル状態の CPU をウェイクアップするために IPI は必要ありません。定期的なバランシングと同様に、NOHZ アイドル ロード バランスもビジー CPU のティックによって駆動されます。キック アイドル ロード バランサーが必要な場合は、GIC を介して選択されたアイドル CPU に ipi 割り込みが送信され、システム内のすべてのアイドル CPU を表すことができます。 . 負荷分散を実行します。

新しいアイドル ロード バランスは理解しやすく、CPU 上でタスクの実行がなく、アイドル状態に入ろうとしているときに、他の CPU が助けを必要としているかどうかを確認し、常にビジー状態の CPU からタスクをプルして負荷を維持することを意味します。システム全体がバランスのとれた状態になります。NOHZ ロード バランスにはシステム内のすべてのアイドル状態の CPU が関係しますが、新しいアイドル ロード バランスはアイドル状態に移行しようとしている CPU のみに関係します。

 

2. 定期的な負荷分散の一般的なプロセスは何ですか?

ティックが到着すると、scheduler_tick 関数で trigger_load_balance が呼び出され、定期的なロード バランシングがトリガーされます。関連するコードは次のとおりです。

コード全体は非常に単純です。主なロジックは、raise_softirq を呼び出して SCHED_SOFTIRQ をトリガーすることです。もちろん、等化間隔の要件を満たしている必要があります (詳細は後述)。nohz_balancer_kick は、nohz アイドル バランスをトリガーするために使用されます。これについては、次の 2 つの章で詳しく説明します。上の図では、関数のコメントを特別に残しておきましたが、この関数は周期バランスをトリガーするだけでなく、nohz アイドルバランスもトリガーするため、ここのコメントは間違っているようです。ただし、実際には、nohz アイドル バランスは本質的に、別の意味での定期的なロード バランシングです。CPU がアイドル状態になり、ティックを生成できないため、ティックを生成できるビジーな CPU がティック バランスのトリガーを支援するために使用されます。実際には、ティック バランスと nohz アイドル バランスは SCHED_SOFTIRQ のソフト割り込みを通じて処理され、最後に run_rebalance_domains 関数が実行されます。

3. 周波数アイドルバランスプロセス全体とは何ですか?

この問題は次の 2 つの質問に分類できます。

1) システム内に複数のアイドル CPU がありますが、周波数アイドル バランスを実行する CPU を選択するにはどうすればよいですか?

2) アイドル状態の CPU に通知する方法と、覚醒した CPU のバランスを取る方法は?

消費電力を考慮しない場合は、アイドル状態のすべての CPU から 1 つを選択すれば問題ありませんが、ヘテロジニアスなシステム (携帯電話環境など) では、さらに考慮する必要があります。例: ビッグコア CPU とスモールコア CPU の両方がアイドル状態にある場合、ビッグコア CPU とスモールコア CPU のどちらをウェイクアップするかを選択しますか? ラージコア CPU は強力な演算能力を備えていますが、消費電力も高くなります。小さなコアを選択した場合、消費電力は節約できますが、提供される計算能力は十分ですか? さらに、アイドルバランス要求を開始する CPU はどのクラスターにありますか? 同じクラスタの CPU が nohz アイドル バランスを実行するのに優先されますか? CPU アイドル状態の深さはどれくらいですか? 考慮すべき点はたくさんありますが、この記事では詳しく説明しません。結局のところ、標準的なカーネル選択の最も単純なアルゴリズムは、アイドル状態の CPU (つまり、アイドル状態の CPU マスクの最初の CPU) をランダムに選択することです。

周波数アイドルバランスを開始する CPU をキッカーと定義し、バランス操作を実行するリクエストを受け取る CPU をキッカーと呼びます。キッカーとキックキーのやり取りは次のようになります。

1) Kicker は、kickee CPU runqueue の nohz_flags メンバーを設定することによって、nohz アイドル バランスを実行するように選択されたことをkickee に通知します。

2) ipiを送信してkickeeを起動します

3) Kickee は割り込みによって起動され、scheduler_ipi を実行して ipi 割り込みを処理します。runqueue の nohz_flags メンバーが設定されていることがわかると、選択されたことがわかります。その後のプロセスは実際には定期的なバランシングと同じであり、SCHED_SOFTIRQ タイプのソフト割り込みをトリガーします。

もう一度強調しましょう: キックされたアイドル状態の CPU は、他のビジー状態の CPU 上のタスクをこの CPU にプルする責任はありません。キックされる側は、すべてのアイドル状態の CPU の負荷を再バランスすることです (ティックは停止します)。選択されたアイドル状態の CPU は、システム内のすべてのアイドル状態の CPU の代表にすぎません。システム内のビジー状態の CPU のタスクをシステム内のすべてのアイドル状態の CPU に分散させるために起動されます。さらに、上記のステップ 1 では、複数のキッカーが同時にキッキーを選択する可能性があるため、操作の繰り返しを避けるために、保留中のリクエストをここで検出する必要があります。具体的なコードについては、nohz_balancer_kick 関数を参照してください。

SCHED_SOFTIRQ ソフト割り込みの処理機能は次のとおりです。

周波数アイドル バランスと定期的な負荷バランスはどちらも SCHED_SOFTIRQ タイプのソフト割り込みを通じて完了します。つまり、どちらも SCHED_SOFTIRQ に登録されたハンドラー関数 run_rebalance_domains を通じて機能を完了します。その後、周波数アイドル バランスを実行するように CPU が選択された場合、同時に、 、ダニも到着するので、どうするか?このとき、スケジューラは nohz アイドル バランスを優先します。結局のところ、nohz アイドル バランスはグローバルな問題 (システム内のすべてのアイドル CPU のバランスを表す) ですが、定期的なロード バランスは各段階で独自のスケジュール ドメインのバランスを取るだけです。

4. NOHZ アイドル ロード バランスを実行するには、どのような状況でアイドル CPU をウェイクアップする必要がありますか?

アクティブな CPU では、ティックが定期的に到着します。CPU のティックで NOHZ ロード バランスをトリガーする必要があるかどうかを確認します。明らかに、負荷の軽い CPU は「自立」することができ、他のアイドル状態の CPU の助けを必要としません。では、CPU 上の軽いタスクと重いタスクをどのように定義すればよいでしょうか? ということは、(消費電力の損失という)リスクを負って他のアイドル状態の CPU をウェイクアップする必要があるということでしょうか?主に次の点を考慮してください。

  • この CPU はアイドル状態であってはならず、その実行キュー内のタスクの数が 2 以上である (ロード バランスは主に実行可能なタスクを移行します。>=2 では、移行できるタスクが少なくとも 1 つあることが保証されます)。
  • システム内には、ティックレス モードのアイドル状態にある他の CPU があります。
  • NOHZ ロード バランスは、あまり頻繁にトリガーしないでください。これについては次の章で詳しく説明します。
  • この CPU ランキューには少なくとも 1 つの CFS タスクがあり、RT タスクまたは IRQ 処理で大量の CPU 計算能力が消費されます。cfs の実行に使用できる計算能力は大幅に減少します。このとき、他のアイドル状態の CPU も停止されます。助けるために必要だった。
  • 異種コンピューティング システムでは、現在の CPU に不適合タスクがあり、システム内により高い計算能力を持つアイドル状態の CPU が存在する場合、より高い計算能力を持つプロセッサが不適合タスクを引き継ぐことができるようにバランスも開始されます。スケジューラは、キャッシュ ヒット率の向上と比較して、タスクが計算能力に適した CPU を取得できることを期待します。

具体的なコードについては、nohz_balancer_kick 関数を参照してください。

5. 周波数アイドルバランスをトリガーする頻度を制御するにはどうすればよいですか?

周波数アイドル バランスは本質的にティック バランスですが、IPI を送信してアイドル状態の CPU をウェイクアップするため、追加のオーバーヘッドが発生するため、周波数アイドル バランスをトリガーする頻度を制御する必要があります。nohz アイドル バランスのトリガーの制御を容易にするために、スケジューラは次のデータ構造を持つ nohz グローバル変数を定義します。

2 つのメンバー nr_cpus と idle_cpus_mask を使用すると、スケジューラは現在のシステム アイドル CPU の状況を理解し、nohz アイドル バランスを実行するために適切な CPU を選択できます。アイドル状態の CPU がキックされた場合、ロード バランシングが必ずしも完了するとは限らず、システム内の CPU 負荷を現在のステータスと一致させるために、ブロックされた負荷を更新する必要がある場合があります。この部分はこの記事の内容ではないため、詳細は説明しません。next_balance は、nohz アイドル バランスがトリガーされる時点を制御するために使用されます。この時点は、システム内のすべてのアイドル CPU の rq->next_balance に関連する必要があります。言い換えれば、システム内のすべてのアイドル CPU がトリガーされる必要がない場合は、バランスが取れている場合、バランスを取る必要はまったくありません。nohz アイドル バランスをトリガーする必要はありません。したがって、nohz アイドル バランスを実行するとき、スケジューラは実際にアイドル状態の CPU を走査して、最小の rq->next_balance (つまり、 、最近バランスを取る必要があるもの)を選択し、それを nohz.next_balance に割り当てます。

nohz アイドル バランスの具体的な実行は非常に簡単で、システム内のすべてのアイドル状態の CPU を横断し、rebalance_domains を呼び出して、CPU の各レベルでスケジュールされたドメインの負荷分散を完了します。特定のコードについては、nohz_idle_balance 関数を参照してください。

 Information Direct: Linux カーネル ソース コード テクノロジ学習ルート + ビデオ チュートリアル カーネル ソース コード

Learning Express: Linux カーネル ソース コード メモリ チューニング ファイル システム プロセス管理 デバイス ドライバー/ネットワーク プロトコル スタック

6. 新しいアイドル状態の負荷分散を行う場合、どのような要素を考慮する必要がありますか?

現在、スケジューラーは、新しいアイドル状態の負荷分散を行うときに主に 2 つの要素、つまり現在の CPU のキャッシュ状態とマシン全体の現在の負荷状態を考慮します。CPU の平均アイドル時間が非常に短い場合、CPU がタスクの実行に戻っても、CPU キャッシュはまだホットです。タスクが他の CPU からプルされると、これらの新しいタスクは他のタスクのキャッシュを破壊するため、影響が及びます。従来のタスクのパフォーマンスは向上しますが、消費電力も増加します。マシン全体の負荷の影響は、ルート ドメインのオーバーロード メンバーに記録されます。いわゆるオーバーロードとは、次の条件が満たされることを意味します。

  • 実行可能なタスクが 1 つ以上あります。つまり、CPU 上で実行を待機しているタスクがあります。
  • 実行中のタスクは 1 つだけですが、不適合なタスクです

上記の条件が満たされる場合、その CPU を過負荷状態と呼び、システム内の少なくとも 1 つの CPU が過負荷状態にある場合、システムは過負荷状態であると見なされます。システムが過負荷になっていない場合は、新たにアイドル状態の負荷分散を行う必要はありません。

上記の決定は CPU の観点から行われるため、新しいアイドルバランスの数が減少します。さらに、スケジューラは、sched ドメインの観点からもチェックし、無効な新しいアイドルバランスの数をさらに回避します。まず第一に、明確にする必要があります: 新しいアイドル状態のロード バランスを行うにはオーバーヘッドが発生します。私たちはビジー状態の CPU を見つけて、その実行キューからタスクをプルするために懸命に努力しました。しかし、実際にはそれほどアイドル状態ではない場合、タスクは独自の実行キューに配置されるため、バランスをとるために使用される CPU 時間は実際には無駄になります。この恥ずかしい状況を回避するにはどうすればよいでしょうか? 2 つのデータが必要です。1 つは現在の CPU の平均アイドル時間、もう 1 つは新しいアイドル ロード バランス (max_newidle_lb_cost メンバー) で導入されたオーバーヘッドです。CPU の平均アイドル時間が max_newidle_lb_cost + このバランシングのコストより小さい場合、バランシングは開始されません。

CPU の無効化を制御し、新しいアイドル ロード バランスに入るために、runqueue データ構造には次のメンバーが含まれています。

avg_idle を計算するアルゴリズムは次のように非常に単純です。

nohz アイドル バランスと同様に、新しいアイドル バランスは負荷分散を処理するだけでなく、ブロックされた負荷更新も処理します。条件が満たされず、CPU のバランスを取る必要がない場合は、アイドル状態に入る前に、システム内のアイドル状態の CPU のブロックされた負荷を更新する必要があるかどうかを確認する必要があります。更新する必要がある場合は、CPU が実行されます。ブロックされたロード。更新をロードします。その背後にあるロジックは、nohz アイドル バランス プロセス中に負荷更新のためにアイドル状態の CPU を調べて選択するのではなく、アイドル状態に移行しようとしている CPU に負荷更新を処理させる方が良いということです。特定のコードについては、newidle_balance 関数を参照してください。

7. スケジュールされたドメインの場合、負荷分散を実行する頻度はどれくらいが適切ですか?

ロード バランシングの実行頻度は、実際には、レイテンシーとオーバーヘッドのバランスによって決まります。スケジュールされたドメインの異なるレベルでの負荷分散によって生じるオーバーヘッドは異なります。モバイル プラットフォームでは、MC ドメインはクラスタ間でバランスが取れており、パフォーマンスへの影響は少なくなります。ただし、DIE ドメインでバランスをとるには、クラスター間でタスクを移行する必要があり、これはパフォーマンスと消費電力に大きな影響を与えます (キャッシュ ヒット率や、元のディープ スリープ ラージ コア CPU へのタスクの移行など)。したがって、バランシングを実行する時間間隔はドメイン レベルに関連する必要があります。また、負荷状況もバランシング時間間隔に影響します。各 CPU の負荷が比較的重い場合は、バランシング時間間隔を長くすることができます。結局のところ、誰もが忙しいのです。しばらく弾を飛ばしてから実行してください。バランスが取れてからでも遅くはありません。

struct sched_domain とバランシングに関連するデータ メンバーには次のものがあります。

4+4 携帯電話プラットフォームの場合、MC ドメインでは、スモール コア クラスタとラージ コア クラスタの両方の min_interval は 4 ミリ秒、max_interval は 8 ミリ秒に等しくなります。DIE ドメイン レベルでは、CPU の数が 8 であるため、min_interval は 8ms、max_interval は 16ms に等しくなります。実際のバランス間隔は、balance_intervalで定義され、スケジュールされたドメインの不均衡度に応じて常に変化する値です。通常、初期値は min_interval から始まり、不均衡状況が改善するにつれて、balance_interval が徐々に大きくなり、max_interval まで平衡間隔が大きくなります。

8. 結論

定期的なバランシングと nohz アイドル バランスはどちらも SCHED タイプのソフト割り込みによってトリガーされます。最後に、rebalance_domains が呼び出され、CPU の各レベルでスケジュール ドメインのバランシングを実行します。特定のスケジュール ドメインでバランシングを実行する特定の関数は、load_balance 関数です。新しいアイドル ロード バランスの場合、CPU 上の各レベルのスケジュール ドメインも走査されてバランス アクションが実行され、呼び出される関数は依然としてload_balance です。したがって、どのようなバランスであっても、最終的にはすべてがload_balanceになります。この記事では紙面の都合上、load_balance のロジックについては詳しく分析しませんので、詳しく知りたい場合は次の章を聞いてください。

原作者:カーネル職人

 

おすすめ

転載: blog.csdn.net/youzhangjing_/article/details/132511625