Je suis fatigué d'entendre les gens vous recommander d'utiliser un seul thread par processeur, alors que de nombreux programmes en utilisent jusqu'à 100 par processus! prenez par exemple certains programmes communs
vb.net ide uses about 25 thread when not debugging
System uses about 100
chrome uses about 19
Avira uses more than about 50
Chaque fois que je poste une question liée à un thread, je me rappelle presque chaque fois que je ne devrais pas utiliser plus d'un thread par processeur, et tous les programmes que je mentionne ci-dessus ruinent mon système avec un seul processeur.
Réponses:
Peut-être dans HPC où vous voulez une efficacité maximale - mais sinon la chose la plus stupide que j'ai entendue aujourd'hui!
Vous devez utiliser le nombre de threads qui sont appropriés pour la conception du programme et toujours donner des performances acceptables.
Pour un serveur Web, il peut être raisonnable de déclencher un thread pour chaque connexion entrante (bien qu'il existe de meilleures façons pour les serveurs très chargés).
Pour une idée, chaque outil exécuté dans son propre thread n'est pas déraisonnable. Je soupçonne que la plupart des threads signalés pour l'IDE .Net sont des choses comme la journalisation et les tâches d'E / S démarrées dans leurs propres threads afin qu'ils puissent continuer non bloqués.
la source
L'avis d'un thread par cœur s'applique lorsque l'objectif est d'accélérer l'exécution parallèle.
Une raison complètement différente et tout aussi valable est la simplicité du code lorsqu'il doit répondre à des événements imprévisibles. Donc, si un programme doit écouter sur 100 sockets et semble accorder toute son attention à chacun, c'est une utilisation parfaite pour le filetage. Un autre exemple est une interface utilisateur, où un thread gère les événements d'interface utilisateur, tandis qu'un autre fait le traitement en arrière-plan.
la source
Vous voulez un thread pour chaque calcul qui peut se dérouler à des rythmes différents des autres calculs.
Pour le calcul parallèle lié au CPU, qui vient en gros blocs de travail, vous voulez généralement un thread par CPU, car une fois qu'ils sont tous occupés, plus de threads n'aident pas et créent simplement une surcharge du planificateur. Si les blocs de travail ont des tailles irrégulières dans le temps ou sont générés dynamiquement au moment de l'exécution (cela se produit souvent lorsque vous avez de grandes structures de données complexes à traiter), vous souhaiterez peut-être attacher ces blocs à de nombreux threads, donc un planificateur a toujours un grand défini pour choisir à partir de la fin d'un certain bloc de travail, afin de garder tous les processeurs occupés.
Pour le calcul lié aux E / S, vous voulez généralement un thread pour chaque "canal" d'E / S indépendant car ils communiquent à des taux différents, et les threads bloqués sur le canal n'empêchent pas les autres threads de progresser.
la source
La règle générale pour les threads est que vous voulez au moins un thread de travail "actif" (capable d'exécuter ses commandes immédiatement en fonction du temps CPU) pour chaque "unité d'exécution" disponible sur l'ordinateur. Une «unité d'exécution» est un processeur d'instructions logiques, donc un serveur hyperthreadé Xeon quadruple puce quadruple cœur aurait 32 EU (4 puces, 4 cœurs par puce, chaque hyperthreadé). Votre Core i7 moyen en aurait 8.
Un thread par UE est l'utilisation la plus complète de la puissance du processeur, à condition que les threads soient toujours en état de fonctionnement; ce n'est presque jamais le cas, car les threads doivent avoir accès à la mémoire non mise en cache, au disque dur, aux ports réseau, etc. qu'ils doivent attendre et qui ne nécessitent pas d'attention active du processeur pour fonctionner. Vous pouvez ainsi augmenter encore l'efficacité globale avec plus de threads en file d'attente et prêts à partir. Cela a un coût; lorsqu'un CPU commute un thread, il doit mettre en cache les registres du thread, le pointeur d'exécution et d'autres informations d'état normalement conservés dans le fonctionnement le plus interne d'une UE et accessibles très rapidement, permettant aux autres EU de cette puce de CPU de les récupérer. Il nécessite également des threads dans le système d'exploitation pour décider quel thread doit être basculé. Enfin, lorsqu'une UE change de fil, il perd les gains de performances du pipeline que la plupart des architectures de processeurs utilisent; il doit vider le pipeline avant de changer de threads. Mais, comme tout cela prend encore beaucoup moins de temps en moyenne que d'attendre simplement que le disque dur ou même la RAM revienne avec des informations, cela en vaut le coût.
Cependant, en général, une fois que vous avez dépassé le double du nombre de threads "actifs" en tant qu'UE, le système d'exploitation commence à consacrer plus de temps aux threads de planification de l'UE et les UE passent plus de temps à basculer entre eux que ce qui est réellement passé à exécuter des threads actifs. des programmes. C'est le point des déséconomies d'échelle; il faudra en fait plus de temps pour qu'un algorithme multithread s'exécute si vous deviez ajouter un thread supplémentaire à ce stade.
Donc, dans l'ensemble, vous voulez conserver au moins autant de threads dans votre programme que vous avez d'UE sur l'ordinateur, mais vous voulez éviter d'avoir plus du double de ce nombre qui n'attendent pas ou ne dorment pas.
la source
Vous devez utiliser un fil pour:
Chaque processeur dont vous avez besoin pour rester occupé.
Chaque E / S que vous pouvez utilement suspendre simultanément que vous ne pouvez pas effectuer de manière non bloquante. (Par exemple, lit à partir d'un disque local.)
Chaque tâche qui nécessite un thread dédié, par exemple l'appel à une bibliothèque qui n'a pas d'interface non bloquante ou où les interfaces non bloquantes ne sont pas appropriées. Cela inclut des tâches telles que la surveillance de l'horloge système, le déclenchement des minuteries, etc.
Quelques extra pour se protéger contre les blocages inattendus tels que les défauts de page.
Quelques éléments supplémentaires pour se protéger contre le blocage attendu qui ne vaut pas la peine d'être optimisé, par exemple dans le code non critique. (Par exemple, si vous avez très rarement besoin de faire une requête DNS, cela ne vaut probablement pas la peine de faire des requêtes DNS de manière asynchrone. Créez simplement quelques threads supplémentaires et simplifiez-vous la vie.)
Si vous suivez la règle "un thread par processeur", alors tout votre code est critique pour les performances. Tout code qui se bloque pour une raison quelconque signifie que votre processus ne peut pas utiliser ce processeur. Cela rend la programmation beaucoup plus difficile sans raison valable.
la source
Vous pouvez générer des processus et des threads pour permettre l'utilisation d'un système multicœur \ multiprocesseur pour un seul programme, auquel cas vous ne gagnez aucun avantage (pour le programme unique au moins) à avoir plus de threads \ processus que de cœurs.
Ou vous pouvez avoir des routines qui interrogent un événement qui bloquent généralement la poursuite de l'exécution. Plutôt que de lier le CPU à l'interrogation, vous pouvez créer un thread qui restera inactif jusqu'à ce que l'événement approprié le réveille. Cette méthode est très couramment utilisée dans les serveurs Web et les files d'attente d'événements GUI. La plupart des programmes veulent avoir une sorte de magasin de données central (même si son code d'exécution de programme) auquel tous les threads peuvent accéder, donc je suppose que c'est pourquoi ils utilisent le threading sur les processus.
la source
Les applications que vous mentionnez exécutent rarement toutes ces dizaines de threads simultanément. La plupart d'entre eux restent assis parce qu'ils sont dans un pool de threads . L'application envoie diverses tâches à une file d'attente, qui est purgée par les threads du pool de threads.
Pourquoi la piscine est-elle si grande alors? Parce que, souvent, les threads doivent attendre d'autres ressources telles que le disque, le réseau, l'utilisateur, un autre thread, etc. Pendant qu'un thread attend, il est approprié d'exécuter d'autres threads pour utiliser pleinement le processeur. Le dimensionnement approprié de la piscine est cependant délicat. Trop peu de threads et vous perdrez les performances car le processeur n'est pas pleinement utilisé en attendant quelque chose. Trop de threads et vous perdrez les performances en changeant entre eux.
la source