Connexion
Abonnez-vous

Linus Torvalds critique violemment les « niveaux » introduits pour l’architecture x86

Le 06 décembre à 15h40

Les niveaux de l'architecture x86 ont été introduits il y a un peu plus de quatre ans par Red Hat, en partenariat avec Intel, AMD et SUSE. L’intention était bonne : apposer un niveau, ou version, à un processeur en fonction des jeux d’instructions optionnels qu’il supporte.

Ce classement est chronologique :

  • x86-64-v1 : CMOV, CX8, FPU, FXSR, MMX, OSFXSR, SCE, SSE, SSE2
  • x86-64-v2 : CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4_1, SSE4_2, SSSE3
  • x86-64-v3 : AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, OSXSAVE
  • x86-64-v4 : AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL

En d’autres termes, plus un processeur est récent, plus il supporte d’instructions, plus son niveau est élevé. C’est ce classement que Linus Torvalds critique, sans prendre de gants, devant l’idée de l’introduire dans une future version de KConfig, un utilitaire présent dans le noyau et servant à le configurer.

Ces appellations (v2, v3, v4…) semblent être, selon lui,  « un artefact de la glibc », la bibliothèque standard GNU C. Il juge cette classification « stupide » : elle « doit disparaitre ». « Je n'ai aucune idée de qui est à l'origine des "niveaux de microarchitecture", mais pour autant que je sache, ce n'est pas du tout officiel, et c'est un modèle complètement erroné », ajoute-t-il.

Où réside le problème ? « Il existe un modèle très réel pour les caractéristiques microarchitecturales, et ce sont les bits CPUID. Essayer de linéariser ces bits est techniquement erroné, car il ne s'agit tout simplement pas d'une sorte de progression linéaire », indique Linus Torvalds.

En clair, même si ces différentes technologies apparaissent dans le temps, un classement chronologique ne peut pas toujours s’appliquer. Les instructions AVX-512, par exemple, ont été ajoutées par Intel dans la 11ᵉ génération de processeurs Core… avant de les supprimer sur la 12ᵉ, puis de les faire revenir dans une évolution d’AVX10.

Que recommande Linus Torvalds ? De rester avec les bits CPUID, qui permettent d’interroger le support d’un jeu d’instructions par un processeur, alors qu’un niveau ne peut renvoyer un résultat garanti.

Le 06 décembre à 15h40

Commentaires (35)

Vous devez être abonné pour pouvoir commenter.

Abonnez-vous
votre avatar
Donc, d'un côté, on a un mini-consortium composé d'au moins 4 acteurs majeurs qui décident d'un truc en commun. De l'autre, on a un gars tout seul qui rejette sous prétexte qu'il trouve ça stupide.

Qu'il ne souhaite pas l'intégrer dans Linux, c'est son problème. Si d'autres décident de l'adopter (en premier, les compilateurs), il ne pourra rien y faire.

Surtout que le CPUID, c'est du runtime. Le niveau, cela à l'air plus d'être quelque chose de statique défini à la compilation...
votre avatar
Sa réponse peux se comprendre, tu auras l'architecture v2,v3 etc et de toutes façons tu feras une lecture du Cpuid pour valider le type exact de processeur.
votre avatar
Les groupes de travail ne donnent pas systématiquement de meilleurs résultats que des individus, parce que le travail de groupe peut conduire à des compromis pas forcément très cohérents ou pas forcément très synergiques. A prendre avec des pincettes quand même.
votre avatar
Hum... je suis Sceptique :glasses:
votre avatar
Pourtant à l'assemblée, on en a de bons exemples... 🤡
votre avatar
Qu'il ne souhaite pas l'intégrer dans Linux, c'est son problème. Si d'autres décident de l'adopter (en premier, les compilateurs), il ne pourra rien y faire.
Il rejette justement l'utilisation dans le kernel :
So no. We are NOT introducing that idiocy in the kernel.
Je pense que techniquement, il a raison puisqu'on a au moins un exemple qui prouve qu'un classement par chronologie de marche pas : les instructions AVX-512 citées dans la brève.

