Nombre optimal de threads par cœur

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

Étant donné que j’ai 4 cœurs, je ne m’attends pas à une accélération en exécutant plus de threads que de cœurs, car un seul cœur ne peut exécuter qu’un seul thread à un moment donné. Je ne connais pas beaucoup le 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 rapidement, plus lentement ou à peu près dans le même temps si je l’exécute avec 4 000 threads au lieu de 4 threads?

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

    Il n’y a pas si longtemps, je faisais des tests de performance 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 minimum et maximum de threads et à la fin, nous avons 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 se trouvait en dehors de ces frontières a été moins performant. Leçon apprise? Si j’étais vous, je testerais avec un nombre différent de threads jusqu’à ce que vous trouviez le bon numéro pour votre application.

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

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

    entrer la description de l'image ici

    Notez que tous les threads fonctionnent sur un tableau mais des plages différentes (deux threads n’accèdent pas au même index), donc les résultats peuvent 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 7200 tr / min). La machine Windows a également un disque dur de 7 200 tr / min.

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

    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 être exécutés dans chaque cœur.

    Avec les processeurs Intel, le nombre de threads est défini par l’hyperthreading qui est juste 2 (lorsque disponible). Mais Hyperthreading réduit votre temps d’exécution de deux, même si vous n’utilisez pas 2 threads! (c.-à-d. 1 pipeline partagé entre deux processus – c’est bien quand vous avez plus de processus, pas si bon sinon. Plus les cœurs sont définitivement meilleurs!)

    Sur d’autres processeurs, vous pouvez avoir 2, 4 ou même 8 threads. Donc, si vous avez 8 cœurs chacun supportant 8 threads, vous pouvez avoir 64 processus en parallèle sans changer de contexte.

    “Pas de changement de contexte” n’est évidemment pas vrai si vous utilisez un système d’exploitation standard qui changera de contexte pour toutes sortes d’autres choses hors de votre contrôle. Mais c’est l’idée principale. Certains systèmes d’exploitation vous permettent d’allouer des processeurs, de sorte que seule votre application a access / utilisation dudit processeur!

    De ma propre expérience, si vous avez beaucoup d’E / S, plusieurs threads sont bons. Si vous avez un travail intensif en mémoire (lecture de la source 1, lecture de la source 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 lues / écrites simultanément (c’est-à-dire que si vous utilisez SSE 4.2 et que vous lisez les valeurs 256 bits, cela arrête tous les threads … probablement presque plus rapide sinon plus rapide.Cela dépendra de votre architecture de processus et de mémoire, certains serveurs avancés gèrent des plages de mémoire séparées pour des cœurs séparés, donc des threads séparés seront plus rapides en supposant que vos données sont correctement classées … les architectures, 4 processus s’exécuteront plus rapidement que 1 processus avec 4 threads.)

    La performance réelle dépendra du rendement volontaire de chaque thread. Par exemple, si les threads ne font AUCUNE E / S et n’utilisent aucun service système (c’est-à-dire qu’ils sont 100% liés au processeur), 1 thread par cœur est la solution optimale. Si les threads font tout ce qui nécessite une attente, vous devrez alors expérimenter 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.

    La réponse dépend de la complexité des algorithmes utilisés dans le programme. J’ai trouvé 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)).

    S’il vous plaît lire mon article concernant les calculs du nombre optimal pour divers algorithmes: pavelkazenin.wordpress.com

    Je pensais append une autre perspective ici. La réponse dépend de savoir si la question suppose une mise à l’échelle faible ou une mise à l’échelle forte.

    De Wikipedia :

    Mise à l’échelle faible: comment la durée de la solution varie avec le nombre de processeurs pour une taille de problème fixe par processeur.

    Forte mise à l’échelle: comment la durée de la solution varie avec le nombre de processeurs pour une taille de problème totale fixe.

    Si la question suppose une mise à l’échelle faible, la réponse de @ Gonzalo suffit. Cependant, si la question suppose une forte mise à l’échelle, il y a quelque chose à append. Dans une mise à l’échelle forte, vous supposez 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 fonctionner diminue. Sur les processeurs modernes, les access mémoire sont coûteux et il serait préférable de conserver la localité en conservant les données dans les caches. Par conséquent, le nombre optimal probable de threads peut être trouvé lorsque l’dataset de chaque thread tient dans le cache de chaque core (je ne vais pas entrer dans les détails de la question de savoir s’il s’agit de cache L1 / L2 / L3).

    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 cœurs.

    Cas 1: exécutez avec quatre threads où chaque thread doit compléter 2AU. Chaque thread prend 10 secondes pour terminer ( avec beaucoup de cache manqués ). Avec quatre cœurs, le temps total sera de 10 secondes (10s * 4 threads / 4 cœurs).

    Cas 2: exécutez avec huit threads où chaque thread doit compléter 1AU. Chaque thread ne prend que 2s (au lieu de 5 en raison de la quantité réduite de caches de cache ). Avec huit cœurs, le temps total sera de 4 s (2 * 8 threads / 4 cœurs).

    J’ai simplifié le problème et les frais généraux ignorés mentionnés dans d’autres réponses (par exemple, les changements de contexte), mais j’espère que vous pourriez avoir intérêt à avoir plus de threads que le nombre de cœurs disponibles, selon la taille des données. re traiter avec.

    4000 threads à la fois sont assez élevés.

    La réponse est oui et non. Si vous bloquez beaucoup d’E / S sur chaque thread, alors oui, vous pourriez afficher des accélérations significatives pouvant aller jusqu’à 3 ou 4 threads par cœur logique.

    Si vous ne bloquez pas beaucoup de choses, alors le temps système supplémentaire avec le threading le rendra plus lent. 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 comme pour l’access au disque ou à Internet, alors oui, plusieurs threads vous aideront dans une certaine mesure, ou du moins, vous rendrez l’application plus réactive.

    Référence.

    Je commencerais à augmenter le nombre de threads pour une application, à partir de 1, puis à quelque chose comme 100, à exécuter trois à cinq essais pour chaque nombre de threads et à construire vous-même un graphique de la vitesse d’opération et du nombre de threads. .

    Vous devriez faire en sorte que le cas des quatre threads soit optimal, avec de légères augmentations d’exécution après cela, mais peut-être pas. Il se peut que votre application soit limitée par la bande passante, c’est-à-dire que le jeu de données que vous chargez en mémoire est énorme, vous obtenez beaucoup de caches, etc, de sorte que 2 threads sont optimaux.

    Vous ne pouvez pas savoir jusqu’à ce que vous testiez.

    Vous trouverez le nombre de threads que vous pouvez exécuter sur votre machine en exécutant la commande htop ou ps qui renvoie le nombre de processus sur votre machine.

    Vous pouvez utiliser la page de manuel sur la commande ‘ps’.

    man ps 

    Si vous souhaitez calculer le nombre de processus de tous les utilisateurs, vous pouvez utiliser l’une de ces commandes:

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

    Calcul du nombre 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 comstackr htop à partir du code source, vous le trouverez ici .

    Un exemple de lots de threads (“pool de threads”) par rapport à un par cœur est celui de l’implémentation d’un serveur Web sous Linux ou Windows.

    Comme 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é en utilisant les ports IOC (I / O Completion Ports), ce qui rendra l’événement d’application piloté: si une E / S termine le système d’exploitation, elle 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 demande-réponse), le thread revient au port IOCP (queue) pour attendre le prochain achèvement.

    Si aucune E / S 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 E / S peut être attachée au mécanisme IOCP. Si nécessaire, les IOC peuvent également être affichés par l’application.

    L’idéal est 1 thread par coeur, tant qu’aucun des threads ne sera bloqué.

    Un cas où cela peut ne pas être vrai: d’autres threads s’exécutent sur le cœur, auquel cas plus de threads peuvent donner à votre programme une plus grande part du temps d’exécution.

    À partir du calcul et du sharepoint vue lié à la mémoire (calcul scientifique), les 4 000 threads rendront l’exécution des applications très lente. Une partie du problème est due à une surcharge de commutation de contexte très élevée et à une localisation de la mémoire très probablement très médiocre.

    Mais cela dépend aussi de votre architecture. D’où j’ai entendu les processeurs de Niagara sont supposés être capables de gérer plusieurs threads sur un seul cœur en utilisant une technique de pipeline avancée. Cependant, je n’ai aucune expérience avec ces processeurs.

    J’espère que cela a du sens, Vérifiez l’utilisation du processeur et de la mémoire et mettez une valeur de seuil. Si la valeur du seuil est dépassée, ne permettez pas de créer un nouveau thread, sinon autorisez …