Comment puis-je avoir 1805 threads alors que je n'ai que 4 CPU virtuels?


9

Je me demandais si quelqu'un pourrait m'expliquer comment, dans mon moniteur d'activité, il est indiqué que j'ai actuellement 1805 fils Screen shot of OS X Activity Monitor

Mais je n'ai que 4 cœurs virtuels sur mon ordinateur (ce qui signifie que je ne devrais pouvoir avoir que 4 threads). Le nombre de threads signifie-t-il que tous les threads gérés par les processeurs lorsqu'ils décident du thread à exécuter?

MODIFIER: La raison pour laquelle je pense qu’il ne peut y avoir que 4 threads sur ma machine vient de cela réponse . Je crois que mon incompréhension découle du fait que le mot "fil" est utilisé dans un contexte différent.


Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacé pour discuter .
bmike

Réponses:


24

Calendrier

Votre 1 805 les threads ne fonctionnent pas simultanément . Ils échangent. Un noyau exécute un peu du thread, puis le met de côté pour exécuter un peu d'un autre thread. Les autres noyaux font la même chose. Tour à tour, les threads s'exécutent un peu à la fois, pas tous en même temps.

L'une des principales responsabilités du système d'exploitation (Darwin et macOS) consiste à planifier quel thread doit être exécuté sur quel noyau pour combien de temps.

Beaucoup de threads n'ont pas de travail à faire, et sont donc laissés en sommeil et non planifiés. De même, de nombreux threads peuvent attendre certaines ressources, telles que des données à extraire du stockage, une connexion réseau à établir ou des données à charger depuis une base de données. Comme il n’ya presque rien à faire à part vérifier l’état de la ressource attendue, ces threads sont planifiés assez brièvement, voire pas du tout.

Le programmeur d'application peut aider cette opération de planification en suspendant son thread pendant un certain temps, sachant que l'attente de la ressource externe prendra un certain temps. Et s'il exécute une boucle «serrée» gourmande en ressources processeur sans motif d'attendre sur des ressources externes, le programmeur peut insérer un appel à volontaire à mettre brièvement de côté afin de ne pas piéger le cœur et permettre ainsi l'exécution d'autres threads.

Pour plus de détails, voir le Page Wikipedia pour le multithreading .

Multi-threading simultané

Quant à votre Question liée , les fils y sont en effet les mêmes que chez nous.

Un des problèmes est le coût supplémentaire de la commutation entre les threads lorsque programmé par le système d'exploitation. Il faut beaucoup de temps pour décharger du noyau les instructions et les données du thread actuel, puis pour charger les instructions et les données du prochain thread planifié. Une partie du travail du système d’exploitation consiste à essayer d’être intelligent dans la planification des threads afin d’optimiser les coûts indirects.

Certains fabricants d’UC ont mis au point une technologie permettant de réduire ce délai afin de faciliter la commutation entre deux threads. Intel appelle sa technologie Hyper-Threading . Connu génériquement multi-threading simultané (SMT) .

Bien que la paire de threads ne s'exécute pas réellement simultanément, la commutation est tellement fluide et rapide que les deux threads semblent être pratiquement simultanés. Cela fonctionne tellement bien que chaque cœur se présente comme une paire de cœurs virtuels au système d’exploitation. Ainsi, un processeur compatible SMT avec quatre cœurs physiques, par exemple, se présentera au système d'exploitation comme un processeur à huit cœurs.

La commutation, même entre des cœurs virtuels optimisés, présente encore quelques frais généraux. Ainsi, un administrateur système peut lancer un commutateur sur la machine pour désactiver SMT si elle décide que cela profiterait aux utilisateurs qui exécutent une application exceptionnellement liée au processeur avec très peu de possibilités de pause. Dans un tel cas, nous revenons à votre question initiale: dans cette situation particulière, vous voudriez bien contraindre les opérations à ne pas avoir plus de ces threads hyperactifs que vous n’avez de cœurs physiques. Mais permettez-moi de répéter: il s'agit d'une situation extrêmement inhabituelle qui peut se produire dans le cadre d'un projet spécialisé dans le traitement de données scientifiques spécialisées, mais qui ne s'appliquerait presque jamais aux scénarios d'entreprise / entreprise courants.


Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacé pour discuter .
bmike

En outre, personne ne met yield() appels système dans leurs unités de traitement gourmandes en ressources processeur (sauf s’il s’agit d’un code hérité issu de la multi-tâche coopérative sur MacOS classique). Le multitâche préemptif est reprogrammé après qu'un thread a utilisé sa tranche de temps.
Peter Cordes

Votre description de l'hyperthreading est fausse. Fils matériels! = Fils logiciels, ce sont des contextes d'exécution / cœurs logiques. Les deux cœurs logiques d'un cœur physique exécutent leurs instructions en même temps. L'interface frontale alterne entre les threads (chaque cycle), mais le noyau d'exécution dans le désordre peut exécuter des instructions / uops à partir des deux threads au cours du même cycle. Cela expose le parallélisme au niveau instruction de deux threads à l’exécution OoO afin de mieux conserver les unités d’exécution alimentées en travail (c’est essentiellement le point de SMT). Il ne s'agit pas simplement de "commutation de contexte optimisée".
Peter Cordes


7

