Nouvelles instructions des processeurs

Le problème exposé dans ce sujet a été résolu.

Bonjour,

je me demandais pourquoi l'on enrichissait les jeux d'instructions des nouveaux processeurs qui feront fonctionner des programmes qui se doivent de rester compatibles avec le jeu d'instructions pour lequel ils sont faits (par exemple le x86-64), et qui donc n'utilisent pas ces nouvelles instructions. Et je me demandais aussi comment cela se traduisait en assembleur. De nouveaux mots mnémoniques ? Pour le peu de code que j'ai vu en assembleur, je n'ai pas vu une grande variété d'instructions, pourtant, j'ai appris qu'il en existait une centaine pour les processeurs courants.

je me demandais pourquoi l'on enrichissait les jeux d'instructions des nouveaux processeurs qui feront fonctionner des programmes qui se doivent de rester compatibles avec le jeu d'instructions pour lequel ils sont faits (par exemple le x86-64), et qui donc n'utilisent pas ces nouvelles instructions.

jtruc34

Marketing + les constructeurs ont tellement de transistors qu'ils savent plus quoi en foutre = plein de nouvelles instructions pas forcément très utiles, sauf pour quelques développeurs de jeux vidéo ou de codecs, voire le calcul scientifique.

Et je me demandais aussi comment cela se traduisait en assembleur. De nouveaux mots mnémoniques ? Pour le peu de code que j'ai vu en assembleur, je n'ai pas vu une grande variété d'instructions, pourtant, j'ai appris qu'il en existait une centaine pour les processeurs courants.

jtruc34

Nouvelles mnémoniques, potentiellement de nouveaux noms de registres. Faut lire les documentations d'Intel et AMD.

+0 -0

Et tant qu'à faire, en parlant de mnémoniques, peut-on dire qu'une mnémonique est systématiquement traduite en une seule instruction ? Je pense par exemple à push qui fait deux choses, le processeur doit sans doute en lire deux aussi.

Merci beaucoup de m'avoir répondu aussi rapidement !

+0 -0

je me demandais pourquoi l'on enrichissait les jeux d'instructions des nouveaux processeurs

Il y a plusieurs raisons à cela. Globalement les processeurs ont de plus en plus de transistors. Car la surface d'une génération à l'autre est souvent constante quand la finesse de gravure augmente. Ces transistors, il faut bien s'en servir. Ces instructions supplémentaires en font partis.

Ajouter des instructions permet plusieurs choses. Déjà les processeurs compatibles x86 et x86_64 ont eu avec le temps des fonctionnalités totalement nouvelles. Pour les exploiter, il fallait l'ajout de nouvelles instructions. Par exemple il y a tout ce qui concerne les calculs sur des vecteurs, la cryptographie gérée par le processeur (comme calculer un SHA-256 de manière matérielle), etc.

L'autre peut être une raison d'optimisation, c'est-à-dire faire en sorte que certaines instructions « courantes » se résument une une instruction. Le code est plus court et le matériel génèrerait ces cas plus rapidement.

feront fonctionner des programmes qui se doivent de rester compatibles avec le jeu d'instructions pour lequel ils sont faits (par exemple le x86-64), et qui donc n'utilisent pas ces nouvelles instructions.

De nombreux programmes n'exploitent pas ces instructions, par manque d'usage mais aussi pour la raison de compatibilité. Ce n'est cependant pas du tout le cas pour tous. Certains programmes exploitent des instructions modernes. Globalement tous les programmes nécessitant de la 3D poussée (les jeux vidéo ou Blender par exemple) vont utiliser des extensions du jeu d'instruction x86 : le SSE (dont il y a plusieurs versions). Le SSE apporte en effet beaucoup d'intérêts pour les calculs lourds que nécessitent la 3D et certains programmes jugent suffisamment utile pour ne plus être compatibles avec ceux qui ne le supportent pas.

Ceux qui font des programmes maisons, comme de nombreux laboratoires, peuvent aussi se permettre de réduire la compatibilité pour des raisons de performances. Bref, c'est au choix de chaque programme de déterminer ce qu'il faut faire. Après tout la compatibilité du tout premier x86 n'est plus forcément très pertinent…

Tout cela est géré par le compilateur, GCC te permettant de décider si tu veux telle ou telle extension ou non.

Et je me demandais aussi comment cela se traduisait en assembleur. De nouveaux mots mnémoniques ?

Oui. Après l'assembleur peut transformer ces mnémoniques en d'autres plus élémentaires comme une sorte de Macro. Cela dépend de l'assembleur et de l'instruction considérée.

Pour le peu de code que j'ai vu en assembleur, je n'ai pas vu une grande variété d'instructions, pourtant, j'ai appris qu'il en existait une centaine pour les processeurs courants.

Car beaucoup de ces instructions sont utiles dans des cas assez restreints. D'autres sont en général dans des programmes assez compliqués pour que la lecture du code assembleur résultant ne soit pas vraiment pertinent. En général ces extensions sont exploitées par le compilateur et non le programmeur assembleur lui même. D'où le fait que tu les vois rarement quand on t'enseigne cela, ou pour les programmes habituellement conçus par ceux qui exploitent l'assembleur à la main.

Et c'est comme pour toute nouveauté, il faut du temps pour qu'un nouveau mnémonique se répande. Pour des raisons de compatibilité d'une part, mais de disponibilité des outils pour l'exploiter d'autre part.

+0 -0

