Il semble que la question soit trop simple à poser, mais je l'ai posée après avoir parcouru quelques points sur les deux.
Les deux méthodes augmentent le débit des instructions. Et Superscaling utilise presque toujours également le pipelining. La super-échelle a plus d'une unité d'exécution, tout comme le pipelining ou je me trompe ici?
La conception superscalaire implique que le processeur puisse émettre plusieurs instructions en une seule horloge, avec des fonctions redondantes pour exécuter une instruction. Nous parlons d'un cœur unique, sachez que le traitement multicœur est différent.
Pipelining divise une instruction en étapes, et puisque chaque étape est exécutée dans une partie différente du processeur, plusieurs instructions peuvent être dans des "phases" différentes à chaque horloge .
Ils sont presque toujours utilisés ensemble. Cette image de Wikipedia montre les deux concepts utilisés, car ces concepts sont mieux expliqués graphiquement:
Ici, deux instructions sont exécutées à la fois dans un pipeline en cinq étapes.
Pour le décomposer davantage, compte tenu de votre modification récente:
Dans l'exemple ci-dessus, une instruction passe par 5 étapes à "exécuter". Ce sont IF (extraction de l'instruction), ID (décodage de l'instruction), EX (exécution), MEM (mise à jour de la mémoire), WB (réécriture dans le cache).
Dans une conception de processeur très simple, à chaque horloge, une étape différente serait terminée, nous aurions donc:
Ce qui ferait une instruction sur cinq horloges. Si nous ajoutons ensuite une unité d'exécution redondante et introduisons une conception superscalaire, nous aurions ceci, pour deux instructions A et B:
Deux instructions en cinq horloges - un gain maximum théorique de 100%.
Le pipelining permet d'exécuter les pièces simultanément, donc nous finirions par quelque chose comme (pour dix instructions A à J):
En neuf horloges, nous avons exécuté dix instructions - vous pouvez voir où le pipelining fait vraiment avancer les choses. Et c'est une explication de l'exemple graphique, pas comment il est réellement implémenté sur le terrain (c'est magie noire).
Les articles Wikipedia pour Superscalar et Pipeline d'instructions sont assez bons.
Il y a longtemps il y a des CPU exécutés ne seule instruction machine à la fois. Ce n'est que lorsqu'elle a été complètement terminée que le CPU a récupéré la prochaine instruction de la mémoire (ou, plus tard, du cache d'instructions).
Finalement, quelqu'un a remarqué que cela signifiait que la plupart des CPU ne faisaient rien la plupart du temps, car il y avait plusieurs sous-unités d'exécution (comme le décodeur d'instructions, l'unité arithmétique entière et FP unité arithmétique) , etc.) et l'exécution d'une instruction n'a occupé qu'un seul d'entre eux à la fois.
Ainsi, " simple " pipelining est né: une fois qu'une instruction a été décodée et a continué vers la prochaine sous-unité d'exécution, pourquoi pas déjà chercher et décoder la prochaine instruction? Si vous aviez 10 de ces " étapes ", alors en ayant chaque étape traiter une instruction différente vous pourriez théoriquement augmenter le débit de l'instruction décuplé sans augmenter l'horloge du processeur du tout! Bien sûr, cela ne fonctionne parfaitement que lorsqu'il n'y a pas de sauts conditionnels dans le code (cela a conduit à beaucoup d'efforts supplémentaires pour gérer les sauts conditionnels spécialement).
Plus tard, la loi de Moore restant correcte plus longtemps que prévu, les fabricants de CPU se sont retrouvés avec toujours plus de transistors à utiliser et ont pensé "pourquoi avoir seulement un de chaque sous-unité d'exécution?". Ainsi, superscalar CPU avec plusieurs sous-unités d'exécution capables de faire la même chose en parallèle sont nés et les conceptions de CPU sont devenues beaucoup, beaucoup plus complexes pour répartir les instructions sur ces unités entièrement parallèles tout en garantissant que les résultats étaient les mêmes que si les instructions avaient été exécutées séquentiellement.
ne analogie: laver les vêtements
Imaginez un magasin de nettoyage à sec avec les installations suivantes: un support pour suspendre les vêtements sales ou propres, une laveuse et une sécheuse (chacune pouvant laver un vêtement à la fois), une table pliante et une planche à repasser.
Le préposé qui fait tout le lavage et le séchage proprement dit est plutôt modeste, de sorte que le propriétaire du magasin, qui prend les commandes de nettoyage à sec, prend un soin particulier à écrire chaque instruction très soigneusement et explicitement.
Au cours d'une journée type, ces instructions peuvent ressembler à:
Le préposé suit ces instructions jusqu'au tee, en faisant très attention à ne jamais rien faire de mal. Comme vous pouvez l'imaginer, il faut beaucoup de temps pour faire la lessive de la journée, car il faut beaucoup de temps pour laver, sécher et plier complètement chaque morceau de linge, et tout doit être fait un à la fois.
Cependant, un jour, le préposé quitte et un nouveau préposé plus intelligent est embauché qui remarque que la plupart des équipements sont inactifs à tout moment de la journée. Pendant que le pantalon séchait, ni la planche à repasser ni la laveuse n'étaient utilisées. Il a donc décidé de mieux utiliser son temps. Ainsi, au lieu de la série d'étapes ci-dessus, il ferait ceci:
C'est du pipelining. Séquencer des activités non liées de telle sorte qu'elles utilisent différents composants en même temps. En gardant autant de différents composants actifs à la fois, vous maximisez l'efficacité et accélérez le temps d'exécution, dans ce cas en réduisant 16 "cycles" à 9, une accélération de plus de 40%.
Maintenant, le petit magasin de nettoyage à sec a commencé à gagner plus d'argent car ils pouvaient travailler beaucoup plus rapidement, alors le propriétaire a acheté une laveuse, une sécheuse, une planche à repasser, une station de pliage supplémentaire et a même embauché un autre préposé. Maintenant, les choses sont encore plus rapides, au lieu de ce qui précède, vous avez:
C'est une conception superscalaire. Plusieurs sous-composants capables de faire la même tâche simultanément, mais avec le processeur décidant comment le faire. Dans ce cas, cela a entraîné une augmentation de vitesse de près de 50% (en 18 "cycles", la nouvelle architecture pouvait parcourir 3 itérations de ce "programme" alors que l'architecture précédente ne pouvait en parcourir que 2).
Les processeurs plus anciens, tels que les 386 ou 486, sont de simples processeurs scalaires, ils exécutent une instruction à la fois exactement dans l'ordre dans lequel elles ont été reçues. Les processeurs grand public modernes depuis le PowerPC/Pentium sont pipelinés et superscalaires. Un processeur Core2 est capable d'exécuter le même code qui a été compilé pour un 486 tout en profitant du parallélisme au niveau des instructions car il contient sa propre logique interne qui analyse le code machine et détermine comment le réorganiser et l'exécuter (ce qui peut être exécuté en parallèle , ce qui ne peut pas, etc.) C'est l'essence même du design superscalaire et pourquoi c'est si pratique.
En revanche, un processeur vectoriel parallèle effectue simultanément des opérations sur plusieurs éléments de données (un vecteur). Ainsi, au lieu d'ajouter simplement x et y, un processeur vectoriel ajouterait, disons, x0, x1, x2 à y0, y1, y2 (résultant en z0, z1, z2). Le problème avec cette conception est qu'elle est étroitement couplée au degré spécifique de parallélisme du processeur. Si vous exécutez du code scalaire sur un processeur vectoriel (en supposant que vous le puissiez), vous ne verriez aucun avantage de la parallélisation vectorielle, car elle doit être explicitement utilisée, de la même manière si vous souhaitez profiter d'un processeur vectoriel plus récent avec plus d'unités de traitement parallèles (par exemple, capable d'ajouter des vecteurs de 12 nombres au lieu de 3), vous devrez recompiler votre code. Les conceptions de processeurs vectoriels étaient populaires dans la plus ancienne génération de superordinateurs car elles étaient faciles à concevoir et il existe de grandes classes de problèmes en science et en ingénierie avec beaucoup de parallélisme naturel.
Les processeurs superscalaires peuvent également avoir la possibilité d'effectuer une exécution spéculative. Plutôt que de laisser les unités de traitement inactives et d'attendre la fin de l'exécution d'un chemin de code avant de brancher un processeur, vous pouvez faire une meilleure estimation et commencer à exécuter le code après la branche avant que le code précédent n'ait terminé le traitement. Lorsque l'exécution du code précédent rattrape le point de branchement, le processeur peut alors comparer la branche réelle avec la supposition de branche et soit continuer si la supposition était correcte (déjà bien en avance par rapport à ce qu'elle aurait été en attendant simplement) ou elle peut invalider les résultats de l'exécution spéculative et exécuter le code de la branche correcte.
Le pipeline est ce que fait un constructeur automobile dans la fabrication de ses voitures. Ils décomposent le processus de montage d'une voiture en étapes et effectuent les différentes étapes à différents points le long d'une chaîne de montage réalisée par différentes personnes. Le résultat net est que la voiture est fabriquée exactement à la vitesse de l'étape la plus lente.
Dans les processeurs, le processus de pipelining est exactement le même. Une "instruction" est décomposée en différentes étapes d'exécution, généralement quelque chose comme 1. l'instruction fetch, 2. les opérandes fetch (registres ou valeurs de mémoire qui sont lus), 2. effectuer le calcul, 3. écrire les résultats (dans la mémoire ou les registres) . La plus lente de celles-ci pourrait être la partie calcul, auquel cas la vitesse de débit globale des instructions via ce pipeline est juste la vitesse de la partie calcul (comme si les autres parties étaient "libres").
Super-scalaire dans les microprocesseurs se réfère à la possibilité d'exécuter plusieurs instructions à partir d'un même flux d'exécution à la fois en parallèle. Donc, si un constructeur automobile exploitait deux chaînes de montage, il est évident qu’elles pourraient produire deux fois plus de voitures. Mais si le processus de mise d'un numéro de série sur la voiture était à la dernière étape et devait être fait par une seule personne, alors ils devraient alterner entre les deux pipelines et garantir qu'ils pourraient chacun faire en moins de la moitié du temps de l'étape la plus lente afin d'éviter de devenir eux-mêmes l'étape la plus lente.
Super-scalaire dans les microprocesseurs est similaire mais a généralement beaucoup plus de restrictions. Ainsi, l'étape de récupération des instructions produira généralement plus d'une instruction au cours de sa phase - c'est ce qui rend super-scalaire dans les microprocesseurs possible. Il y aurait alors deux étapes d'extraction, deux étapes d'exécution et deux étapes d'écriture différée. De toute évidence, cela se généralise à plus de deux pipelines.
Tout cela est beau et dandy, mais du point de vue d'une bonne exécution, les deux techniques peuvent entraîner des problèmes si elles sont appliquées à l'aveugle. Pour une exécution correcte d'un programme, il est supposé que les instructions sont exécutées complètement l'une après l'autre dans l'ordre. Si deux instructions séquentielles ont des calculs interdépendants ou utilisent les mêmes registres, il peut y avoir un problème. L'instruction ultérieure doit attendre la fin de la réécriture de l'instruction précédente avant de pouvoir exécuter l'étape de récupération d'opérande. Ainsi, vous devez bloquer la deuxième instruction de deux étapes avant de l'exécuter, ce qui va à l'encontre de l'objectif de ce qui a été gagné par ces techniques en premier lieu.
Il existe de nombreuses techniques utilisées pour réduire le problème du décrochage qui sont un peu compliquées à décrire, mais je vais les énumérer: 1. enregistrement de transfert, (également stocker pour charger le transfert) 2. changement de nom de registre, 3. tableau de bord, 4 exécution dans le désordre. 5. Exécution spéculative avec restauration (et retrait) Tous les processeurs modernes utilisent à peu près toutes ces techniques pour implémenter le super-scalaire et le pipelining. Cependant, ces techniques ont tendance à avoir des rendements décroissants par rapport au nombre de pipelines dans un processeur avant que les décrochages ne deviennent inévitables. En pratique, aucun fabricant de CPU ne fabrique plus de 4 pipelines dans un seul cœur.
Le multicœur n'a rien à voir avec aucune de ces techniques. Il s'agit essentiellement de ramener deux microprocesseurs ensemble pour implémenter un multitraitement symétrique sur une seule puce et de partager uniquement les composants qui ont du sens à partager (généralement le cache L3 et les E/S). Cependant, une technique qu'Intel appelle "hyperthreading" est une méthode pour essayer d'implémenter virtuellement la sémantique du multicœur dans le cadre super-scalaire d'un seul cœur. Ainsi, une seule micro-architecture contient les registres de deux (ou plus) cœurs virtuels et récupère les instructions de deux (ou plus) flux d'exécution différents, mais s'exécutant à partir d'un système super-scalaire commun. L'idée est que parce que les registres ne peuvent pas interférer les uns avec les autres, il y aura généralement plus de parallélisme conduisant à moins de décrochages. Donc, plutôt que d'exécuter simplement deux flux d'exécution de cœur virtuel à la moitié de la vitesse, c'est mieux en raison de la réduction globale des blocages. Cela semblerait suggérer qu'Intel pourrait augmenter le nombre de pipelines. Cependant, cette technique s'est avérée quelque peu absente des implémentations pratiques. Comme il fait partie intégrante des techniques super-scalaires, je l'ai quand même mentionné.
Le pipelining est l'exécution simultanée de différentes étapes de plusieurs instructions au même cycle. Il est basé sur la division du traitement des instructions en étapes et sur des unités spécialisées pour chaque étape et des registres pour stocker les résultats intermédiaires.
La super-échelle envoie plusieurs instructions (ou micro-instructions) à plusieurs unités d'exécution existantes dans le CPU. Il repose donc sur des unités redondantes en CPU.
Bien sûr, ces approches peuvent se compléter.