De plus, pour un développeur kernel ou même compilateur, c'est probablement plus parlant d'utiliser les CPUID. Sa pique :
Now instead of asking "does this CPU support the cmpxchgb16 instruction?", the question instead becomes one of "what the hell does 'v3' mean again?"
me semble vraie.

Après, il fait du Linus sans une once de diplomatie comme trop souvent.
Surtout que le CPUID, c'est du runtime. Le niveau, cela à l'air plus d'être quelque chose de statique défini à la compilation...
Ça n'empêcherait pas d'être obligé de quand même tester au runtime les CPUID qui varient dans une même version (comme AVX512F). J'ai du mal à me représenter la quantité de code embarqué pour rien si l'on teste au runtime en opposition à une génération de code statique, mais si ce n'est pas significatif, autant ne pas faire de génération statique.
votre avatar
Je pense que techniquement, il a raison puisqu'on a au moins un exemple qui prouve qu'un classement par chronologie de marche pas : les instructions AVX-512 citées dans la brève.
Le côté chronologique, c'est Linus qui semble l'introduire.

De base, cette classification ne semble pas être axée dessus. Bien sûr, v1 vient avant v2, qui vient avant v3 qui vient lui-même avant v4. La dessus, je pense qu'on peut être d'accord.

Maintenant, je pense qu'il faut voir ce que ces niveaux représentes pour ce qu'ils sont. Le v1 par exemple, ne représente pas des jeux d'instructions vieux, mais des jeux d'instructions considérés comme la base (aujourd'hui, on n'imagine pas un processeur sans FPU par exemple).

Les niveaux suivants viennent ensuite enrichir chaque niveau précédent de nouvelles instructions. Bien évidement qu'il va y avoir un ordre peu ou prou chronologique, car les jeux d'instructions sortent au fur à et mesure.

Regrouper des jeux d'instructions "d'une même période" au sein d'un même niveau, est-ce si déconnant que ça ?

Qui plus est, cela permet de gérer plus facilement la compatibilité du matériel. Tout processeur compatible d'un niveau N peut être remplacé par un processeur d'un niveau équivalent ou supérieur.

Enfin, je rajouterai que regrouper les jeux d'instructions selon différents ensemble, cela permet également de s'assurer de pouvoir utiliser ensemble des jeux d'instructions. Si ça se fait plutôt bien à la compilation via les options, c'est un peu plus difficile de gérer ça au runtime en se basant sur le CPUID, car cela peut entrainer une complexité calculatoire si tu veux faire tous les cas.

Qui plus est, je vois un avantage pourtant certains pour le noyau linux : les modules. Avoir un module compatible avec tel ou tel niveau permettrait de s'assurer que le module fonctionne pour tous les processeurs compatibles avec un niveau spécifique ou supérieur, sans avoir besoin de le recompiler pour chaque architecture spécifiquement (ce qui est le cas aujourd'hui).

Car oui, la notion de niveau est aussi un moyen d'assurer une compatibilité avec les processeurs à venir, en "forçant" l'inclusion de jeux d'instruction de niveaux inférieurs, sous peine d'avoir un processeur qui soit limité en terme de niveau.
Après, il fait du Linus sans une once de diplomatie comme trop souvent.
C'est un peu ce que je lui reproche. Je ne nie pas qu'il a fait beaucoup pour l'informatique (rien que Git et Linux, c'est déjà énorme). Mais il n'est pas non plus obligé de se montrer aussi dénigrant. Il me semblait pourtant qu'il avait dit qu'il ferait attention dans le passé, étant conscient de son comportement parfois borderline...
Ça n'empêcherait pas d'être obligé de quand même tester au runtime les CPUID qui varient dans une même version (comme AVX512F).
On peut toujours, mais c'est en théorie inutile si le jeu d'instruction que l'on veut utiliser est inclus dans le niveau du processeur.
votre avatar
Les niveaux suivants viennent ensuite enrichir chaque niveau précédent de nouvelles instructions. Bien évidement qu'il va y avoir un ordre peu ou prou chronologique, car les jeux d'instructions sortent au fur à et mesure.
Regrouper des jeux d'instructions "d'une même période" au sein d'un même niveau, est-ce si déconnant que ça ?
Qui plus est, cela permet de gérer plus facilement la compatibilité du matériel. Tout processeur compatible d'un niveau N peut être remplacé par un processeur d'un niveau équivalent ou supérieur.
Ce n'est justement pas le cas. La news de Next est inexact. C'est bien tout le problème.

Lire https://www.phoronix.com/news/Torvalds-Mind-Fart-x86_64-Level et ses commentaires par exemple.
Car oui, la notion de niveau est aussi un moyen d'assurer une compatibilité avec les processeurs à venir, en "forçant" l'inclusion de jeux d'instruction de niveaux inférieurs, sous peine d'avoir un processeur qui soit limité en terme de niveau.
C'est précisément ce qui est en train d'être abandonné.
next.ink Next
next.ink Next
votre avatar
Ce n'est justement pas le cas. La news de Next est inexact. C'est bien tout le problème.
Peux-tu expliciter stp ? Le seul truc que j'ai vu qui pourrait aller dans ce sens, c'est la désactivation via microcode de fonctionnalités pour cause de failles/sécurité. Si cela devait affecter un jeu d'instruction d'un niveau précis, alors le processeur perdrait sa compatibilité.
C'est précisément ce qui est en train d'être abandonné.
Oui et non. Ce qui est abandonné, ce ne sont pas les jeux d'instructions, mais les architectures complètements obsolètes. Un ordinateur 64 bits aujourd'hui, démarre en 16bits, avant de passer en mode protégé 32 bits pour enfin activer le mode 64 bits. Car la méthode de démarrage n'a pas changé depuis au moins la fin des années 80. La seule chose qui ait changé, c'est que maintenant, c'est l'UEFI qui fait une partie du boulot au lieu que cela soit l'OS qui fasse tout.

Le 16 bits est complètement désué et ne sert plus à rien (il n'y a plus de programmes en mode 16bits qui tourne directement sur une architecture 32/64bits comme ce que nous avons eu à une époque sous Windows par exemple, où il était possible de lancer un programme DOS directement sous Windows).

Ou alors j'ai mal compris les intentions d'AMD et d'Intel.
votre avatar
On peut toujours, mais c'est en théorie inutile si le jeu d'instruction que l'on veut utiliser est inclus dans le niveau du processeur.
Et là c'est le drame, car tu vises la v4 sans vérifier les bits CPUID et, malheureusement, ton CPU ne supporte justement pas AVX512F :stress:

Quoi qu'on en dise, vérifier ou non la disponibilité des instructions sera toujours nécessaire. Parce que là on parle d'AVX512F, mais rien ne dit qu'il n'existe pas des architectures x86-64 un peu exotiques qui ne mettent pas toutes les instructions "usuelles"...
votre avatar
Pourquoi drame ?. Si le CPU ne supporte pas un jeu d'instruction nécessaire pour être en v4, il ne sera pas en v4, tout simplement...

Vérifier la présence d'un jeu d'instruction, oui, bien sûr, cela sera toujours nécessaire. Que ce soit à la compilation ou à l'exécution, l'important, c'est que cela soit fait.
votre avatar
Le problème est justement qu’AVX512F était marqué obligatoire en v3 (ou v4, toujours rajouter la parenthèse « ou vn+1 » dans le reste de mon message), mais pas en v4. Ensuite, Intel a sorti une gamme de processeurs annoncé compatible v4 et ne contenant justement pas l’instruction en question (parce que ça ne rentrait pas dans leurs cœurs « efficiency » donc tout le processeur en est privé).

Résultat, je compile mon truc pour v3 minimum, le compilateur profite de l’instruction AVX512F pour vectoriser—systématiquement—certaines de mes fonctions, et l’exécutable crash sur certain processeurs Intel compatible v4.

S’il y avait effectivement une augmentation stricte de la vn à la vn+1, il n’y aurait pas de problème. Ce n’est pas le cas.
votre avatar
Ensuite, Intel a sorti une gamme de processeurs annoncé compatible v4 et ne contenant justement pas l’instruction en question (parce que ça ne rentrait pas dans leurs cœurs « efficiency » donc tout le processeur en est privé).
Justement, c'est ce que j'entends de la part des détracteurs. Mais pour l'instant, aucun exemple n'a été donné d'un processeur annoncé comme v4 et sans ce jeu d'instructions. Oui, le jeu a été retiré de la 12e génération. Tant qu'un processeur de 12e génération n'est pas estampillé v4, ça ne pose absolument aucun problème.

Si ça existe, il doit pourtant être facile de trouver, sur le site d'Intel par exemple, un processeur estampillé v4 sans ce jeu d'instruction. Les 5min de recherches que j'ai fait n'ont pas été concluant.
votre avatar
prenons le problème à l'envers

pour l'instruction existante sur l'intel 11, mais retiré de l'intel 12,
si les 2 sont estampillés "v3"
=> si l'instruction en question ne fait pas partie de la v3, elle ne sera jamais utilisée, même sur l'intel 11 si l'instruction fait partie de la v3 <= crash sur l'intel 12

si l'intel 11 est estampillé v4 car il a l'instruction, mais que l'intel 12 est estampillé v3 car il ne l'a pas, il n'y aura pas de souci technique,

ça va juste être super frustrant si un acheteur d'intel 12 espère gagner en perfs, mais que manque de bol ses logiciels font appel à des instructions, existantes dans l'intel 12, mais hors v3, et l'intel 12 ne peut pas être v4 car il lui manque l'avx512, pas utilisé ici, mais si le code se base sur la version et pas les cpuid, jamais les jeux d'instructions existants mais associés à une version supérieure ne seront utilisés, pas bloquant, mais vraiment très dommage
votre avatar
C'est pas parce que la décision est collégiale qu'elle n'est pas mauvaise.

Moi de ce que je lis, c'est qu'on a des jeux d'instruction différents qui se retrouvent dans des "versions" sans trop de raison car ce n'est pas comme ça que ça a été pensé au départ dans leur intégration au sein des CPU.

J'imagine qu'un jour ou l'autre il va y avoir un abandon de certains jeux les plus anciens, pour simplifier l'architecture, et que peut venir mettre le bazar dans cette numérotation.

D'ailleurs l'article le dit déjà avec AVX-512 : il y a déjà des produits qui suivent pas forcément strictement l'approche de cette nomenclature. Donc le CPU Intel Gen11 ne peut a priori pas se déclarer en v4, mais se retrouve amputé d'une capacité parce que le système a voulu être migré vers un autre mode de gestion.

Après, il doit y avoir une raison pour avoir souhaité fonctionner de cette façon, mais d'un point de vue noyau, ça me parait rendre beaucoup plus compliqué de "packager" les capacités plutôt qu'une requête individuelle sur chaque capacité, pour savoir si elle est gérée ou non.
votre avatar
C'est pas parce que la décision est collégiale qu'elle n'est pas mauvaise.
Ce n'est pas parce qu'une décision est prise par une seule personne qu'elle n'est pas mauvaise ;)

Soit dit en passant, les "décisions absurdes" (3 volumes au total, avec des années écoulés entre chaque volume) est une lecture très intéressante pour, justement, comprendre comment, par en groupe, on peut arriver à prendre une décision... absurde !
votre avatar
« décision absurde » ou « consensus mou foireux » ?
:mrgreen:
votre avatar
Peut-être que c'est réellement stupide, en fait! Intel et AMD n'en subiront pas les conséquences en plus... RH et Suze qui utilisent le noyau, même s'ils sont contributeurs, le sont plutôt dans un mode retour vers le futur de backport des nouveautés matérielles vers des driver model de noyaux anciens...
Bref, yakafaucon c'est bien mais au moins les 2 derniers ne pourront pas ne pas tenir compte de ce point de vue de poids.
votre avatar
Ces "classes" ont un avantage : définir des versions précompilées d'executables plus ou moins optimisées pour un CPU donné, sans devoir précompiler une pléthore de versions avant de les distribuer. Après, si les versions se suivaient bien régulièrement chronologiquement, ok, ce serait une pas trop mauvaise idée, mais ce n'est pas le cas.
votre avatar
J'ai la même lecture. Cela permettrait de créer des chemins d'exécution. Au lancement de l'appli, on détermine avec les cpuid si on est compatible v1, v2, v3, v4, et on utilise le chemin d'exécution correspondant.
Cela pourrait mener à des optimisation plus poussées.
Même si certains CPU pourraient se retrouver sur un niveau inférieur pour un jeu d'instruction non utilisé...

Quand au kernel ... Franchement, utiliser le cpuid en permanence et choisir un chemin d'exécution presque "à l'instruction près" au lieu de le faire une fois de temps en temps et de choisir un gros chemin d'exécution linéaire...
votre avatar
Quand au kernel ... Franchement, utiliser le cpuid en permanence et choisir un chemin d'exécution presque "à l'instruction près" au lieu de le faire une fois de temps en temps et de choisir un gros chemin d'exécution linéaire...

Pour une appli dans le userspace peut être, mais dans un noyau, on ne peut pas souffrir de l'à peu près. Un kernel est un gros programme faisant plein de choses complexes et dans lequel il est impératif de savoir ce qu'il se passe à tout instant. Comme je l'ai dit dans un post plus bas, déboguer un kernel n'est pas chose facile et seuls les spécialistes y arrivent. Si tu leur colles une bonne grosse tartine d'à peu près avec un nappage de brouillard, je ne donne pas longtemps avant d'avoir un beau bordel généralisé.

Bref, dans un applicatif au dessus du noyau, pourquoi pas ? Mais bon, avec de l'expérience, ça complexifie inutilement. Disons que cela rendra service à ceux qui ne veulent pas se donner les moyens de bosser correctement.
votre avatar
A l'inverse, tracer le code si il passe sont temps à passer par un cpuid pour aller à droite où à gauche...
Mais je rejoins pour le kernel, en même temps je comprends l'idée des 4 topologies pour le userspace et pour les drivers ayant du traitement.
votre avatar
Et encore les drivers tournent en kernelspace et un à peu près peut amener facilement au plantage de la machine.
votre avatar
Remarque: c'est pas beaucoup mieux côté ARM/RISC-V. Il y a plein de déclinaisons de jeux d'instructions.
votre avatar
Du coup, raison de plus pour rester « simple » avec les CPUID.

Imagine que les fabricants de puces ARM/Risc-V se mettent à faire leur propre classification V1, V2 ... et bien sûr pas forcément dans la logique x86, voire aussi pas forcément compatible entre elles. Bref, tout ce qu'il faut pour de la mauvaise vulgarisation de capacités fonctionnelles des processeurs.
votre avatar
Je suppose (pure spéculation) que la volonté d'avoir ces niveaux est lié au monde conteneurisé, où l'on produit des images par architecture, englobées sous un manifeste unique. Imaginons que je produis des builds amd64 et arm64 pour image "toto", je les pousse avec un manifeste unique, et l'utilisateur va puller "toto" qui pointera directement sur la bonne archi en fonction du système cible.

Ça paraît compliqué d'optimiser les builds pour chaque jeu d'instruction étant donnée la combinatoire possible.

Par contre, on peut facilement imaginer d'étendre ce système avec des versions: amd64-v1, amd64-v2, etc. pour optimiser les builds et les pousser tous sous un manifeste unique.
votre avatar
Torvalds est contre tout ce qui ne vient pas de lui anyway.
votre avatar
C'est une façon de voir.
Mais ils ont été très cons de ne pas le mettre dans la boucle vu le niveau de représentation de Linux à l'échelle mondiale.

De plus, les gens de RedHat sont là d'abord pour faire du pognon contrairement à l'équipe Linux. Bien qu'il y ait pas mal de contributions d'individus chez RedHat, cela reste de la contribution d'individus et non d'une entreprise.

Linus a son style ... et je le trouve tout simplement efficace parce que c'est du style « Léodagan » qui met les choses au clair versus les champions du consensus mou qui essaient de noyer le poisson pour cacher l'idiotie de leur idée de m_rde. Et en parlant de Léodagan, ça me rappelle : « Ce qu’il y a de bien avec les opinions tranchées, c’est que ça relance le débat ! En somme, vous êtes une sorte de provocateur, quoi. » adressée aux champions de la solution de milieu du gué.