Merci ! À cela arrive une question : comment le compilateur fait-il pour savoir qu'il peut être utile d'utiliser ces instructions spécialisées ? Le programmeur doit écrire du code déjà spécialisé avant la compilation ? Et deuxièmement : ces programmes qui utilisent des nouvelles instructions, ils sont aussi distribués sous l'unique terme x86 par exemple ? Je ne sais pas s'ils fonctionneront sur mon ordi avant de les avoir essayés ? Si je prends SSE, il me semble que tous les processeurs actuels sous le noms x86 le connaissent. Mais y a-t-il des extensions plus récentes des jeux d'instructions des derniers processeurs grand public qui soient utilisées ? Troisièmement : est-il possible, en programmation haut-niveau, de profiter pleinement des avantages des nouveautés des processeurs, dès lors que les compilateurs sont adaptés ? Ou ce n'est accessible qu'en assembleur ? Cela rejoint un peu la première question.

Excusez-moi, les questions arrivent en vrac, mais apprenant de nouvelles choses en apparaissent de nouvelles.

+0 -0

À cela arrive une question : comment le compilateur fait-il pour savoir qu'il peut être utile d'utiliser ces instructions spécialisées ?

Le compilateur a d'une part une liste de mnémoniques disponibles et de l'autre un code source, il essaye de décomposer le code source en mnémoniques qu'il a de disponible. Après, la liste des mnémoniques disponibles dépend de la machine cible et de ce que le programmeur lui a demandé (s'il a refusé ou pas certaines extensions du jeu d'instruction par exemple).

Et deuxièmement : ces programmes qui utilisent des nouvelles instructions, ils sont aussi distribués sous l'unique terme x86 par exemple ?

Oui.

Je ne sais pas s'ils fonctionneront sur mon ordi avant de les avoir essayés ?

Si tu peux, en général les programmes précisent le matériel minimum recommandé ou requis pour fonctionner. Dans ces clauses là figurent souvent ce genre de précisions de manière directe ou discrète.

Après normalement tout cela est testé au lancement, si tu lances un programme avec des instructions SSE sur une machine ne le supportant pas, tu auras un message d'erreur. Après si le programme est mal fait, l'erreur pourrait être plus conséquent.

Mais y a-t-il des extensions plus récentes des jeux d'instructions des derniers processeurs grand public qui soient utilisées ?

Le SSE5 n'est pas totalement répandue par exemple.

Excusez-moi, les questions arrivent en vrac, mais apprenant de nouvelles choses en apparaissent de nouvelles.

Tu verras rapidement que ce processus est infini. Un être curieux trouvera toujours de nouvelles questions. ;)

EDIT :

Troisièmement : est-il possible, en programmation haut-niveau, de profiter pleinement des avantages des nouveautés des processeurs, dès lors que les compilateurs sont adaptés ? Ou ce n'est accessible qu'en assembleur ? Cela rejoint un peu la première question.

Normalement c'est le cas. Je n'ai pas de contre exemple en tête en tout cas.

+1 -0

j'ai appris qu'il en existait une centaine pour les processeurs courants.

Pour la famille x86, on en est plutôt à un bon millier, en fait.

Sinon, la quasi-totalité des instructions introduites dans la famille x86 depuis 2003 et l'arrivée de processeurs 64 bits sont des instructions dites SIMD : une instruction unique permet de réaliser la même opération en parallèle sur plusieurs jeux de données. Et année après année, il est possible de réaliser de plus en plus d'opérations d'un coup, même si ces opérations restent globalement les mêmes d'une génération à l'autre.

+0 -0

Et donc, c'est grâce aux mises-à-jour des compilateurs que l'on peut les utiliser sans s'en rendre compte ? Auriez-vous un exemple de code en langage plus haut-niveau que l'assembleur qui, compilé, ne donnerait pas le même langage machine entre deux évolutions du jeu d'instructions x86 ?

+0 -0

Salut,

Et donc, c'est grâce aux mises-à-jour des compilateurs que l'on peut les utiliser sans s'en rendre compte ? Auriez-vous un exemple de code en langage plus haut-niveau que l'assembleur qui, compilé, ne donnerait pas le même langage machine entre deux évolutions du jeu d'instructions x86 ?

jtruc34

Un simple calcul entre nombres flottants sera différent entre un vieux processeur x86 qui ne disposera que des instructions x87 et un plus récent qui, comme précisé par mes VDDs, utilisera les instructions SSE.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <stdio.h>


int
main(void)
{
        double a = 56.7;
        double b = 3.;

        printf("%f\n", a * b);
        return 0;
}

Avec des instructions SSE (ici movsd et mulsd), cela donne ceci.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
    .section    .rodata
.LC2:
    .string "%f\n"
    .text
    .globl  main
main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movabsq $4633176632899246490, %rax
    movq    %rax, -8(%rbp)
    movabsq $4613937818241073152, %rax
    movq    %rax, -16(%rbp)
    movsd   -8(%rbp), %xmm0
    mulsd   -16(%rbp), %xmm0
    movl    $.LC2, %edi
    movl    $1, %eax
    call    printf
    movl    $0, %eax
    leave
    ret

Avec des instructions x87 (ici fldl, fmull et fstpl), cela donne cela.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    .section    .rodata
.LC2:
    .string "%f\n"
    .text
    .globl  main
main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movabsq $4633176632899246490, %rax
    movq    %rax, -8(%rbp)
    movabsq $4613937818241073152, %rax
    movq    %rax, -16(%rbp)
    fldl    -8(%rbp)
    fmull   -16(%rbp)
    subq    $8, %rsp
    leaq    -8(%rsp), %rsp
    fstpl   (%rsp)
    movl    $.LC2, %edi
    movl    $0, %eax
    call    printf
    addq    $16, %rsp
    movl    $0, %eax
    leave
    ret

NB : les exemple ont été réalisés avec un processeur de la famille x86_64.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte