Le prédicteur de branchements 2-ahead de Zen 5 : une idée vieille de 30 ans ouvre de nouvelles possibilités
(chipsandcheese.com)- AMD Zen 5 a introduit un prédicteur de branchements 2-Ahead dans le cadre d’une refonte complète de l’architecture Zen, remettant au goût du jour les travaux des années 1990 sur la prédiction anticipée de branchements sur plusieurs blocs pour l’extension des front-ends x86 modernes
- La prédiction de branchements est un mécanisme qui permet au front-end du CPU de continuer à aller chercher des instructions même avant que le résultat d’un branchement conditionnel ne soit connu ; une erreur de prédiction entraîne un vidage du pipeline et un coût de redémarrage
- Zen 5 dispose, depuis son cache d’instructions L1 de 32 Ko, de deux fetch pipes de 32 octets/cycle, chacun relié à un cluster de décodage 4-wide ; l’Op Cache adopte aussi une structure dual-port 6-wide capable de fournir jusqu’à 12 opérandes à l’Op Queue
- La nouvelle structure traite en un cycle deux branchements taken à travers des blocs d’instructions non contigus et utilise un champ de longueur sur 5 bits pour trouver le point de départ d’une troisième fenêtre de prédiction, réduisant ainsi la surutilisation des ressources de décodage et d’Op Cache
- Comme x86 utilise des instructions de longueur variable, il est difficile de paralléliser la détermination des limites d’instructions ; le prédicteur de branchements 2-Ahead et la double structure fetch/décodage deviennent donc des évolutions clés dans l’extension du front-end de la famille Zen
Ce qui change dans le front-end de Zen 5
- AMD a présenté Zen 5 comme une refonte complète de l’architecture Zen, et le prédicteur de branchements 2-Ahead en est l’un des aspects les plus remarquables
- Cette structure, fondée sur des idées étudiées dans des articles vieux de 30 ans, réapparaît dans un contexte où l’on cherche à pousser davantage les performances par cœur
- Prédire plusieurs branchements taken à la fois permet au front-end de regarder à l’avance plus loin dans le flux d’instructions
Pourquoi la prédiction de branchements est nécessaire au pipeline CPU
- Les CPU modernes utilisent une structure en pipeline, qui divise la récupération des instructions (fetch), le décodage et l’exécution en plusieurs étapes
- En présence d’un branchement conditionnel, le front-end doit décider de l’emplacement de la prochaine instruction à aller chercher avant la fin de l’évaluation de la condition
- Les choix possibles se résument globalement à deux options
- S’arrêter jusqu’à ce que le résultat du branchement soit connu
- Prédire le chemin suivant et, en cas d’erreur, jeter le travail incorrect puis redémarrer à partir d’un point certain
- Si la prédiction est erronée, il faut effectuer un flush pour retirer du pipeline le travail dépendant de cette hypothèse
- Le coût d’un arrêt sur une condition de branchement est proportionnel au nombre d’étages de pipeline entre l’instruction fetch et la fin de l’évaluation de la condition de branchement
- Au final, le CPU doit prédire aussi précisément que possible le flux d’instructions du programme
Le contexte d’apparition de l’idée 2-Ahead
- Parmi les méthodes de prédiction simples, il existait une stratégie consistant à considérer les courts sauts arrière comme toujours taken, ce qui offrait historiquement un net avantage par rapport au fait de toujours aller chercher l’adresse suivante
- Conserver un petit état, comme l’historique récent des branchements ou des adresses, permet d’obtenir de meilleurs résultats dans les programmes réels
- Des structures de quelques dizaines de Ko suffisaient déjà à atteindre des taux de prédiction des branchements dans le haut de la plage des 90 %
- Le prédicteur de branchements 2-Ahead est une proposition discutée dès le début des années 1990, à une époque où l’on abordait aussi la question de l’élargissement architectural à 8-wide ou plus
- Par la suite, avec le passage des CPU commerciaux au multicœur, la surface de chaque cœur est devenue plus importante, et le monde académique s’est concentré sur l’amélioration de prédicteurs TAGE plus efficaces en surface
- La miniaturisation des procédés ayant permis d’intégrer davantage de transistors sur une surface similaire, l’intérêt pour les performances par cœur a aussi grandi de nouveau, parallèlement à la tendance à faire monter en échelle jusqu’à des centaines de CPU out-of-order
Pourquoi le front-end x86 est plus délicat
- Les ISA à instructions de longueur fixe, comme Arm 64 bits, facilitent le décodage en parallèle de portions arbitraires d’une ligne de cache d’instructions
- Il suffit de découper les données d’entrée sur des frontières d’octets d’instruction garanties et de répliquer la logique de décodage
- En x86, les instructions ont une longueur variable ; il faut donc analyser linéairement les octets d’instruction pour connaître la limite suivante de chaque instruction
- Une certaine parallélisation est possible grâce à du pipelining, par exemple en décodant partiellement d’abord les préfixes, mais le coût n’est pas négligeable en x86
- C’est aussi l’une des raisons pour lesquelles le décodage 4-wide est longtemps resté courant dans les cœurs x86 orientés performances
- Des conceptions comme le décodage 6-wide de l’Intel Golden Cove ont pu être commercialisées grâce à l’augmentation de la densité logique des procédés récents, mais le coût en surface et en énergie du décodage x86 parallèle monolithique augmente de façon superlinéaire avec la largeur
- Le code entier des applications courantes présente généralement une densité de branchements d’environ 1 branchement toutes les 5 à 6 instructions, ce qui réduit l’incitation à élargir beaucoup plus les décodeurs
- Le front-end x86 a besoin d’un moyen de contourner l’étape difficile à paralléliser de détermination des limites d’instructions et d’atteindre en toute sécurité la prochaine limite d’instruction
L’implémentation double fetch/décodage de Zen 5
- « Multiple-block ahead branch predictors » par Seznec et al. est un article clé qui traite des raisons d’être et des modes d’implémentation du prédicteur de branchements 2-Ahead
- Un prédicteur capable de traiter plusieurs branchements taken ne suffit pas à lui seul ; Seznec et al. estimaient qu’il fallait du dual-porting de l’instruction fetch pour l’exploiter sans faire exploser les exigences en surface
- Zen 5 transforme l’instruction fetch et l’Op Cache en structures dual-port
- Il utilise deux fetch pipes de 32 octets/cycle depuis le cache d’instructions L1 de 32 Ko
- Chaque fetch pipe est relié à son propre cluster de décodage 4-wide
- L’Op Cache est une conception dual-ported 6-wide et peut fournir jusqu’à 12 opérandes à l’Op Queue
- Le Branch Target Buffer fait lui aussi partie des éléments concernés par le dual-porting
- La grande taille du L1 BTB de Zen 5, avec 16K entries accessibles, peut expliquer la possibilité d’un L1 BTB dual-ported
- Le L2 BTB compte 8K entries, soit moins que le L1 BTB
- AMD utilise le L2 BTB de manière proche d’un victim cache : les entrées évincées du L1 BTB sont déplacées vers le L2 BTB
Comment traiter deux branchements taken en un cycle
- Zen 5 peut traiter en un cycle deux branchements taken à travers des blocs d’instructions non contigus
- Ce changement réduit la perte de bande passante de fetch lorsqu’un branchement taken est rencontré et permet de prédire au-delà de deux branchements taken
- Il devient possible de regarder plus loin dans le flux d’instructions après le second branchement taken, avec trois fenêtres de prédiction
- Les trois fenêtres de prédiction peuvent toutes servir à produire des instructions pour le décodage
- La deuxième fenêtre de prédiction est accompagnée d’un champ de longueur sur 5 bits
- Il évite de réserver excessivement des ressources de décodage ou d’Op Cache
- Plus petit qu’un pointeur, il fournit tout de même le point de départ de la troisième fenêtre de prédiction
- Lorsque la troisième fenêtre de prédiction franchit une limite de ligne de cache, il n’est pas nécessaire de stocker un état supplémentaire dans l’index de recherche de prédiction pour le cycle suivant
- Si la troisième fenêtre de prédiction se trouve dans la même ligne de cache que la première ou la deuxième fenêtre de prédiction, cette troisième fenêtre partielle n’est pas aussi efficace qu’une troisième fenêtre de prédiction complète
Contraintes restantes avec le SMT
- Dans Zen 5, lorsque deux threads sont actifs, les fetch pipes associés aux clusters de décodage sont partitionnés statiquement
- Dans cet état, pour fonctionner comme un cœur à double fetch, il faut aller chercher des instructions à la fois dans le cache d’instructions L1 et dans l’Op Cache
- AMD a peut-être rendu l’Op Cache dual-port afin de mieux maintenir le double pipeline de fetch
Articles connexes mentionnés
- « Multiple-block ahead branch predictors » par Seznec et al. – ASPLOS 1996 : traite des raisons d’être et des orientations d’implémentation du prédicteur de branchements 2-Ahead
- « Optimization of Instruction Fetch Mechanisms for High Issue Rates » par Conte et al. – ISCA 1995 : traite de l’optimisation des mécanismes d’instruction fetch pour des issue rates élevés
- « Increasing the instruction fetch rate via multiple branch prediction and a branch address cache » par Yeh et al. – ICS 1993 : traite de l’augmentation du fetch rate grâce à la prédiction multiple de branchements et à un cache d’adresses de branchements
- « Out-of-Order Instruction Fetch using Multiple Sequencers » par Oberoi and Sohi – ICPP’02 : traite de l’instruction fetch out-of-order utilisant plusieurs séquenceurs
- « Parallelism in the Front-End » par Oberoi and Sohi – ISCA 2003 : traite du parallélisme dans le front-end CPU
1 commentaires
Avis sur Hacker News
Pour une bonne explication de la prédiction de branchement, depuis les premières implémentations, https://danluu.com/branch-prediction/ est une bonne référence
[0] : https://www.youtube.com/watch?v=nhXevKMm3JI&list=PLzH6n4zXuc...
[1] : https://www.youtube.com/watch?v=nczJ58WvtYo&list=PLzH6n4zXuc...
Je me demande ce que donnera la performance SMT, et j’espère que cette approche apportera un gain tout en étant encore affinée à la génération suivante
Zen5c monte jusqu’à 192 cœurs ou 384 vCPU, et Zen 6c l’an prochain pourrait atteindre 256 cœurs. Sur un serveur 1U bi-socket, cela ferait potentiellement 512 cœurs et 1024 vCPU
Les problèmes de mise à l’échelle des applications web que l’on rencontrait en 2014 peuvent désormais tenir dans un seul serveur, à condition de pouvoir le refroidir. Même en ne comptant que 1 RPS par vCPU, cela fait 1000 RPS hors cache hits, et la page d’accueil de HN n’envoie pas non plus 1000 pages vues par seconde à un serveur
Je me demande ce qu’il en est des performances HPC. Le refroidissement en soi n’est peut-être pas un gros problème, mais à partir d’un certain point cela pourrait devenir un problème « humide » nécessitant du refroidissement liquide direct (DLC)
Si l’on considère un rack de serveurs dense avec des GPU comme une seule machine, on en est déjà à plusieurs centaines de kilocœurs
J’ai déjà débattu avec quelqu’un qui ne comprenait pas l’idée qu’un service à l’échelle de Wikipedia puisse être fourni depuis un seul serveur, et c’était assez amusant. C’est facile depuis un moment déjà ; on ne le fait simplement pas pour des raisons pratiques comme la disponibilité ou le rapport coût-efficacité
Intuitivement, on pourrait penser qu’augmenter le nombre de tâches qui traitent le même problème à moitié vitesse devrait avoir un coût en mémoire, et je me demande s’il est courant que des applications consomment simplement plus de mémoire sans gain de vitesse lorsque le SMT est activé
Dans une bonne partie des benchmarks publics, la plupart des applications ne semblent pas bénéficier d’un gain notable en vitesse d’exécution
Il est toujours fascinant de voir des articles vieux de plusieurs décennies, publiés à l’époque sans beaucoup d’attention, devenir soudainement à la pointe une fois que le matériel est devenu suffisamment puissant
Par exemple le Z-buffer. Utilisé dans les jeux vidéo 3D, il était traité comme une digression dans le premier article, non pas à cause du sujet, mais parce qu’il nécessitait trop de mémoire
Quelques décennies plus tard, les mégaoctets sont devenus assez bon marché, et tous les moteurs de rendu 3D temps réel ont fini par l’utiliser
Il me semble qu’il y a eu un vide d’environ 38 ans dans la littérature avant leur redécouverte par David MacKay
Leur première utilisation grand public date de 2003, et ils sont aujourd’hui utilisés dans le WiFi, Ethernet et la 5G
[1] https://en.wikipedia.org/wiki/Low-density_parity-check_code
[2] https://scholar.google.com/scholar?q=%22low+density+parity+c...
En allant à la bibliothèque lire ce que les chercheurs en informatique publiaient sous forme d’articles papier, on pourrait peut-être trouver des idées irréalistes à l’époque mais désormais implémentables
Ces vingt dernières années, les performances par cœur ont été freinées au profit du passage à l’échelle horizontale, c’est-à-dire davantage de cœurs, ce qui a rendu problématiques la complexité de chaque cœur et la surface de die. Sans cette tendance, si les concepteurs de CPU avaient surtout cherché la performance par cœur, on aurait probablement vu une implémentation bien plus tôt
Le Z-buffer est un concept simple, donc il pouvait effectivement apparaître comme une digression dans l’article. Un meilleur exemple serait peut-être le ray tracing. Même sans bagage en graphisme 3D, le concept lui-même est assez clair, mais jusqu’à récemment il était irréaliste en performance pour le rendu temps réel
Ce qui est intéressant, c’est qu’on n’a pas trouvé d’approche plus simple pour approximer un rendu proche du réel, et qu’il faut revenir à une solution ancienne, quelque peu naïve et coûteuse
Beaucoup d’universitaires considéraient que les systèmes de types sous-structurels avaient en pratique été tués par le garbage collection, mais Rust les a ressuscités en les combinant avec les nouvelles idées de C++ de l’époque
Cette exigence supplémentaire en bande passante mémoire le rendait difficile et coûteux à implémenter correctement. Les implémentations haut de gamme utilisaient des canaux RAM dédiés, mais sur le matériel bas de gamme, elles accaparaient une grande partie de la bande passante de l’interface mémoire partagée
Par exemple, certains jeux N64 désactivaient le Z-buffer et optimisaient le rendu arrière-plan/premier plan géré en logiciel afin d’éviter le coût de lecture et de mise à jour des informations de profondeur
Les prédicteurs spéculatifs ont été la cible de nombreuses attaques visant à extraire des données privées
Si une bonne partie des ISA courantes sont vulnérables, je me demande si des mesures sont prises pour réduire l’impact de ces attaques
Il n’existe pas de moyen de l’empêcher, sauf approche du type faire bouillir l’océan[0]. L’exécution spéculative est trop précieuse pour les performances ; un ordinateur qui n’en aurait pas serait pratiquement inutilisable. Si vous voulez vraiment un processeur sans exécution spéculative, achetez un vieux Pentium de première génération
Les atténuations pratiques sont diverses, mais elles doivent au minimum garantir une séparation des processus entre un processus victime contenant des secrets et un attaquant potentiel capable d’influencer l’exécution de la victime
Intel s’est fait prendre à exécuter spéculativement à travers les rings, ce qui permettait de lire depuis l’espace utilisateur la mémoire du noyau ou de l’hyperviseur. Sur un CPU dont la conception n’est pas mauvaise, la principale source d’inquiétude est plutôt l’iframe HTML
Des origines différentes ne peuvent pas envoyer librement des requêtes HTTP[1], mais elles peuvent s’inclure mutuellement sans autorisation[2]. Traditionnellement, ces informations étaient chargées dans le processus de l’attaquant et pouvaient fuiter via une attaque par timing
La première solution du Web n’a pas été de séparer les iframes en processus, mais de supprimer purement et simplement le multithreading à mémoire partagée. Si l’on retire à l’attaquant sa référence de temps, ce que la victime exécute spéculativement importe moins. Mais pour cela, il faut supprimer le multithreading. Sinon, un thread peut créer une horloge en écrivant en boucle des données connues
[0] https://hackaday.com/2013/08/02/the-mill-cpu-architecture/
[1] Du moins, tant que l’origine cible ne l’autorise pas via CORS
[2] Par exemple : hotlink d’images ou intégration dans une iframe
Ce n’est pas une vulnérabilité intrinsèque à la prédiction elle-même
En tant que débutant dans ce domaine, même après lecture, je ne vois pas clairement ce qu’est exactement un prédicteur de branchement 2-ahead
Dans les années 90, on était plutôt proche de l’un ou de l’autre, mais les processeurs modernes semblent avoir les deux
Le résumé de “Multiple-block ahead branch predictors” explique qu’il s’agit de prédire le bloc suivant le prochain bloc d’instructions, sans utiliser les informations du bloc d’instructions courant pour prédire l’adresse du bloc suivant. Cela permet de réduire le goulot d’étranglement du fetch d’instructions dans les processeurs “brainiac” à dispatch large, et de prédire efficacement deux adresses de blocs d’instructions en un cycle
Il indique aussi que, dans les processeurs “speed demon”, le processus de prédiction de branchement peut être pipeliné, ce qui permet d’atteindre des fréquences plus élevées ou d’améliorer la précision grâce à des structures de prédiction plus grandes. Contrairement aux approches classiques à prédicteurs multiples, les prédicteurs de branchement plusieurs blocs en avance peuvent utiliser n’importe quelle méthode de prédiction de branchement
[0] https://dl.acm.org/doi/10.1145/237090.237169
Au passage, eyegor a apparemment déjà publié le lien, mais l’idée est au moins de lire le résumé
Ce doit être beaucoup plus difficile que de prédire le prochain branchement, mais cela permet de récupérer beaucoup plus tôt le code qui alimentera un pipeline plus profond
Ainsi, au lieu d’évaluer à l’avance seulement n+1 comme dans une prédiction de branchement classique, il peut aussi évaluer à l’avance le résultat n+2. Je ne sais pas très bien comment cela fonctionne sans mettre à mal le cache L1
Si l’on regarde au-delà de n+1, j’aurais tendance à penser que les évictions de cache augmentent beaucoup, donc il y a probablement quelque chose qui m’échappe
On dit que Zen 5 peut regarder plus loin, jusqu’au flux d’instructions au-delà du second taken branch, et qu’il peut ainsi disposer de trois fenêtres de prédiction utiles pour produire les instructions à décoder
L’article original est en accès public, mais je ne l’ai pas encore beaucoup lu : https://dl.acm.org/doi/10.1145/237090.237169
Chaque direction d’un branchement mène au début d’un nouveau bloc d’instructions, et la dernière instruction de ce bloc est généralement un autre branchement
Autrement dit, un prédicteur de branchement est un dispositif qui devine l’adresse du bloc suivant. Un prédicteur de branchement 2-ahead fait la même chose, mais pour les deux blocs qui suivent
Pour reprendre les termes de l’article, « les informations du bloc d’instructions courant sont utilisées pour prédire l’adresse du bloc qui suit le prochain bloc d’instructions »
Contrairement à un prédicteur de branchement classique, cela peut se faire sans attendre que les instructions du bloc suivant soient décodées. Il peut donc alimenter simultanément plusieurs décodeurs d’instructions
C’est particulièrement utile dans les CPU modernes où le décodeur d’instructions est devenu un goulot d’étranglement. Avec un seul décodeur qui ne décode qu’une instruction par cycle, il est difficile de suivre un front-end large capable d’exécuter beaucoup d’instructions, par exemple 4 à 6 par cycle
Il faudrait peut-être davantage de branch hints : https://github.com/ziglang/zig/issues/5177
Je me demande s’il serait possible d’avoir cold, warm, warmer, et d’omettre hot comme valeur par défaut. Parfois, on pourrait aussi marquer tous les branchements sauf un comme cold
C’est peut-être une mauvaise idée, mais j’aimerais comprendre pourquoi.
Quand il y a un branchement conditionnel, je me demande pourquoi on ne pourrait pas récupérer et préparer les instructions des deux branches possibles, puis jeter la mauvaise.
J’aimerais savoir si c’est beaucoup plus difficile, ou s’il y a une autre raison qui fait que ça n’en vaut pas la peine.
Les prédicteurs de branchement TAGE modernes ont largement plus de 99 % de réussite. Les instructions supplémentaires de l’autre branche sont donc presque toujours jetées.
Pire encore, le front-end récupère des dizaines de branchements en avance par rapport au point où le back-end peut vérifier la direction réelle. Que fait-on au branchement suivant ? Décoder 4 branches possibles, puis 8, 16, 32 ? La plupart seront jetées.
Si l’on dispose du matériel pour récupérer plusieurs flux d’instructions en parallèle, comme Intel Gracemont/Goldmont/Skymont et AMD Zen 5, la meilleure stratégie consiste à supposer que le prédicteur de branchement a raison à 100 %. On suit une branche, puis la suivante.
Intel Skymont a 3 décodeurs, chacun en 3-wide, et décode donc en parallèle les 3 prochaines cibles de branchement. Intel insère même de faux branchements pour découper les gros blocs de code, afin que les trois décodeurs décodent toujours des parties différentes du flux d’instructions à venir. Ensuite, les 3 flux de micro-opérations sont fusionnés, ce qui permet à Skymont de maintenir une bande passante effective de décodage de 9 instructions par cycle.
Exécuter les deux branches ne réduit un peu la latence que dans les rares cas où la prédiction de branchement est mauvaise. En revanche, en continuant à suivre les deux ou trois prochaines prédictions dans une seule direction, Intel et AMD peuvent faire travailler plusieurs décodeurs en parallèle. Intel peut obtenir du 9-wide avec trois décodeurs 3-wide plus simples, et AMD du 8-wide avec deux décodeurs 4-wide plus simples.
Le compilateur, le runtime, le CPU, etc. peuvent souvent deviner quel résultat est le plus plausible, et ne pas faire de travail supplémentaire est généralement une meilleure stratégie. C’est préférable à dépenser du silicium et de la chaleur sur la mauvaise réponse au cas où l’on se tromperait.
Beaucoup de gens semblent ne pas avoir l’intuition de la précision possible de la prédiction de branchement. En regardant simplement son propre code, on se rend vite compte que « la plupart du flux de contrôle va par ici, et cette branche sert à gérer les cas exceptionnels ».
Les compilateurs actuels déduisent aussi cela assez bien, et les CPU/JIT/runtimes peuvent construire des heuristiques impressionnantes. Et quand cela échoue malgré tout, on peut ajouter des indications explicites dans le code pour signaler au compilateur, etc., la direction attendue.
Le tampon de réordonnancement des instructions des CPU modernes a une profondeur de plusieurs centaines d’instructions, et s’il ne contient que 8 sauts conditionnels, cela donne déjà 256 chemins possibles pour le programme.
Si la probabilité que le prédicteur de branchement réussisse les 8 est supérieure à 50 %, ce qui est le cas en pratique, faire 256 fois plus de travail pour s’y préparer n’en vaut pas la peine.
Il faut du silicium pour conserver davantage d’état microarchitectural, ainsi que davantage d’unités d’exécution pour exploiter pleinement la technique. Mais les CPU superscalaires en disposent déjà, car c’est indispensable pour exploiter le parallélisme au niveau des instructions dans le code comportant peu de branchements.
Le reste, c’est le travail pénible consistant à gérer des complexités comme les alias et les interruptions, mais les ingénieurs matériel sont des magiciens et y arrivent aussi.
Cependant, l’exécution spéculative ouvre la possibilité d’exploiter des canaux auxiliaires liés au timing du cache pour extraire des informations à partir de données touchées par du code exécuté seulement de façon spéculative, dont les effets architecturaux ne sont pas commités. Autrement dit, des informations peuvent fuiter même depuis du code qui n’a pas été « réellement » exécuté.
Cela inclut du code qui n’a pas été exécuté explicitement à cause de vérifications conditionnelles, par exemple des contrôles de permissions.
Un exemple d’attaque bien connu est Spectre : https://en.m.wikipedia.org/wiki/Spectre_(security_vulnerabil...
Donc, fondamentalement, le calcul n’est pas du tout rentable. Ces ressources de puce sont bien mieux employées pour d’autres threads ou cœurs.
Pour juger si c’est une bonne idée, j’aimerais d’abord voir des données de performance. On n’a pas non plus d’informations sur la pénalité de prédiction de branchement de cette approche.
Quoi qu’il en soit, l’intuition derrière cette approche semble être de récupérer et décoder agressivement des instructions qui ne sont peut-être pas encore dans le cache d’instructions L1 ou le cache de micro-opérations.
C’est important pour x86, et probablement aussi pour RISC-V. Les deux ont des longueurs d’instructions variables, donc en regardant seulement un bloc de cache d’instructions, le cœur ne peut pas savoir comment décoder les instructions qui s’y trouvent. Dans ces deux ISA, pour commencer à décoder un bloc de cache d’instructions, il faut connaître au moins le PC d’une instruction.
Donc, si l’application sait où elle peut sauter deux blocs plus loin, cela aide à récupérer et décoder plus en avance que l’approche actuelle.
Cette approche ressemble au préchargement d’instructions, mais le préchargement d’instructions ne fournit pas au cœur les informations de point de départ.
Les cœurs ARM hautes performances ont probablement moins ce problème de « trouver le point de départ », car toutes les instructions font 32 bits. La procédure de décodage peut donc être parallélisée même sans connaître le point de départ.
Cette méthode devrait bénéficier aux applications fortement dépendantes du front-end, par exemple les workloads cloud où les blocs de code chauds sont dispersés un peu partout dans le binaire. Je me demande s’il y a des gains ou des pertes de performance pour d’autres types d’applications.
Je ne comprends toujours absolument pas ce qu’est un prédicteur de branchement 2-ahead.
En général, les anciens articles de recherche supposent que le lecteur en sait beaucoup moins sur ce genre de sujet, parce qu’à l’époque ces connaissances étaient bien plus de niche.
Ce qu’il faut maintenant, c’est de la bande passante mémoire. Les deux canaux mémoire du socket AM5 grand public font pâle figure face à ce niveau de performances de calcul, surtout même comparés à l’Apple Silicon de base.
Je suis passé d’une grosse configuration Zen à un M2 Max, et j’ai été à nouveau surpris de voir à quel point l’augmentation de la bande passante mémoire accélère les traitements intensifs sur les données. Même avec un multitâche assez lourd, le tuyau mémoire étroit de la configuration Zen se bouchait souvent.
Si les gens regardent l’Apple Silicon, notamment à cause des LLM, c’est parce que les LLM sont certes mieux adaptés au GPU, mais nécessitent aussi beaucoup de VRAM, et que NVIDIA pratique des prix absurdes sur les GPU dotés de beaucoup de VRAM.
Si AMD veut vraiment casser l’élan de NVIDIA, il doit vendre des GPU grand public avec 64 à 128 Go de VRAM.