今日の主役は、Go インタビューの汎用 GMP モデル質問の拡張質問 (質問)、つまり「GMP モデル、なぜ」です。 P はありますか? "
質問の背後にあるさらなる検討、実際、この面接の質問の本質は次のような質問です。「GMP モデル、なぜ G と M を直接結合できないのか」 ? 追加の P もあります。とても面倒です。なぜですか。どのような問題を解決しようとしているのですか?」
この記事では、Jianyu が GM と GMP の変更の理由を探ります。モデル。static void schedule(G *gp) { ... schedlock(); if(gp != nil) { ... switch(gp->status){ case Grunnable: case Gdead: // Shouldn't have been running! runtime·throw("bad gp->status in sched"); case Grunning: gp->status = Grunnable; gput(gp); break; } gp = nextgandunlock(); gp->readyonstop = 0; gp->status = Grunning; m->curg = gp; gp->m = m; ... runtime·gogo(&gp->sched, 0); }
schedlock
メソッドを呼び出して、グローバル ロックを取得します。 gput
メソッドを呼び出して、現在の Goroutine 実行ステータスやその他の情報を後で使用できるように保存します。 nextgandunlock
メソッドを呼び出して、次に実行可能な Goroutine を見つけ、他のスケジューラーが使用できるようにグローバル ロックを解放します。 runtime·gogo
メソッドを呼び出して、取得したばかりの次の実行対象ゴルーチンを実行し、次のスケジュール設定に入ります。 Go1.0.1 のスケジューラ ソース コードを分析すると、さらに興味深い点。それがスケジューラそのもの(scheduleメソッド)であり、通常の処理ではリターン、つまりメイン処理を終了することはありません。
彼はスケジューリング プロセスを継続的に実行します。GoroutineA が完了すると、GoroutineB の検索を開始します。B が見つかると、GoroutineB が見つかります。 A の完了したスケジューリング権が B に渡され、GoroutineB がスケジューリング、つまり実行を開始できるようになります。
もちろん、ブロックされている(Blocked)Gもあります。 G が何らかのシステム コールまたはネットワーク コールを行っていると、G はストールすることになります。この時点で、M (システム スレッド) はカーネル キューに戻され、新しいラウンドのウェイクアップを待ちます。
表面上、GM モデルは破壊できず、完璧であるように見えます。しかし、なぜ変更するのでしょうか?
2012 年に、Dmitry Vyukov は、「スケーラブルな Go スケジューラの設計ドキュメント」という記事を発表しましたが、これは今でも Go スケジューラに関する主要な研究記事の主な対象となっており、その記事で全体的な理由と考慮事項を説明しています。内容はこの記事を指します。
現在の Goroutine スケジューラ (Go1.0 の GM モデルを参照) は、Go で作成された同時実行プログラム、特に高スループットのサーバーや並列コンピューティング プログラムのスケーラビリティを制限します。
実装には次の問題があります:
GM モデルの上記の多くの問題を解決するために、Go1.1 では Dmitry Vyukov が取り組みました。 GMモデルをベースに、新たにP(プロセッサー)コンポーネントを追加。また、新しく発生した問題を解決するために Work Stealing アルゴリズムを実装しました。
GMP モデルについては、前回の記事「Go グループの友人に尋ねられた: 制御する Goroutine の適切な数はどれくらいですか? GC とスケジューリングに影響しますか?」 』で解説されています。
# 良いと思う友人は注目してください。ここでは繰り返しません。
P を追加するとどのような変化がもたらされますか?それについてもっと明確に話しましょう。
各 P には独自のローカル キューがあり、グローバル キューへの直接の依存が大幅に減少し、その結果、ロックの競合が減少します。 GM モデルのパフォーマンス オーバーヘッドの大部分はロック競合です。
各 P の相対的なバランスに基づいて、ワーク スティーリング アルゴリズムも GMP モデルに実装されています。P のローカル キューが空の場合、グローバル キューから削除したり、他の P のローカル キューから実行可能な G を盗んで実行したりして、アイドリングを減らし、リソースの使用率を向上させます。
なぜ別の P コンポーネントを追加するのでしょうか?
M(システムスレッド)の配置と合わせて、これを行うと以下の問題が発生します。 一般的に、M の数は P よりも多くなります。 Go と同様に、M の数の最大制限は 10000 で、デフォルトの P の数は CPU コアの数です。さらに、M の特性により、つまり、M をブロックするシステム ブロッキング コールが存在しても十分ではない場合、M は増加し続けます。以上がGoodbye Go インタビュアー: GMP モデル、なぜ P があるのですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。