Je ne suis pas un expert de l'architecture x86 (j'espère que quelqu'un de plus expérimenté pourra m'éclairer), mais voici quelques réponses de haut niveau à vos questions.
J'ai entendu dire que l'ARM n'est pas hyperthreadé comme le x86 [...].
C'est vrai, l'hyperthreading est une fonctionnalité propriétaire d'Intel. À ma connaissance, il n'existe pas de technologie ARM analogue sur le silicium.
[...] et donc mes 4 cœurs seront déjà en train de changer de contexte pour suivre mes 6 pthreads (et les processus d'arrière-plan). Quel genre de pénalité de performance dois-je attendre de cela ? [...]
Ce n'est pas nécessairement le cas, bien que cela puisse très bien se produire dans de nombreux scénarios. Cela dépend plus de la nature de vos calculs par thread... faites-vous simplement beaucoup de calculs lourds, ou faites-vous beaucoup de blocages/attentes sur les E/S ? Quoi qu'il en soit, cette dégradation se produira sur les deux architectures et il s'agit plutôt d'un problème général de planification des threads. Dans le monde Intel hyperthreadé, chaque "cœur physique" est vu par le système d'exploitation comme deux "cœurs logiques" qui partagent les mêmes ressources mais ont leur propre pipeline et jeux de registres. L'article de wikipedia indique :
Chaque processeur logique peut être individuellement arrêté, interrompu ou dirigé pour exécuter un fil d'exécution spécifique, indépendamment des autres processeurs logiques partageant le même noyau physique[7].
Contrairement à une configuration traditionnelle à double processeur qui utilise deux processeurs physiques distincts, les processeurs logiques d'un noyau hyperthreadé partager les ressources d'exécution. Ces ressources comprennent le moteur d'exécution, les caches et l'interface du bus système ; Le partage des ressources permet à deux processeurs logiques de travailler plus efficacement l'un avec l'autre et à un processeur logique d'emprunter des ressources à un cœur logique bloqué (en supposant que les deux cœurs logiques soient associés au même cœur physique). Un processeur se bloque lorsqu'il attend des données qu'il a envoyées pour pouvoir terminer le traitement du fil actuel. Le degré d'avantage constaté lors de l'utilisation d'un processeur hyperthreadé ou multicœur dépend des besoins du logiciel et de la manière dont celui-ci et le système d'exploitation sont écrits pour gérer efficacement le processeur[7].
Donc, si quelques-uns de vos threads bloquent constamment sur les E/S, c'est peut-être là que vous verrez plus d'améliorations dans une application à 6 threads sur un système à 4 cœurs physiques (à la fois pour ARM et Intel x86) puisque, théoriquement, c'est là que l'hyperthreading pourrait briller.... un thread bloquant sur les E/S ou sur le résultat d'un autre thread peut "dormir" tout en permettant à l'autre thread fonctionnant sur le même cœur de faire son travail sans l'overhead complet d'un changement de thread (experts s'il vous plaît chime in et dites-moi si je me trompe ici).
Mais ARM 4 cœurs contre x86 2 cœurs... en supposant que toutes les autres choses soient égales (ce qui n'est évidemment pas le cas, en réalité les vitesses d'horloge, la hiérarchie du cache, etc. ont un impact énorme), je pense que cela dépend vraiment de la nature des threads. J'imagine que cette baisse de performance pourrait se produire si vous faites juste une tonne de "threads". purement lié au processeur (c'est-à-dire que les threads n'ont jamais besoin d'attendre quelque chose d'extérieur au CPU). Mais si vous effectuez beaucoup d'entrées/sorties bloquantes dans chaque thread, vous pouvez obtenir des gains de vitesse significatifs en utilisant jusqu'à 3 ou 4 threads par cœur logique.
Une autre chose à garder à l'esprit est le cache. Lorsque vous effectuez de nombreux calculs liés au processeur, un changement de thread peut faire exploser le cache, ce qui se traduit par un accès à la mémoire beaucoup plus lent au départ. Cela se produit sur les deux architectures. Ce n'est pas le cas avec la mémoire E/S, cependant. Mais si vous ne faites pas beaucoup de choses bloquantes, alors l'overhead supplémentaire avec le threading ne fera que le rendre plus lent pour les raisons ci-dessus.
J'ai entendu dire que je devais m'attendre à ce que ces commutateurs contextuels ARM soient moins efficaces que les commutateurs x86. Est-ce vrai ?
Un changement de contexte matériel est un changement de contexte matériel, vous poussez tous les registres dans la pile et vous basculez quelques bits pour changer l'état d'exécution. Donc non, je ne pense pas que l'un ou l'autre soit "plus rapide" à cet égard. Cependant Pour un seul cœur physique, des techniques telles que l'hyperthreading accélèrent considérablement le "changement de contexte" au sens des systèmes d'exploitation (je pense que vous voulez dire le passage d'un thread à l'autre), puisque les instructions des deux programmes sont déjà exécutées en parallèle sur le même cœur.
Je ne connais pas le GCD, je ne peux donc pas faire de commentaires à ce sujet.
En fin de compte, je dirais que votre meilleure chance est d'évaluer l'application sur les deux architectures. Voyez où se trouvent vos goulots d'étranglement. S'agit-il de l'accès à la mémoire ? Garder le cache chaud est donc une priorité. J'imagine qu'un thread par cœur serait toujours optimal dans n'importe quel scénario, si vous pouvez le faire.
De bonnes choses à lire sur ce sujet :
- https://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html
- https://lwn.net/Articles/250967/
- Nombre optimal de threads par cœur
- Commutation de contexte de fil et de processus