Maison  >  Article  >  développement back-end  >  Au revoir Go intervieweur : Modèle GMP, pourquoi y a-t-il P ?

Au revoir Go intervieweur : Modèle GMP, pourquoi y a-t-il P ?

Golang菜鸟
Golang菜鸟avant
2023-08-08 16:31:451424parcourir


Le protagoniste d'aujourd'hui est une question d'extension (question) de la question polyvalente du modèle GMP dans l'interview de Go, c'est-à-dire "Modèle GMP, pourquoi a-t-il besoin de P?"

Plonger davantage dans l'arrière-plan de la question, en fait, cette interview L'essence de la question est de demander : « Dans le modèle GMP, pourquoi G et M ne peuvent-ils pas être directement liés ? essayer de résoudre ?"

Cet article vous amènera à explorer les raisons des changements dans les modèles GM et GMP.

Modèle GM

Avant Go1.1, le modèle de planification de Go était en fait le modèle GM, c'est-à-dire qu'il n'y avait pas de P.

Aujourd'hui, je vais vous amener à revoir les créations passées.

Déchiffrer le code source de Go1.0

L'une des façons pour nous de comprendre quelque chose est d'examiner le code source. Jetons un coup d'œil aux principales étapes clés du code source du planificateur Go1.0.1 avec. Jianyu :

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);
}

  • Callschedlock méthode pour obtenir Verrouillage global. schedlock 方法来获取全局锁。
  • 获取全局锁成功后,将当前 Goroutine 状态从 Running(正在被调度) 状态修改为 Runnable(可以被调度)状态。
  • 调用 gput 方法来保存当前 Goroutine 的运行状态等信息,以便于后续的使用。
  • 调用 nextgandunlock 方法来寻找下一个可运行 Goroutine,并且释放全局锁给其他调度使用。
  • 获取到下一个待运行的 Goroutine 后,将其运行状态修改为 Running。
  • 调用 runtime·gogo
Après avoir acquis avec succès le verrou global, modifiez l'état actuel de Goroutine de l'état En cours d'exécution (en cours de planification) à l'état Exécutable (peut être planifié).

Appelgput méthode pour enregistrer État d'exécution actuel de Goroutine et autres informations pour une utilisation ultérieure.

Appelnextgandunlock méthode pour trouver Le prochain Goroutine peut être exécuté et le verrou global est libéré pour que d'autres planificateurs puissent l'utiliser.
Au revoir Go intervieweur : Modèle GMP, pourquoi y a-t-il P ?
Après avoir obtenu la prochaine Goroutine à exécuter, changez son statut d'exécution en Running.

Appelméthode runtime·gogo , exécutez le prochain Goroutine à exécuter qui vient d'être obtenu et entrez dans le prochain cycle de planification.

En pensant au modèle GM

En analysant le code source du planificateur de Go1.0.1, nous pouvons trouver un point intéressant. Il s'agit du planificateur lui-même (méthode de planification). Dans les processus normaux, il ne reviendra pas, c'est-à-dire qu'il ne mettra pas fin au processus principal.

🎜🎜🎜Diagramme du modèle G-M🎜🎜🎜 Il exécutera en continu le processus de planification une fois que GoroutineA est terminé, il commence à rechercher GoroutineB. Lorsque B est trouvé, le droit de planification terminé de A est transmis à B, de sorte que GoroutineB. commence à être Scheduling, c'est-à-dire en cours d'exécution. 🎜🎜Bien sûr, il y a aussi des G qui sont bloqués (Blocked). Supposons que G effectue des appels système ou réseau, ce qui entraînera le blocage de G. À ce moment-là, M (thread système) sera remis dans la file d'attente du noyau, en attendant un nouveau cycle de réveil. 🎜🎜🎜🎜Inconvénients du modèle GM🎜🎜🎜🎜En apparence, le modèle GM semble indestructible et sans défauts. Mais pourquoi le changer ? 🎜🎜En 2012, Dmitry Vyukov a publié l'article "Scalable Go Scheduler Design Doc", qui est toujours la cible principale des principaux articles de recherche sur le planificateur Go. Il a décrit les raisons et considérations générales dans l'article. Le contenu suivant citera cet article. . 🎜

Le planificateur Goroutine actuel (faisant référence au modèle GM de Go 1.0) limite l'évolutivité des programmes concurrents écrits en Go, en particulier les serveurs à haut débit et les programmes de calcul parallèle.

L'implémentation présente les problèmes suivants :

  • Il existe un seul mutex global (Sched.Lock) et une gestion centralisée de l'état :
    • mutex doit protéger toutes les opérations liées à la goroutine (création, achèvement, réorganisation, etc.), ce qui conduit à une sérieuse concurrence entre serrures.
  • Problèmes de livraison des goroutines :
    • remise de la goroutine (G) (G.nextg) : les goroutines exécutables sont souvent transférées entre les threads de travail (M).
    • Ce qui précède peut entraîner une latence accrue et une surcharge supplémentaire. Chaque M doit être capable d'exécuter n'importe quel G exécutable, en particulier le M qui vient de créer G.
  • Chaque M doit être mis en cache en mémoire (M.mcache) :
    • entraînera une consommation excessive de ressources (chaque mcache peut absorber 2 M de cache mémoire et d'autres caches) et une mauvaise localisation des données.
  • Blocage/déblocage fréquent des threads :
    • Les threads sont fréquemment bloqués et débloqués en présence d'appels système. Cela ajoute beaucoup de frais supplémentaires en termes de performances.

Modèle GMP

Afin de résoudre bon nombre des problèmes ci-dessus du modèle GM, dans Go1.1, Dmitry Vyukov a ajouté un nouveau composant P (processeur) basé sur le modèle GM. Et implémenté l'algorithme Work Stealing pour résoudre certains problèmes nouvellement générés.

Au revoir Go intervieweur : Modèle GMP, pourquoi y a-t-il P ?

Modèle GMP, dans l'article précédent « Les amis du groupe Go ont demandé : quel est le nombre approprié de Goroutines à contrôler, cela affectera-t-il le GC et la planification ? a été expliqué dans "."

Les amis qui pensent que c'est bien peuvent y prêter attention, je ne le répéterai pas ici.

Quels changements cela apportera-t-il

Quels changements cela apportera-t-il après l'ajout de P ? Parlons-en plus explicitement.

  • Chaque P a sa propre file d'attente locale, ce qui réduit considérablement la dépendance directe à l'égard de la file d'attente globale. Le résultat est une réduction de la concurrence entre les verrous. La majeure partie des performances supplémentaires du modèle GM est due à la concurrence des verrous.

  • Sur l'équilibre relatif de chaque P, l'algorithme Work Stealing est également implémenté dans le modèle GMP. Si la file d'attente locale de P est vide, l'exécutable G sera volé dans la file d'attente globale ou la file d'attente locale de. d'autres P à fonctionner, réduisant ainsi la marche au ralenti et améliorant l'utilisation des ressources.

Pourquoi y a-t-il P

Certains amis peuvent être confus en ce moment Si vous souhaitez implémenter une file d'attente locale et un algorithme de vol de travail, alors pourquoi ne pas simplement l'ajouter directement à M ? pour M Des fonctions similaires peuvent être obtenues .

Pourquoi ajouter un autre composant P ?

Combiné avec le positionnement de M (thread système), si vous faites cela, il y a les problèmes suivants.

  • D'une manière générale, le nombre de M sera supérieur à celui de P. Comme dans Go, la limite maximale du nombre de M est de 10 000 et le nombre par défaut de P est le nombre de cœurs de processeur. De plus, en raison des propriétés de M, c'est-à-dire que s'il existe un appel de blocage du système qui bloque M et n'est pas suffisant, M continuera d'augmenter.

  • Si M continue d'augmenter, si la file d'attente locale est montée sur M, cela signifie que la file d'attente locale augmentera également en conséquence. Ceci est évidemment déraisonnable, car la gestion des files d’attente locales deviendra compliquée et les performances du Work Stealing seront considérablement réduites.

  • M Après avoir été bloqué par un appel système, nous espérons allouer ses tâches non exécutées à d'autres pour continuer à s'exécuter, plutôt que de tout arrêter dès qu'il est bloqué.

Par conséquent, il n'est pas raisonnable d'utiliser M. Ensuite, introduire un nouveau composant P et associer la file d'attente locale à P peut très bien résoudre ce problème.

Résumé

L'article d'aujourd'hui combine quelques situations historiques, une analyse des causes et une description de la solution pour l'ensemble du planificateur de langage Go.

« Modèle GMP, pourquoi y a-t-il P ? » Cette question est comme une compréhension de la conception d'un système, car désormais de nombreuses personnes vont mémoriser le modèle GMP ou le parcourir de manière instantanée afin de faire face à l'entretien. Et comprendre les véritables raisons qui en sont la cause est ce que nous devons apprendre et comprendre.

Ce n'est que lorsque vous savez ce qui se passe et pourquoi cela se produit que vous pourrez briser la situation.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer
Article précédent:Aller aux bases de GoroutineArticle suivant:Aller aux bases de Goroutine