Donc, oui, je me range à l'avis de Linus parce qu'il sait de quoi il parle et l'a prouvé plusieurs fois. De plus, je mets le nez régulièrement dans le fonctionnement des noyaux et aux vues de la complexité de l'exercice, il est important que cela reste clair. Faire des à peu près sur ce type de briques logicielles, c'est juste criminel ... un noyau ne se débogue pas avec une jolie interface colorée pour touriste fainéant à Iphone.
votre avatar
On peut placer son point de vue du côté dev : pourquoi prendre le risque de compiler avec un "niveau" qui ne fonctionnera peut être pas, si on peut tester individuellement la présence de chaque circuit spécialisé ? Ou à l'inverse : pourquoi s'empêcher d'activer un circuit spécialisé pourtant présent, si le processeur n'a pas le bon niveau ? De plus, si les devs, sont capables de compiler avec différents "niveaux" de compilation, c'est qu'ils ont différentes versions de leur code (ou alors, c'est qu'ils bénéficient d'optimisation JIT et donc, les optimisation sont décidées à la volée et donc il y a pas de débat). Et s'il y a bien différentes implémentations pour différentes instructions, pourquoi ne pas simplement activer les bibliothèques dynamiques adéquates en fonction du CPUID ? ça me semble le plus optimal, et sans risque d'incompatibilité.
votre avatar
Bon, c'est sur que le compilateur peut décider d'optimiser certaines boucles et autre morceaux de code, mais les devs peuvent eux mêmes différencier leur algos pour viser une optimisation selon les instructions spécialisées envisagées, et sans que le compilateur ne soit capable de réaliser ces optimisations. De plus, si le compilateur est capable d'utiliser des instructions spécialisées par lui même, il est aussi capable de compiler plusieurs versions d'un même code dans un même exécutable, avec une décision à l'exécution de la version à choisir en fonction du jeu d'instruction présent. Alors pourquoi ne pas rendre ça plus automatique ? Les lib/exécutables seraient peut être plus gros, mais moins une fois chargés en mémoire centrale si on élague l'inutile ?
votre avatar
ça me parait censé comme critique. Cette hiérarchisation veut dire qu'on peut plus enlever des instructions d'un niveau inférieur sur des générations de processeur récente même si elles sont rendues obsolètes. ça impose de supporter toutes les instructions intel/AMD même si elles n'ont pas ou plus de sens, au risque d'être étiqueté avec une "version" faible.
votre avatar
C'est quoi le but affiché de ces "niveaux" ?
Je n'y connais pas grand chose dans cette partie de l'informatique et je ne me sent pas d'aller chercher l'info à droite à gauche, mais comme ici il y a plus de spéculations que de retours sourcés sur le POURQUOI de la proposition initiale, il me semble dommage que cette raison n'ai pas été indiquée dans l'article. 😢
votre avatar
Le but est (voir ma réponse à fdorin plus haut) était de pouvoir compiler les applications avec un niveau minimum d’optimisation (par exemple pour éviter d’avoir à choisir entre un binaire qui grossit trop—à cause de tous les optimisations possibles selon ce qui est disponible dans le processeur d’exécution—et un binaire presque pas optimisé—pour supporter les processeurs n’ayant pas les instructions avancées).

Certains ce souviennent des distribution Linux qui sont passées de paquets i386 à i686 (donc Pentium II ou équivalent minimum) en 32-bit.

Il se passe essentiellement la même chose en 64-bit avec les niveaux dont on parle ici : Building Red Hat Enterprise Linux 9 for the x86-64-v2 microarchitecture level.
votre avatar
Cette histoire de niveaux ne tient pas debout, à la première occasion ça va se casser la figure parcequ'intel voudra à nouveau faire des ségrégations de gamme basées sur l'une ou l'autre nouvelle fonctionnalité. Le cpuid est la seule chose à peu près fiable et capable de survivre à une nouvelle stratégie commerciale.
votre avatar
Ben le CPUID est buggué dans plusieurs CPU, AMD ou Intel, donc ça reste du n'imp.
(ce qui rejoins le coup de gueule d'avant de Linus concernant les bugs chez les fondeurs)

Linus Torvalds critique violemment les « niveaux » introduits pour l’architecture x86

Fermer