Intel Pentium 4 3.06 Ghz HyperThreading | ||||||
By Samuel D. / Franck D. - 14/11/2002 | ||||||
Hyperthreading : Explications
Depuis le Pentium et son architecture superscalaire (capable de traiter deux instructions en même temps), l'évolution des processeurs tend vers une optimisation grandissante de la parallélisation. Derrière ce terme se cache l'idée de faire faire le maximum de travail au processeur pendant chacun de ses cycles, on comprend donc que l'enjeu soit d'importance. Par la suite, deux technologies ont été introduites pour contribuer à une meilleure parallélisation :
L'architecture NetBurst a introduit une nouvelle technologie de parallélisation sous la forme de l'Hyper-Threading (HT), qui permet l'exécution simultanée de plusieurs threads avec un seul processeur physique. Pour mieux comprendre en quoi elle consiste, expliquons d'abord brièvement ce qu'est un thread, et quel est son intérêt.
Un environnement multi-tâches tel que Windows ou Linux fait cohabiter en mémoire plusieurs programmes, sous la forme de processus et de threads. Chaque processus et chaque thread utilise une partie des ressources du système, à savoir cycles processeur et mémoire. La différence entre un processus et un thread réside dans le fait que deux processus ne peuvent travailler dans une zone mémoire commune, alors que deux threads le peuvent. En pratique, un programme ne comporte souvent qu'un seul processus, et est susceptible d'utiliser plusieurs threads. Un thread (littéralement "une tâche") consiste ainsi en un morceau de programme dont la particularité est de s'exécuter séparément du reste du programme, à la différence d'une fonction dont le début et la fin sont définis de façon figée dans le déroulement du programme. Prenons un exemple concret afin d'illustrer l'intérêt d'un thread : vous utilisez votre logiciel de messagerie (Outlook ou autre), et vous rédigez un nouveau message. D'une façon simplifiée, le logiciel de messagerie utilise alors deux threads : un thread s'occupe de scruter vos entrées au clavier et de mettre à jour la fenêtre du nouveau message, et un autre thread vérifie de façon périodique l'arrivée de nouveaux messages. Si un seul et même thread était utilisé pour les deux actions, la rédaction de votre message serait temporairement interrompue à chaque vérification des nouveaux messages, ce qui serait fort peu ergonomique. L'intérêt du thread réside donc dans la séparation des tâches, donnant l'impression que le programme est capable de faire plusieurs choses en même temps. L'OS traite alternativement tous les threads en cours, passant "la main" continuellement de l'un à l'autre, et donnant ainsi l'illusion d'une exécution simultanée. C'est à la charge de l'OS de répartir les threads courants sur les ressources présentes, en fonction de leur priorité et du temps qu'il leur est apparti. Ce système prend tout son sens sur une machine à plusieurs processeurs : l'OS peut ainsi affecter un ou plusieurs threads à chaque processeur, parallélisant ainsi leur exécution.
Le ou les processeurs centraux sont donc amenés à traiter une série de threads, et afin de permettre cette alternance continuelle, chaque thread est associé à un contexte (ou état) qui contient entre autres l'état des registres du processeur au moment où le traitement du thread est arrêté. Chaque fois qu'un thread est traité par le processeur, son état est restauré dans les registres du processeur, permettant ainsi à celui-ci de reprendre l'exécution du thread là où il l'avait laissée. Enfin, lorsqu'un autre thread va prendre la main, ce contexte est sauvegardé. La transition d'un thread à un autre est une opération
particulièrement coûteuse pour le processeur. La restauration
de l'état permet certes de restaurer rapidement la plupart des
registres, mais le pipeline nécessite d'être vidangé
afin de terminer les instructions du thread précédent. Opération
particulièrement pénalisante sur le Pentium 4 dont le pipeline
comprend 20 étages.
Ainsi, deux threads peuvent coexister simultanément dans le même
processeur physique, et l'OS ayant affaire à deux "destinations"
possible pour chacun des threads qu'il traite, il y voit deux processeurs,
tout comme si le système était équipé de deux
processeurs complets !
On peut alors s'interroger sur l'intérêt du système, considérant que les deux threads sont certes susceptibles de cohabiter au même instant, mais doivent se partager les mêmes unités de calcul, ce qui à première vue semble ne pas changer grand-chose par rapport à leur traitement successif par le même processeur. En réalité, et c'est là qu'est toute l'astuce, l'HT
exploite une faiblesse du Pentium 4, qui tient à la mauvaise utilisation
de ses ressources en utilisation courante. En effet, aux dires d'Intel,
un code classique n'utilise en moyenne que 35% des ressources réelles
du pipeline du Pentium 4, soit à peine plus d'un tiers du débit
maximal théorique ! La raison de ce faible taux réside principalement
dans la multitude de conflits qui interrompent le fonctionnement optimal
du pipeline, en particulier les conflits de dépendance et de branchement.
Le moteur d'exécution dans le désordre (OOO) peut alors travailler avec deux configurations de registres différentes (les deux contextes) et deux fois plus d'instructions. Son efficacité s'en trouve grandement améliorée, car il peut optimiser l'organisation des instructions envoyées dans le pipeline. En quelque sorte, les instructions du second thread comblent les "bulles" dans le pipeline, et il en résulte finalement que les unités de calcul du Pentium 4 sont mieux exploitées qu'avec un seul flux d'instructions ; Intel annonce à ce titre un gain de performance compris entre 30 et 40%.
Que penser donc de l'HT ? Celui-ci peut être considéré comme une amélioration à double tranchant, dans la mesure où elle est susceptible d'apporter des gains allant jusqu'à 40% pour certaines applications, mais négatifs pour d'autres applications. Tout ceci dépend en grande partie des applications, mais également du système d'exploitation, comme nous le verrons plus loin.
Afin de mesurer le gain théorique apporté par l'HT, et ce en comparaison à un système à deux processeurs, nous avons utilisé un programme de calcul développé spécifiquement et appelé MTB (Multi-Thread benchmark). Ce programme utilise une routine de calcul basée sur la méthode Whetstone, et composée de 10 modules distincts regroupants une série d'opérations communément effectuées par les programmes courants : manipulation de tableaux, sauts conditionnels, arithmétique entière et flottante, opérations trigonométriques, appels de fonctions. Afin d'éviter les conflits de cache, la boucle de calcul utilise des tableaux de petite taille, ce qui n'est pas réellement représentatif de conditions réelles mais permet de fournir une idée de la puissance brute de calcul.
Le programme permet de lancer simultanément jusqu'à quatre
boucles de calcul, chacune dans un thread différent. Chaque thread
peut être affecté à un des processeurs du système.
Le temps de calcul de chaque boucle est mesuré, et on peut ainsi
en déduire un index correspondant à la puissance de calcul
du système, obtenu en divisant le temps total par le nombre de
threads.
Sans HT, le Pentium 4 à 3.06GHz renvoie un index de performances de 16.2, ce qui nous donne un résultat SMP hypothétique de 32.4. Face à cela, l'utilisation de l'HT fait grimper l'index à 22.9, ce qui nous donne un gain de performance de 41% par rapport à un seul processeur, pourcentage à comparer avec les 100% que procurerait une véritable configuration SMP. Nous obtenons donc un résultat très proche des chiffres théoriques annoncés par Intel. Il convient cependant de noter que les résultats sont largement inférieurs à ceux obtenus avec une configuration SMP, face auquel l'hyper-threading est annoncé comme étant une alternative. Qui plus est, ces résultats ne reflètent pas les conditions réelles, pour lesquelles les caches représentent un facteur de performance important. Nous verrons cela lors des tests avec des benchmarks moins synthétiques que MTB.
|
||||||
Fermer |