web-dev-qa-db-fra.com

Nombre optimal de threads par coeur

Disons que j'ai un processeur à 4 cœurs et que je veux exécuter un processus dans le minimum de temps. Le processus est idéalement parallélisable, je peux donc en exécuter des morceaux sur un nombre infini de threads et chaque thread prend le même temps.

Comme j'ai 4 cœurs, je n’attends aucune accélération en exécutant plus de threads que de cœurs, puisqu'un seul core ne peut exécuter qu’un seul thread à un moment donné. Je ne connais pas grand chose au matériel, alors ce n'est qu'une supposition.

Existe-t-il un avantage à exécuter un processus parallélisable sur plus de threads que de cœurs? En d'autres termes, mon processus se terminera-t-il plus vite, plus lentement ou à peu près au même temps si je l'exécute en utilisant 4000 threads plutôt que 4 threads ?

257
Juliet

Si vos threads ne font pas d'E/S, de synchronisation, etc., et qu'il n'y a rien d'autre en cours d'exécution, 1 thread par cœur vous procurera les meilleures performances. Cependant, ce n'est très probablement pas le cas. L'ajout de threads est généralement utile, mais après un certain point, cela entraîne une dégradation des performances.

Il n'y a pas si longtemps, je faisais des tests de performances sur une machine à 2 quad-core exécutant une application ASP.NET sur Mono sous une charge assez décente. Nous avons joué avec le nombre minimal et maximal de threads et nous avons finalement découvert que pour cette application particulière dans cette configuration particulière, le meilleur débit se situait entre 36 et 40 threads. Tout ce qui est en dehors de ces limites a été pire. Leçon apprise? Si j'étais vous, je testerais avec un nombre différent de threads jusqu'à ce que vous trouviez le bon nombre pour votre application.

Une chose est sûre: les threads 4k prendront plus de temps. Cela fait beaucoup de changements de contexte.

236
Gonzalo

Je suis d'accord avec la réponse de @ Gonzalo. J'ai un processus qui ne fait pas d'E/S, et voici ce que j'ai trouvé:

enter image description here

Notez que tous les threads fonctionnent sur un tableau mais que des plages différentes (deux threads n'accèdent pas au même index), les résultats peuvent donc différer s'ils ont travaillé sur des tableaux différents.

La machine 1.86 est un MacBook Air avec un SSD. L'autre mac est un iMac avec un disque dur normal (je pense que c'est 7 200 tr/min). La machine Windows dispose également d’un disque dur à 7 200 tr/min.

Dans ce test, le nombre optimal était égal au nombre de cœurs de la machine.

121
Motasim

Je sais que cette question est plutôt ancienne, mais les choses ont évolué depuis 2009.

Il y a deux choses à prendre en compte maintenant: le nombre de cœurs et le nombre de threads pouvant s'exécuter dans chaque cœur.

Avec les processeurs Intel, le nombre de threads est défini par la méthode Hyperthreading, qui n'est que de 2 (si disponible). Mais Hyperthreading réduit votre temps d'exécution de deux, même lorsque vous n'utilisez pas 2 threads! (c'est-à-dire 1 pipeline partagé entre deux processus - c'est bien quand il y a plus de processus, c'est moins bien sinon. Plus de cœurs sont définitivement meilleurs!)

Sur d’autres processeurs, vous pouvez avoir 2, 4, voire 8 threads. Ainsi, si vous avez 8 cœurs qui prennent chacun en charge 8 threads, vous pouvez avoir 64 processus s'exécutant en parallèle sans changement de contexte.

"Aucun changement de contexte" n’est évidemment pas vrai si vous utilisez un système d’exploitation standard capable de changer de contexte pour toutes sortes de choses qui échappent à votre contrôle. Mais c'est l'idée principale. Certains systèmes d’exploitation vous permettent d’allouer des processeurs afin que seule votre application ait accès/utilise ledit processeur!