Auparavant, la mémoire n'était ni virtualisée ni protégée et tout code pouvait écrire n'importe où. À cette époque, la conception d'un thread à un processeur était logique. Dans les décennies qui ont suivi, la mémoire a d'abord été protégée, puis virtualisée. Pensez aux threads en tant que cœurs virtuels - une sorte de promesse qu’à un moment donné, lorsque vos données et votre code étaient prêts, ce thread est poussé ( ou programmés comme les ingénieurs PHD et mathématiciens qui font des recherches sur les algorithmes de planification l'appellent ) sur une CPU réelle pour effectuer le travail réel.

enter image description here

Désormais, en raison de l'ampleur des différences temporelles, le processeur et le cache fonctionnent si rapidement par rapport aux données stockées sur le réseau ou le réseau, que des milliers de threads pourraient se succéder pendant que l'un d'entre eux attend que www.google.com livre un message. paquet ou deux de données, c’est la raison pour laquelle vous voyez autant de threads que de CPU.

Si vous convertissez les opérations de fil qui se produisent sur l’échelle de temps noir / bleu et les convertissez en une seconde = 1 ns, les choses qui nous intéressent ressemblent davantage à une prise de disque dur de 100 microsecondes, à 4 jours et à un aller-retour de 200 ms par Internet. Retard de 20 ans si vous comptez les secondes sur l’échelle de temps du processeur. Comme nombreux pouvoirs de dix exercices , dans presque tous les cas - la CPU reste inutilisée pendant "des mois" dans l’attente d’un travail significatif dans un monde externe très lent.

L’image que vous avez publiée n’a rien de mal, alors nous ne comprenons peut-être pas l’objet auquel vous vous entraînez en vous interrogeant sur les sujets.

Si vous cliquez avec le bouton droit de la souris (clic de contrôle) sur les fils de mots dans la rangée d'en-tête en haut, ajoutez le statut de l'application et vous verrez que la plupart des fils sont probablement inactifs, en veille et en cours d'exécution à un moment donné.


Les commentaires ne sont pas pour une discussion prolongée; cette conversation a été déplacé pour discuter .
bmike

1

Vous ne posez pas la question sans doute la plus fondamentale: "Comment puis-je avoir 290 processus lorsque mon processeur n'a que quatre cœurs?" Cette réponse est un peu d'histoire, ce qui pourrait vous aider à comprendre la situation dans son ensemble, même si la question spécifique a déjà été répondue. En tant que tel, je ne donnerai pas une version TL; DR.

Il était une fois (pensez, années 1950-1960), les ordinateurs ne pouvaient faire qu'une chose à la fois. Elles étaient très chères, remplies de salles entières et nous avions besoin d’un moyen de les utiliser efficacement en les partageant entre plusieurs personnes. La première façon de faire était le traitement par lots , dans lequel les utilisateurs soumettraient des tâches à l'ordinateur et seraient mis en file d'attente, exécutés l'un après l'autre et les résultats renvoyés à l'utilisateur. C’était acceptable, mais cela signifiait que si vous vouliez faire un calcul qui prendrait quelques jours, personne d’autre ne pourrait utiliser l’ordinateur pendant cette période.

La prochaine innovation (pensez, années 1960-1970) était partage de temps . Désormais, au lieu d'exécuter la totalité d'une tâche, puis la totalité de la suivante, l'ordinateur exécuterait un peu d'une tâche, l'interromprait ensuite et exécuterait un peu la suivante, et ainsi de suite. Ainsi, l’ordinateur donnerait l’impression qu’il exécutait plusieurs processus simultanément. Le grand avantage de cela est que vous pouvez maintenant exécuter un calcul qui prendra quelques jours et, bien que cela prendra encore plus longtemps, car il continue de s’interrompre, d’autres personnes peuvent toujours utiliser la machine pendant cette période.

Tout cela était destiné aux énormes ordinateurs de type mainframe. Quand les ordinateurs personnels ont commencé à devenir populaires, ils n’étaient au début pas très puissants et, hé, depuis personnel cela leur semblait correct de ne pouvoir faire qu'une chose - exécuter une seule application à la fois (pensez, années 1980). Mais, à mesure qu'ils sont devenus plus puissants (pensez, des années 1990 à aujourd'hui), les gens voulaient aussi que leurs ordinateurs personnels partagent leur temps.

Nous nous sommes donc retrouvés avec des ordinateurs personnels qui donnaient l’illusion d’exécuter simultanément plusieurs processus en les exécutant un à la fois pendant de brèves périodes, puis en les mettant en pause. Les threads sont essentiellement la même chose: finalement, les utilisateurs voulaient que même des processus individuels donnent l’illusion de faire plusieurs choses simultanément. Au début, le rédacteur de l'application devait se débrouiller seul: passer un peu de temps à mettre à jour les graphiques, mettre cela en pause, dépenser un peu de temps à calculer, mettre ça en pause, passer un peu de temps à faire autre chose, ...

Cependant, le système d'exploitation maîtrisant déjà plusieurs processus, il était logique de l'étendre pour gérer ces sous-processus appelés processus. Nous avons donc un modèle où chaque processus (ou application) contient au moins un thread, mais certains en contiennent plusieurs. Chacun de ces threads correspond à une sous-tâche quelque peu indépendante.

Mais, au plus haut niveau, le processeur ne fait que donner l’illusion que ces threads fonctionnent tous en même temps. En réalité, il en fonctionne un pendant un petit moment, le met en pause, en choisit un autre pour courir un peu, etc. Sauf que les processeurs modernes peuvent exécuter plusieurs threads à la fois. Donc, dans le réal En réalité, le système d’exploitation joue à ce jeu de "courir pour un peu, faire une pause, faire autre chose pour un peu, faire une pause" sur tous les cœurs simultanément. Ainsi, vous pouvez avoir autant de threads que vous (et les concepteurs de vos applications) souhaitez, mais, à tout moment, ils seront tous en pause.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.