golang-GMP モデル

参考:https://blog.csdn.net/xmcy001122/article/details/119392934

意味

G:ゴルーチンの略称。

M:ワーカースレッド(OSスレッド)はマシンとも呼ばれます。

P: プロセッサー (スケジューラー)。GOMAXPROCS によって変更できます。M が Go コードを実行すると、最初に P に関連付けられます。

Go では、スレッドはゴルーチンを実行するエンティティであり、スケジューラの機能は、実行可能なゴルーチンをワーカー スレッドに割り当てることです。

ここに画像の説明を挿入
グローバル キュー (グローバル キュー): 実行を待機している G を格納します。

P のローカル キュー: グローバル キューと同様に、実行を待機している G も格納されます。格納される数は制限されており、最大 256 です。新しい G' を作成すると、最初に G' が P のローカル キューに追加され、キューがいっぱいになると、ローカル キュー内の G の半分がグローバル キューに移動されます

P リスト: すべての P はプログラムの開始時に作成され、GOMAXPROCS (構成可能) までの配列に保存されます。

M: スレッドがタスクを実行したい場合は、P を取得し、P のローカル キューから G を取得する必要があります。P キューが空の場合、M はグローバル キューから G のバッチを取得して、それを P のキューに入れようとします。ローカルキュー、または他の P のローカルキューから半分を盗んで P のローカルキューに置きますM は G を実行し、G が実行された後、M は P から次の G を取得し、繰り返します。

PとMはいつ作成されますか

1. P をいつ作成するか: P の最大数 n を決定した後、ランタイム システムはこの数に従って n P を作成します。
2. M が作成されるとき: P を関連付けてその中で実行可能な G を実行するのに十分な M がありません。たとえば、この時点ですべての M がブロックされており、P にまだ多くの準備完了タスクがある場合、アイドル状態の M を探し、アイドル状態の M が存在しない場合は、新しい M を作成します。

スケジューラーの設計戦略

スレッドの多重化: スレッドの頻繁な作成と破棄を避け、スレッドを再利用します。

1)仕事盗みの仕組み

このスレッドに実行可能な G がない場合、スレッドを破棄する代わりに、他のスレッドによってバインドされている P から G を盗もうとします。

2)ハンドオフ機構

このスレッドがシステム コールを実行するか、 G が原因でブロックすると、スレッドはバインドされた P を解放し、実行のために P を他のアイドル スレッドに転送します (または新しいスレッドを作成します)。

並列処理の使用: GOMAXPROCS は P の数を設定し、最大で GOMAXPROCS スレッドが分散され、複数の CPU 上で同時に実行されます。GOMAXPROCS は同時実行の程度も制限します (GOMAXPROCS = コア数/2 など)。この場合、最大でも CPU コアの半分が並列処理に使用されます。

プリエンプション: コルーチンでは、次のコルーチンを実行する前に、コルーチンが自発的に CPU を放棄するまで待つ必要があります。Go では、他のゴルーチンが餓死するのを防ぐために、ゴルーチンは CPU の最大 10 ミリ秒を占有します。ゴルーチンとコルーチンの違いです。

グローバル G キュー: 新しいスケジューラにもグローバル G キューは残っていますが、機能が弱体化されており、M がワークスチールを実行し、他の P から G を盗むことができない場合、グローバル G キューから G を取得できます

Go 実行ライフサイクル

ここに画像の説明を挿入

Go ライフサイクルには、M0G0という 2 つの非常に重要な概念があります。

M0の紹介

M0の特徴をいくつかご紹介します。

プロセス開始後は0番、つまりプロセス数と一致する番号が付けられたメインスレッドであり、世界で唯一のものでもあります。

グローバル変数に配置されるため、head 経由で割り当てる必要はありません。

その主な機能は、メインのゴルーチンである最初のゴルーチンを初期化して実行することです。

メインの起動が完了すると、他のスレッドと同じになり、リソースを確保する必要があります

G0の紹介

M が開始されるたびに、それに応じてゴルーチン、つまり G0 が作成されます。G0 は独立しています。つまり、各スレッドの作成により確実に G0 が作成されます。つまり、各 M は独自の G0 を持ちます

同様に、そのストレージもグローバル変数にあります

その主な機能は、他のゴルーチンをスケジュールすることです。つまり、G を M にスケジュールする際に P が実行するプロセスは、実際には G0 によって完了されます。

おすすめ

転載: blog.csdn.net/weixin_44866921/article/details/130305872