D'après ma propre expérience, si vous avez beaucoup d'E/S, utiliser plusieurs threads est une bonne chose. Si vous avez un travail très intensif en mémoire (source de lecture 1, source de lecture 2, calcul rapide, écriture), le fait d'avoir plus de threads n'aide pas. Encore une fois, cela dépend de la quantité de données que vous lisez/écrivez simultanément (c.-à-d. Si vous utilisez SSE4.2 et lisez des valeurs de 256 bits, cela stoppe tous les threads dans leur étape ... autrement dit, 1 thread est probablement beaucoup plus facile à mettre en œuvre et probablement aussi rapide, sinon plus rapide Cela dépend de votre architecture de processus et de mémoire, certains serveurs avancés gèrent des plages de mémoire distinctes pour des cœurs distincts afin que les threads séparés soient plus rapides en supposant que vos données sont correctement archivées ... C’est pourquoi, sur certaines architectures, 4 processus s’exécutent plus rapidement que 1 processus avec 4 threads.)

47
Alexis Wilke

La performance réelle dépendra de la quantité de production volontaire de chaque thread. Par exemple, si les threads n'effectuent AUCUNE entrée/sortie et n'utilisent aucun service système (c'est-à-dire qu'ils sont liés à 100% par l'unité centrale), 1 thread par cœur est optimal. Si les threads font quelque chose qui nécessite d'attendre, vous devrez faire des essais pour déterminer le nombre optimal de threads. 4000 threads entraîneraient une surcharge de planification importante, ce qui n'est probablement pas optimal non plus.

24
Jim Garrison

La réponse dépend de la complexité des algorithmes utilisés dans le programme. J’ai proposé une méthode pour calculer le nombre optimal de threads en effectuant deux mesures des temps de traitement Tn et Tm pour deux nombres arbitraires de threads "n" et "m". Pour les algorithmes linéaires, le nombre optimal de threads sera N = sqrt ((m n (Tm * (n-1) - Tn * (m-1)))/( n Tn-m Tm)).

Veuillez lire mon article concernant les calculs du nombre optimal pour divers algorithmes: pavelkazenin.wordpress.com

18
pkazen

Je pensais ajouter une autre perspective ici. La réponse varie selon que la question suppose une mise à l’échelle faible ou forte.

De Wikipedia :

Faible mise à l'échelle: la manière dont le temps de résolution varie en fonction du nombre de processeurs pour une taille de problème fixe par processeur.

Forte mise à l'échelle: la manière dont le temps de résolution varie en fonction du nombre de processeurs pour une taille de problème totale fixée.

Si la question suppose une mise à l'échelle faible, la réponse de @ Gonzalo suffit. Cependant, si la question suppose une mise à l'échelle forte, il y a quelque chose à ajouter. En cas de forte mise à l'échelle, vous prenez une taille de charge de travail fixe. Par conséquent, si vous augmentez le nombre de threads, la taille des données sur lesquelles chaque thread doit travailler diminue. Sur les CPU modernes, les accès mémoire sont coûteux et il serait préférable de conserver la localité en conservant les données dans des caches. Par conséquent, le nombre optimal probable de threads peut être trouvé lorsque l'ensemble de données de chaque thread s'inscrit dans le cache de chaque core (Je ne vais pas entrer dans les détails de discuter s'il s'agit de cache (s) L1/L2/L3 du système).

Cela est vrai même lorsque le nombre de threads dépasse le nombre de cœurs. Par exemple, supposons qu'il y ait 8 unités arbitraires (ou AU) de travail dans le programme qui seront exécutées sur une machine à 4 coeurs.

Cas 1: est exécuté avec quatre threads, chaque thread devant terminer 2AU. Il faut 10 secondes à chaque thread ( avec beaucoup de cache manquants ). Avec quatre cœurs, le temps total sera de 10 s (10 * 4 fils/4 cœurs).

Cas 2: est exécuté avec huit threads, chaque thread devant terminer 1AU. Chaque thread ne prend que 2s (au lieu de 5s à cause de la quantité réduite ) de cache cache ). Avec huit cœurs, le temps total sera de 4 s (2s * 8 threads/4 cœurs).

J'ai simplifié le problème et ignoré les frais généraux mentionnés dans d'autres réponses (par exemple, les changements de contexte), mais j'espère que vous comprendrez qu'il peut être avantageux d'avoir plus de threads que le nombre de cœurs disponibles, en fonction de la taille des données que vous avez ' re traiter avec.

8
someneat

4000 fils à la fois, c'est assez élevé.

La réponse est oui et non. Si vous bloquez beaucoup d'E/S dans chaque thread, alors, vous pourriez montrer des améliorations significatives en effectuant probablement jusqu'à 3 ou 4 threads par noyau logique.

