Les guerres entre RISC et CISC à la fin des années 1990 ont disparu depuis longtemps, et on pense aujourd'hui que la différence entre RISC et CISC est totalement hors de propos. De nombreuses personnes affirment que les jeux de commandes ne sont pas pertinents.
Cependant, les jeux de commandes sont en fait importants. Ils imposent des restrictions sur les types d'optimisations qui peuvent ĂȘtre facilement ajoutĂ©s au microprocesseur.
J'ai récemment examiné de plus prÚs les informations sur l'architecture du jeu d'instructions RISC-V (ISA), et voici quelques-uns des aspects qui m'ont vraiment impressionné à propos du RISC-V ISA:
- Il s'agit d'un petit jeu de commandes RISC facile à apprendre. TrÚs préféré pour ceux qui souhaitent acquérir des connaissances sur les microprocesseurs.
- , , .
- CPU ISA RISC-V.
- , , RISC-V.
RISC
En commençant Ă mieux comprendre RISC-V, j'ai rĂ©alisĂ© que RISC-V s'est avĂ©rĂ© ĂȘtre un retour radical Ă ce que beaucoup croyaient ĂȘtre une Ăšre rĂ©volue de l'informatique. Du point de vue de la conception, RISC-V sur une machine similaire Ă la durĂ©e de mouvement Ă un classique R Ă©duquĂ© I nstruction S et C omputer (RISC, «ordinateur avec un ensemble de commandes courtes") au dĂ©but des annĂ©es 80 et 90.
Ces derniÚres années, beaucoup ont fait valoir que la division en RISC et CISC n'avait plus de sens, car tant d'instructions ont été ajoutées aux processeurs RISC comme ARM, et si beaucoup d'entre elles sont assez complexes, qu'au stade actuel, il s'agit plus d'un processeur hybride que d'un pur processeur RISC. Des considérations similaires ont été appliquées à d'autres processeurs RISC tels que le PowerPC.
RISC-V, d'autre part, est un représentant véritablement «hardcore» des processeurs RISC. Si vous lisez les discussions sur RISC-V sur Internet, vous trouverez des gens affirmant que RISC-V a été développé par des radicaux RISC de la vieille école qui refusent de suivre le rythme.
L'ancien ingénieur ARM Erin Shepherd a écrit une critique intéressante du RISC-V il y a quelques années :
ISA RISC-V . , .. (, , ) , .
Je vais donner un peu de contexte briÚvement. La petite taille du code présente un avantage en termes de performances car elle facilite le stockage du code exécutable dans le cache haute vitesse du processeur.
La critique ici est que les concepteurs de RISC-V se sont trop concentrés sur la fourniture d'un petit jeu d'instructions. AprÚs tout, c'est l'un des objectifs originaux du RISC.
Selon Erin, la conséquence en était qu'un vrai programme aurait besoin de beaucoup plus d'instructions pour accomplir des tùches, c'est-à -dire qu'il prendrait plus d'espace mémoire.
Traditionnellement, pendant de nombreuses annĂ©es, on croyait que davantage d'instructions devraient ĂȘtre ajoutĂ©es au processeur RISC pour le rendre plus similaire au CISC. L'idĂ©e est que des commandes plus spĂ©cialisĂ©es peuvent remplacer l'utilisation de plusieurs commandes courantes.
Compression de commandes et fusion de macro-opérations
Cependant, il existe deux innovations dans l'architecture du processeur qui rendent cette stratégie d'ajout d'instructions plus complexes, à bien des égards, redondante:
- Instructions compressées - Les instructions sont compressées en mémoire et décompressées dans la premiÚre étape du processeur.
- Fusion de macro-opération - Deux instructions simples ou plus sont lues par le processeur et fusionnées en une instruction plus complexe.
En fait, ARM utilise déjà ces deux stratégies, et les processeurs x86 utilisent cette derniÚre, donc RISC-V ne fait aucune nouvelle astuce ici.
Cependant, il y a ici une subtilité: RISC-V profite beaucoup plus de ces deux stratégies pour deux raisons importantes:
- Les commandes compressées ont été ajoutées initialement. D'autres architectures, comme ARM, y ont réfléchi plus tard et les ont vissées de maniÚre assez hùtive.
- C'est là que se justifie l'obsession de RISC pour un petit nombre d'équipes uniques. Il reste simplement plus d'espace pour ajouter des commandes compressées.
Le deuxiĂšme point nĂ©cessite quelques Ă©claircissements. Dans les architectures RISC, les commandes ont gĂ©nĂ©ralement une largeur de 32 bits. Ces bits doivent ĂȘtre utilisĂ©s pour coder diverses informations. Disons que nous avons une commande comme celle-ci (il y a des commentaires aprĂšs le point-virgule):
ADD x1, x4, x8 ; x1 â x4 + x8
Il ajoute le contenu des registres
x4
et
x8
stocke le résultat dans
x1
. Le nombre de bits requis pour coder cette instruction dĂ©pend du nombre de registres disponibles. RISC-V et ARM ont 32 registres. Le nombre 32 peut ĂȘtre exprimĂ© en 5 bits:
2â” = 32
Puisque la commande doit spécifier trois registres différents, un total de 15 bits (3 à 5) est nécessaire pour coder les opérandes (données d'entrée pour l'opération d'addition).
Par conséquent, plus nous voulons prendre en charge de fonctionnalités dans le jeu d'instructions, plus nous prendrons de bits sur les 32 bits dont nous disposons. Bien sûr, nous pouvons passer aux commandes 64 bits, mais cela consommera trop de mémoire, ce qui signifie que les performances en pùtiront.
Dans un effort agressif pour rĂ©duire le nombre d'instructions, RISC-V laisse plus de place pour ajouter des bits pour indiquer que nous utilisons des instructions compressĂ©es. Si le processeur voit que certains bits sont dĂ©finis dans la commande, il comprend alors qu'il doit ĂȘtre interprĂ©tĂ© comme compressĂ©.
Cela signifie qu'au lieu de coller 32 bits d'une instruction Ă l'intĂ©rieur, nous pouvons insĂ©rer deux instructions de 16 bits chacune. Naturellement, toutes les commandes RISC-V ne peuvent pas ĂȘtre exprimĂ©es au format 16 bits. Par consĂ©quent, un sous-ensemble d'instructions 32 bits est sĂ©lectionnĂ© en fonction de leur utilitĂ© et de leur frĂ©quence d'utilisation. Alors que les instructions non compressĂ©es peuvent recevoir 3 opĂ©randes (donnĂ©es d'entrĂ©e), les instructions compressĂ©es ne peuvent recevoir que 2 opĂ©randes. Autrement dit, la commande compressĂ©e
ADD
ressemblera Ă ceci:
C.ADD x4, x8 ; x4 â x4 + x8
Le code d'assemblage RISC-V utilise un préfixe
C.
pour indiquer que la commande doit ĂȘtre assemblĂ©e dans une commande compressĂ©e.
Essentiellement, les instructions compressées réduisent le nombre d'opérandes. Trois registres d'opérandes prendraient 15 bits, laissant seulement 1 bit pour indiquer l'opération! Ainsi, lorsque vous utilisez deux opérandes pour indiquer l'opcode (l'opération à effectuer), il nous reste 6 bits.
C'est en fait proche du fonctionnement de l'assembleur x86 lorsque pas assez de bits sont réservés pour utiliser les trois registres d'opérandes. Le processeur x86 gaspille des bits pour permettre, par exemple, à la commande de
ADD
lire les données entrantes de la mémoire et des registres.
Cependant, le vrainous bénéficions de la combinaison de la compression de commande et de la fusion de macro-opération. Lorsque le processeur reçoit un mot de 32 bits contenant deux instructions compressées de 16 bits, il peut les fusionner en une instruction plus complexe.
Cela semble absurde - sommes-nous revenus à notre point de départ?
Non, car nous contournons le besoin de remplir la spécification ISA avec un tas d'instructions complexes (c'est-à -dire que la stratégie ARM suit). Au lieu de cela, nous exprimons, par essence, toute une série de commandes complexes indirectement , à travers diverses combinaisons de commandes simples.
Dans des circonstances normales, la macro-fusion poserait un problÚme: bien que deux instructions soient remplacées par une, elles occupent toujours deux fois plus de mémoire. Cependant, lors de la compression des commandes, nous ne prenons pas d'espace supplémentaire. Nous profitons des deux architectures.
Regardons l'un des exemples donnés par Erin Shepherd. Dans son article critique sur ISA RISC-V, elle montre une fonction simple en C.Pour clarifier les choses, j'ai pris la liberté de la réécrire:
int get_index(int *array, int i) {
return array[i];
}
Sur x86, cela compilera le code d'assembly suivant:
mov eax, [rdi+rsi*4]
ret
Lorsqu'une fonction est appelée dans un langage de programmation, les arguments sont généralement passés à la fonction dans un registre selon un ordre établi qui dépend du jeu d'instructions utilisé. Sur x86, le premier argument est placé dans un registre
rdi
, le second dans
rsi
. Par dĂ©faut, les valeurs de retour doivent ĂȘtre placĂ©es dans un registre
eax
.
La premiĂšre commande multiplie le contenu
rsi
par 4. Elle contient une variable
i
. Pourquoi se multiplie-t-il? Parce qu'il se
array
compose d'éléments entiers séparés par 4 octets. Par conséquent, le troisiÚme élément du tableau est à un décalage de 3 à 4 = 12 octets.
Ensuite, nous ajoutons ceci Ă
rdi
qui contient l'adresse de base
array
... Cela nous donne l'adresse finale du
i
e élément
array
. Nous lisons le contenu de la cellule mémoire à cette adresse et le stockons dans
eax
: tùche terminée.
Sur ARM, tout se passe de la mĂȘme maniĂšre:
LDR r0, [r0, r1, lsl #2]
BX lr ;return
Ici, nous ne multiplions pas par 4, mais décalons le registre de
r1
2 bits vers la gauche, ce qui équivaut à multiplier par 4. C'est probablement une description plus précise de ce qui se passe sur x86. Je doute qu'il soit possible de multiplier par tout ce qui n'est pas un multiple de 2, car la multiplication est une opération assez compliquée et le déplacement est peu coûteux et facile.
D'aprĂšs ma description de x86, le reste est Ă deviner. Passons maintenant Ă RISC-V, oĂč le vrai plaisir commence! (les commentaires commencent par un point-virgule)
SLLI a1, a1, 2 ; a1 â a1 << 2
ADD a0, a0, a1 ; a0 â a0 + a1
LW a0, a0, 0 ; a0 â [a0 + 0]
RET
Sur RISC-V, les registres
a0
et
a1
sont simplement des alias pour
x10
et
x11
. C'est là que sont placés les premier et deuxiÚme arguments de l'appel de fonction.
RET
Est une pseudo-commande (raccourci):
JALR x0, 0(ra) ; sp â 0 + ra
; x0 â sp + 4 ignoring result
JALR
accÚde à l'adresse stockée
ra
qui fait référence à l'adresse de retour.
ra
Est un pseudonyme
x1
.
Et tout cela a l'air absolument terrible, non? Deux fois plus de commandes pour une opération simple et couramment utilisée, comme effectuer une recherche d'index sur une table et renvoyer un résultat.
Ăa a vraiment l'air mauvais. C'est pourquoi Erin Shepherd a Ă©tĂ© extrĂȘmement critique Ă l'Ă©gard des dĂ©cisions de conception prises par les dĂ©veloppeurs RISC-V. Elle Ă©crit:
Les simplifications de RISC-V simplifient le décodeur (c'est-à -dire le processeur frontal), mais cela se fait au prix de plus d'instructions. Cependant, la mise à l'échelle de la largeur du pipeline est une tùche délicate, tandis que le décodage de quelques instructions (ou trÚs) inhabituelles est bien étudié (les principales difficultés surviennent lors de la détermination de la longueur de la commande n'est pas triviale - en raison de ses préfixes infinis, x86 est un cas particuliÚrement négligé).
Cependant, grĂące Ă la compression des commandes et Ă la fusion macro-op, la situation peut ĂȘtre amĂ©liorĂ©e.
C.SLLI a1, 2 ; a1 â a1 << 2
C.ADD a0, a1 ; a0 â a0 + a1
C.LW a0, a0, 0 ; a0 â [a0 + 0]
C.JR ra
DĂ©sormais, les instructions occupent exactement la mĂȘme quantitĂ© d'espace mĂ©moire que l'exemple d'ARM.
Ok, maintenant faisons la fusion macro-op !
L'une des conditions pour que RISC-V autorise les opérations de fusion en une seule est que le registre cible correspond . Cette condition est remplie pour les commandes
ADD
et
LW
(mot de chargement, "mot de chargement"). Par conséquent, le processeur les transformera en une seule instruction.
Si cette condition Ă©tait remplie pour SLLI, nous pourrions fusionner les trois commandes en une seule . Autrement dit, le processeur verrait quelque chose qui ressemble Ă une instruction ARM plus complexe:
LDR r0, [r0, r1, lsl #2]
Mais pourquoi ne pourrions-nous pas écrire cette opération de macro complexe directement dans le code?
Parce que ISA ne prend pas en charge une telle opération de macro! Rappelez-vous que nous avons un nombre limité de bits. Alors rallongons les commandes! Non, cela prendra trop de mémoire et débordera plus rapidement le précieux cache du processeur.
Cependant, si nous émettons ces instructions longues et semi-complexes à l'intérieur du processeur, aucun problÚme ne se pose. Un processeur n'a jamais plus de quelques centaines d'instructions à la fois. Par conséquent, si nous dépensons pour chaque commande, disons 128 bits, cela ne créera pas de difficultés. Il y aura encore assez de silicium pour tout.
Lorsqu'un dĂ©codeur reçoit une commande ordinaire, il la transforme gĂ©nĂ©ralement en une ou plusieurs micro-opĂ©rations. Ces micro-opĂ©rations sont les instructions avec lesquelles le processeur fonctionne rĂ©ellement. Ils peuvent ĂȘtre trĂšs larges et contenir de nombreuses informations utiles supplĂ©mentaires. Le prĂ©fixe "micro" semble ironique, car ils sont plus larges. Cependant, en rĂ©alitĂ©, «micro» signifie qu'ils ont un nombre limitĂ© de tĂąches.
La fusion de macro-opération bouleverse un peu le travail du décodeur: au lieu de transformer une commande en plusieurs micro-opérations, nous prenons de nombreuses opérations et les transformons en une seule micro-opération.
Autrement dit, ce qui se passe dans un processeur moderne peut sembler plutĂŽt Ă©trange:
- PremiĂšrement, il combine les deux Ă©quipes en une seule en utilisant la compression .
- Il les divise ensuite en deux à l'aide du déballage .
- Il les combine ensuite en une seule opération en utilisant la fusion macro-op .
D'autres commandes peuvent ĂȘtre divisĂ©es en plusieurs micro-opĂ©rations, plutĂŽt que fusionnĂ©es. Pourquoi certaines Ă©quipes fusionnent-elles tandis que d'autres se sĂ©parent? Y a-t-il un systĂšme dans cette folie?
Un aspect clé de la transition vers les micro-opérations est le niveau de complexité requis:
- Pas trop complexe, car sinon ils ne pourront pas terminer dans un nombre fixe de cycles d'horloge alloués à chaque commande.
- Pas trop simple, sinon nous gaspillerons simplement les ressources du processeur. Faire deux micro-opérations prendra deux fois plus de temps qu'une seule.
Tout a commencĂ© avec les processeurs CISC. Intel a commencĂ© Ă diviser ses instructions CISC complexes en micro-opĂ©rations pour les rendre plus faciles Ă insĂ©rer dans des pipelines de processeurs comme les instructions RISC. Cependant, dans les constructions ultĂ©rieures, les dĂ©veloppeurs ont rĂ©alisĂ© que de nombreuses Ă©quipes du SCRC pouvaient ĂȘtre fusionnĂ©es en une Ă©quipe modĂ©rĂ©ment complexe. S'il y a moins de commandes Ă exĂ©cuter, le travail sera terminĂ© plus rapidement.
Avantages obtenus
Nous avons discutĂ© de nombreux dĂ©tails, donc maintenant, il doit ĂȘtre difficile pour vous de comprendre ce que signifie tout ce travail. Ă quoi sert toute cette compression et cette fusion? Ils semblent faire beaucoup de travail inutile.
PremiÚrement, la compression des commandes est complÚtement différente de la compression du zip. Le mot «compression» est un peu trompeur car la compression ou la décompression instantanée d'une commande est tout à fait simple. Aucun temps n'est perdu à ce sujet.
Il en va de mĂȘme pour la fusion de macro-opĂ©ration. Bien que ce processus puisse sembler compliquĂ©, des systĂšmes similaires sont dĂ©jĂ utilisĂ©s dans les microprocesseurs modernes. Par consĂ©quent, les coĂ»ts que toute cette complexitĂ© ajoute ont dĂ©jĂ Ă©tĂ© payĂ©s.
Cependant, contrairement aux concepteurs d'ARM, MIPS et x86, lorsqu'ils ont commencé à concevoir leur ISA, les créateurs de RISC-V connaissaient la compression des commandes et la fusion des macro-opérations. Grùce à divers tests avec le premier jeu d'instructions minimal, ils ont fait deux découvertes importantes:
- Les programmes RISC-V occupent gĂ©nĂ©ralement Ă peu prĂšs le mĂȘme ou moins d'espace mĂ©moire que toute autre architecture de processeur. Y compris x86, qui devrait utiliser la mĂ©moire efficacement, Ă©tant donnĂ© qu'il s'agit d'ISA CISC.
- Il doit effectuer moins de micro-opérations que les autres ISA.
En fait, en concevant l'ensemble d'instructions de base avec la fusion à l'esprit, ils ont pu fusionner suffisamment d'instructions pour que le processeur de tout programme doive effectuer moins de micro-opérations que les processeurs concurrents.
Cela a incitĂ© l'Ă©quipe de dĂ©veloppement RISC-V Ă redoubler d'efforts pour mettre en Ćuvre la fusion macro-opĂ©rationnelle en tant que stratĂ©gie fondamentale RISC-V. Le manuel RISC-V contient de nombreuses notes sur les opĂ©rations avec lesquelles vous pouvez fusionner. Il comprend Ă©galement des correctifs pour faciliter la fusion des commandes trouvĂ©es dans les modĂšles courants.
Le petit ISA facilite l'apprentissage des Ă©tudiants. Cela signifie qu'il est plus facile pour un Ă©tudiant en architecture de processeur de concevoir son propre processeur fonctionnant sur des instructions RISC-V. Il convient de rappeler que la compression de commande et la fusion macro-op sont facultatives.
RISC-V a un petit jeu de commandes fondamentales qui doit ĂȘtre implĂ©mentĂ©. Cependant, toutes les autres commandes sont implĂ©mentĂ©es dans le cadre des extensions. Les commandes compressĂ©es ne sont qu'une extension facultative.
La fusion macro-op n'est que l'optimisation. Il ne change pas de comportement en gĂ©nĂ©ral et n'a donc pas besoin d'ĂȘtre implĂ©mentĂ© dans votre propre processeur RISC-V.
Stratégie de conception RISC-V
RISC-V a pris tout ce que nous savons sur les processeurs modernes aujourd'hui et a utilisé ces connaissances pour concevoir des processeurs ISA. Par exemple, nous savons que:
- Les cĆurs de processeur actuels ont un systĂšme de prĂ©diction de branche sophistiquĂ©.
- Les cĆurs de processeur sont superscalaires, c'est-Ă -dire qu'ils exĂ©cutent de nombreuses instructions en parallĂšle.
- Pour assurer la superscalarité, l'exécution des commandes avec un changement d'ordre (exécution dans le désordre) est utilisée.
- Ils ont des convoyeurs.
Cela signifie que des fonctionnalités telles que l'exécution conditionnelle prise en charge par ARM ne sont plus nécessaires. La prise en charge de cette fonction par ARM ronge des bits du format d'instruction. RISC-V peut sauvegarder ces bits.
L'exĂ©cution conditionnelle a Ă©tĂ© conçue Ă l'origine pour Ă©viter les fourchettes, car elles sont mauvaises pour les pipelines. Pour accĂ©lĂ©rer le travail du processeur, il reçoit gĂ©nĂ©ralement Ă l'avance les commandes suivantes, de sorte qu'immĂ©diatement aprĂšs l'exĂ©cution de la prĂ©cĂ©dente, Ă la premiĂšre Ă©tape du processeur, la suivante peut ĂȘtre captĂ©e.
Avec le branchement conditionnel, nous ne pouvons pas savoir Ă l'avance oĂč se trouvera la prochaine commande lorsque nous commencerons Ă remplir le pipeline. Cependant, un processeur superscalaire peut simplement exĂ©cuter les deux branches en parallĂšle.
C'est pour cette raison que RISV-C n'a pas non plus de registres d'état, car ils créent des dépendances entre les commandes. Plus chaque commande est indépendante, plus il est facile de l'exécuter en parallÚle avec une autre commande.
Fondamentalement, la stratégie RISC-V est que nous pouvons rendre ISA aussi simple que possible et l'implémentation minimale du processeur RISC-V aussi simple que possible sans avoir besoin de décisions de conception qui rendraient impossible la création d'un processeur haute performance.
La publicité
Notre société propose des serveurs non seulement avec des processeurs Intel, mais également des serveurs avec des processeurs AMD EPYC. Comme pour les autres types de serveurs, il existe une vaste sélection de systÚmes d'exploitation pour une installation automatique, il est possible d'installer n'importe quel systÚme d'exploitation à partir de votre propre image. Essayez-le maintenant!