Cependant, si vous ne bloquez pas beaucoup de choses, la surcharge supplémentaire liée au filetage ralentira le processus. Utilisez donc un profileur et voyez où se trouvent les goulots d'étranglement dans chaque pièce éventuellement parallèle. Si vous effectuez des calculs lourds, plus d'un thread par processeur ne vous aidera pas. Si vous effectuez beaucoup de transfert de mémoire, cela ne vous aidera pas non plus. Si vous faites beaucoup d'E/S, par exemple pour un accès disque ou Internet, alors, oui, plusieurs threads vous aideront dans une certaine mesure, ou du moins, ils rendent l'application plus réactive.

7
Earlz

Référence.

Je commençais à augmenter le nombre de threads pour une application, en commençant à 1, puis à 100, à exécuter trois à cinq essais pour chaque nombre de threads, et à vous construire un graphique de la vitesse de fonctionnement par rapport au nombre de threads. .

Vous devriez que le cas à quatre threads soit optimal, avec une légère augmentation du temps d’exécution par la suite, mais peut-être pas. Votre application est peut-être limitée par la bande passante, c'est-à-dire que le jeu de données que vous chargez en mémoire est énorme, que vous obtenez beaucoup de données manquantes dans le cache, etc., de sorte que deux threads sont optimaux.

Vous ne pouvez pas savoir avant de tester.

6
mmr

Vous trouverez combien de threads peuvent être exécutés sur votre ordinateur en exécutant la commande htop ou ps qui renvoie le nombre de processus sur votre ordinateur.

Vous pouvez utiliser la page de manuel relative à la commande 'ps'.

man ps

Si vous souhaitez calculer le nombre de processus de tous les utilisateurs, vous pouvez utiliser l'une des commandes suivantes:

  1. ps -aux| wc -l
  2. ps -eLf | wc -l

Numéro de calcul d'un processus utilisateur:

  1. ps --User root | wc -l

En outre, vous pouvez utiliser "htop" [Référence] :

Installation sur Ubuntu ou Debian:

Sudo apt-get install htop

Installation sur Redhat ou CentOS:

yum install htop
dnf install htop      [On Fedora 22+ releases]

Si vous voulez compiler htop à partir du code source, vous le trouverez ici .

3

Un exemple de beaucoup de threads ("pool de threads") vs un par cœur est celui de la mise en œuvre d'un serveur Web sous Linux ou Windows.

Étant donné que les sockets sont interrogés sous Linux, de nombreux threads peuvent augmenter la probabilité que l'un d'entre eux interroge le bon socket au bon moment - mais le coût de traitement global sera très élevé.

Sous Windows, le serveur sera implémenté à l’aide des ports d’achèvement des E/S (IOCP), ce qui rendra l’application événementielle: si une E/S complète, le système d’exploitation lance un thread en attente pour le traiter. Lorsque le traitement est terminé (généralement avec une autre opération d'E/S comme dans une paire requête-réponse), le thread retourne sur le port IOCP (file d'attente) pour attendre la fin suivante.

Si aucune entrée/sortie n'est terminée, il n'y a pas de traitement à effectuer et aucun thread n'est lancé.

En effet, Microsoft ne recommande pas plus d’un thread par cœur dans les implémentations IOCP. Toute entrée/sortie peut être attachée au mécanisme IOCP. Les CIO peuvent également être postés par l'application, si nécessaire.

2
Olof Forshell

L'idéal est 1 thread par cœur, tant qu'aucun des threads ne bloquera.

Dans certains cas, cela peut ne pas être vrai: d'autres threads s'exécutent sur le noyau, auquel cas plusieurs threads peuvent donner à votre programme une plus grande tranche du temps d'exécution.

2
patros

Si cela vous semble logique, vérifiez l’utilisation du processeur et de la mémoire et définissez une valeur seuil. Si la valeur de seuil est dépassée, n'autorisez pas la création d'un nouveau thread, sinon autorisez ...

0
M. Gopal

parler du point de vue du calcul et de la mémoire (calcul scientifique) 4000 threads vont ralentir l’application. Une partie du problème tient à la surcharge de commutation de contexte et à la très faible localisation mémoire.

Mais cela dépend aussi de votre architecture. D'après ce que j'ai entendu dire, les processeurs Niagara sont supposés être capables de gérer plusieurs threads sur un même cœur en utilisant une technique de traitement de pipeline avancée. Cependant, je n'ai aucune expérience avec ces processeurs.

0
Anycorn