À Hot Chips la semaine dernière, IBM a annoncé son nouveau processeur mainframe Z. C’est un gros morceau de kit intéressant sur lequel je veux faire un morceau plus large à un moment donné, mais il y avait une caractéristique de cette conception de base que je veux extraire et me concentrer spécifiquement. IBM Z est connu pour avoir de gros caches L3, soutenus par une puce de cache L4 globale distincte qui fonctionne comme un cache entre plusieurs sockets de processeurs – avec la nouvelle puce Telum, IBM a supprimé cela – il n’y a pas de L4, mais assez intéressant, il n’y a pas de L3. Ce qu’ils ont fait à la place pourrait être une indication de l’avenir de la conception de cache sur puce.

Caches : une brève introduction

Tout processeur moderne est associé à plusieurs niveaux de cache. Ceux-ci sont séparés par la capacité, la latence et la puissance – le cache le plus rapide le plus proche des ports d’exécution a tendance à être petit, puis plus loin, nous avons des caches plus grands qui sont légèrement plus lents, puis peut-être un autre cache avant d’atteindre la mémoire principale. Les caches existent parce que le cœur du processeur veut des données MAINTENANT, et si tout était conservé dans la DRAM, il faudrait plus de 300 cycles à chaque fois pour récupérer les données.

Un cœur de processeur moderne prédira à l’avance les données dont il a besoin, les importera de la DRAM dans ses caches, puis le cœur pourra les récupérer beaucoup plus rapidement lorsqu’il en aura besoin. Une fois que la ligne de cache est utilisée, elle est souvent « expulsée » du cache de niveau le plus proche (L1) vers le niveau supérieur (L2), ou si ce cache L2 est plein, la ligne de cache la plus ancienne du L2 sera expulsée vers un Cache L3 pour faire de la place. Cela signifie que si cette ligne de données est à nouveau nécessaire, elle n’est pas trop loin.


Un exemple de L1, L2 et d’un L3 partagé sur les processeurs Zen de première génération d’AMD

Il y a aussi la portée des caches privés et partagés. Une conception de processeur moderne a plusieurs cœurs, et à l’intérieur de ces cœurs se trouve au moins un cache privé (le L1) auquel seul ce cœur a accès. Au-dessus de cela, un cache peut être soit un cache privé toujours local au cœur, soit un cache partagé, que tout cœur peut utiliser. Un processeur Intel Coffee Lake, par exemple, a huit cœurs, et chaque cœur a un cache L2 privé de 256 Ko, mais au niveau de la puce, il y a un L3 partagé de 16 Mo entre les huit cœurs. Cela signifie que si un seul cœur le souhaite, il peut continuer à expulser les données de son plus petit L2 vers le grand L3 et disposer d’un pool de ressources si ces données veulent être réutilisées. Non seulement cela, mais si un deuxième cœur a également besoin de certaines de ces données, il peut les trouver dans le cache L3 partagé sans avoir à les écrire dans la mémoire principale et à les récupérer là-bas. Pour compliquer les choses, un cache « partagé » n’est pas nécessairement partagé entre tous les cœurs, il peut n’être partagé qu’entre quelques-uns spécifiques.

Le résultat final est que les caches aident à réduire le temps d’exécution et à importer plus de données de la mémoire principale au cas où cela serait nécessaire ou selon les besoins.

Compromis

Dans cet esprit, vous pourriez vous demander pourquoi nous ne voyons pas de caches L1 ou L2 de 1 Go sur un processeur. C’est une question parfaitement valable. Il y a un certain nombre d’éléments en jeu ici, impliquant la zone de matrice, l’utilité et la latence.

La zone de matrice est facile à aborder en premier – en fin de compte, il peut n’y avoir qu’un espace défini pour chaque structure de cache. Lorsque vous concevez un cœur en silicium, il peut exister un meilleur moyen de disposer les composants du cœur pour avoir le chemin critique le plus rapide. Mais le cache, en particulier le cache L1, doit être proche de l’endroit où les données sont nécessaires. Concevoir cette mise en page avec un cache L1 de 4 Ko à l’esprit sera très différent si vous voulez plutôt un grand cache L1 de 128 Ko. Il y a donc un compromis à faire ici – au-delà du L1, le cache L2 est parfois un gros consommateur d’espace de matrice, et bien qu’il ne soit (généralement) pas aussi limité par le reste de la conception de base, il doit toujours être équilibré avec ce que est nécessaire sur la puce. Tout grand cache partagé, qu’il se termine par un cache de niveau 2 ou un cache de niveau 3, peut souvent être la plus grande partie de la puce, selon le nœud de processus utilisé. Parfois, nous nous concentrons uniquement sur la densité des transistors logiques dans le noyau, mais avec des caches très volumineux, la densité du cache est peut-être plus importante dans le nœud de processus qui finit par être utilisé.

L’utilité est également un facteur clé – nous parlons principalement de processeurs à usage général ici sur AnandTech, en particulier ceux construits sur x86 pour les PC et les serveurs, ou Arm pour les smartphones et les serveurs, mais il existe de nombreux modèles dédiés dont le rôle est pour un charge de travail ou tâche. Si tout ce qu’un cœur de processeur doit faire est de traiter des données, par exemple un moteur d’IA de caméra, alors cette charge de travail est un problème bien défini. Cela signifie que la charge de travail peut être modélisée et que la taille des caches peut être optimisée pour offrir les meilleures performances/puissance. Si le but du cache est de rapprocher les données du cœur, alors chaque fois que les données ne sont pas prêtes dans le cache, cela s’appelle un échec de cache – l’objectif de toute conception de processeur est de minimiser les échecs de cache en échange de performances ou puissance, et donc avec une charge de travail bien définie, le noyau peut être construit autour des caches nécessaires pour un rapport performances/échec de cache optimal.

La latence est également un facteur important dans la conception des grands caches. Plus vous avez de cache, plus il faut de temps pour y accéder, non seulement en raison de la taille physique (et de la distance par rapport au cœur), mais parce qu’il y a plus à rechercher. Par exemple, les petits caches L1 modernes sont accessibles en trois cycles seulement, tandis que les grands caches L1 modernes peuvent avoir cinq cycles de latence. Un petit cache L2 peut être aussi bas que huit cycles, alors qu’un grand cache L2 peut être de 19 cycles. Il y a beaucoup plus qui entre dans la conception de cache que simplement plus gros est plus lent, et toutes les grandes entreprises de conception de processeurs travailleront avec acharnement pour réduire ces cycles autant que possible, car souvent une économie de latence dans un cache L1 ou un cache L2 offre bons gains de performances. Mais finalement, si vous allez plus gros, vous devez tenir compte du fait que la latence sera souvent plus grande, mais votre taux d’échec de cache sera plus faible. Cela revient au paragraphe précédent qui parle de charges de travail définies. Nous voyons des entreprises comme AMD, Intel, Arm et d’autres effectuer une analyse approfondie de la charge de travail avec leurs gros clients pour voir ce qui fonctionne le mieux et comment leur conception de base devrait se développer.

Alors, qu’est-ce qu’IBM a fait de si révolutionnaire ?

Dans le premier paragraphe, j’ai mentionné qu’IBM Z est leur gros produit mainframe – c’est le fer de lance de l’industrie. Il est mieux construit que votre bunker nucléaire autorisé par le gouvernement. Ces systèmes sous-tendent les éléments critiques de la société, tels que les infrastructures et les services bancaires. Les temps d’arrêt de ces systèmes sont mesurés en millisecondes par an, et ils ont des coffres-forts et des basculements à profusion – avec une transaction financière, lorsqu’elle est effectuée, elle doit être engagée dans toutes les bonnes bases de données à coup sûr, voire en cas de défaillance physique le long de la chaîne.

C’est là qu’IBM Z entre en jeu. C’est incroyablement niche, mais a un design incroyablement incroyable.

Dans le produit z15 de la génération précédente, il n’y avait pas de concept d’un produit système 1 CPU = 1 . L’unité de base d’IBM Z était un système à cinq processeurs, utilisant deux types de processeurs différents. Quatre processeurs de calcul (CP) hébergeaient chacun 12 cœurs et 256 Mo de cache L3 partagé en 696 mm2 construit sur 14 nm fonctionnant à 5,2 GHz. Ces quatre processeurs se sont divisés en deux paires, mais les deux paires étaient également connectées à un contrôleur de stockage (SC), également de 696 mm2 et sur 14 nm, mais ce contrôleur de stockage contenait 960 Mo de cache L4 partagé, pour les données entre les quatre processeurs.

Notez que ce système n’avait pas de DRAM « globale » et que chaque processeur de calcul avait sa propre mémoire équivalente sauvegardée par DDR. IBM combinerait alors ce « tiroir » à cinq processeurs avec quatre autres pour un seul système. Cela signifie qu’un seul système IBM z15 mesurait 25 x 696 mm2 de silicium, 20 x 256 Mo de cache L3 entre eux, mais aussi 5 x 960 Mo de cache L4, connectés dans une topologie tout-à-tout.

IBM z15 est une bête. Mais la prochaine génération d’IBM Z, appelée IBM Telum plutôt qu’IBM z16, adopte une approche différente de tout ce cache.

IBM, dites-leur quoi faire avec le cache

Le nouveau système supprime le contrôleur de stockage séparé avec le cache L4. Au lieu de cela, nous avons ce qui ressemble à un processeur normal avec huit cœurs. Construit sur Samsung 7nm et à 530mm2, IBM regroupe deux processeurs en un, puis met quatre packages (huit processeurs, 64 cœurs) dans une seule unité. Quatre unités forment un système, pour un total de 32 processeurs / 256 cœurs.

Sur une seule puce, nous avons huit cœurs. Chaque cœur dispose de 32 Mo de cache L2 privé, qui a une latence d’accès de 19 cycles. Il s’agit d’une longue latence pour un cache L2, mais il est également 64 fois plus grand que le cache L2 de Zen 3, qui est une latence de 12 cycles.

En regardant la conception de la puce, tout cet espace au milieu est le cache L2. Il n’y a pas de cache L3. Pas de L3 physique partagé pour tous les cœurs d’accès. Sans une puce de cache centralisée comme avec z15, cela signifierait que pour que le code qui a une certaine quantité de données partagées fonctionne, il aurait besoin d’un aller-retour vers la mémoire principale, ce qui est lent. Mais IBM y a pensé.

Le concept est que le cache L2 n’est pas seulement un cache L2. À première vue, chaque cache L2 est en effet un cache privé pour chaque cœur, et 32 ​​Mo sont incroyablement énormes. Mais quand vient le temps d’expulser une ligne de cache de L2, soit à dessein par le processeur, soit en raison du besoin de faire de la place, plutôt que de simplement disparaître, il essaie de trouver de l’espace ailleurs sur la puce. S’il trouve un espace dans le L2 d’un noyau différent, il s’y trouve et est marqué comme une ligne de cache L3.

Ce qu’IBM a implémenté ici, c’est le concept de caches virtuels partagés qui existent à l’intérieur de caches physiques privés. Cela signifie que le cache L2 et le cache L3 deviennent la même chose physique, et que le cache peut contenir un mélange de lignes de cache L2 et L3 selon les besoins de tous les différents cœurs en fonction de la charge de travail. Cela devient important pour les services cloud (oui, IBM propose IBM Z dans son cloud) où les locataires n’ont pas besoin d’un processeur complet, ou pour les charges de travail qui ne s’adaptent pas exactement aux cœurs.

Cela signifie que l’ensemble de la puce, avec huit caches L2 privés de 32 Mo, pourrait également être considéré comme ayant un cache L3 « virtuel » partagé de 256 Mo. Dans ce cas, considérez l’équivalent pour l’espace grand public : la puce Zen 3 d’AMD a huit cœurs et 32 ​​Mo de cache L3, et seulement 512 Ko de cache L2 privé par cœur. S’il implémentait un schéma L2/L3 virtuel plus important comme IBM, nous nous retrouverions avec 4,5 Mo de cache L2 privé par cœur, ou 36 Mo de L3 virtuel partagé par chiplet.

Ce schéma IBM Z a l’avantage chanceux que si un cœur a juste besoin de données qui se trouvent dans la L3 virtuelle et que cette ligne L3 virtuelle se trouve juste dans sa L2 privée, alors la latence de 19 cycles est bien inférieure à ce qu’est un partage le cache L3 physique serait (~ 35-55 cycles). Cependant, ce qui est plus probable, c’est que la ligne de cache L3 virtuelle nécessaire se trouve dans le cache L2 d’un cœur différent, ce qui, selon IBM, entraîne une latence moyenne de 12 nanosecondes sur son interconnexion en anneau bidirectionnelle, qui a une bande passante de 320 Go/s. 12 nanosecondes à 5,2 GHz représentent environ 62 cycles, ce qui sera plus lent qu’un cache L3 physique, mais le L2 plus grand devrait signifier moins de pression sur l’utilisation du L3. Mais aussi parce que la taille de L2 et L3 est si flexible et grande, en fonction de la charge de travail, la latence globale devrait être plus faible et la portée de la charge de travail augmentée.

Mais cela ne s’arrête pas là. Nous devons aller plus loin.

Pour IBM Telum, nous avons deux puces dans un package, quatre packages dans une unité, quatre unités dans un système, pour un total de 32 puces et 256 cœurs. Plutôt que d’avoir cette puce de cache L4 externe, IBM va plus loin et permet à chaque cache L2 privé de pouvoir également héberger l’équivalent d’un L4 virtuel.

Cela signifie que si une ligne de cache est expulsée du L3 virtuel sur une puce, elle ira chercher une autre puce dans le système pour vivre et sera marquée comme ligne de cache L4 virtuelle.

Cela signifie que d’un point de vue central singulier, dans un système à 256 cœurs, il a accès à :

  • 32 Mo de cache L2 privé (latence de 19 cycles)
  • 256 Mo de cache L3 virtuel partagé sur puce (+12 ns de latence)
  • 8192 Mo / 8 Go de cache L4 virtuel partagé hors puce (+? latence)

Techniquement, du point de vue d’un seul cœur, ces chiffres devraient probablement être de 32 Mo / 224 Mo / 7936 Mo, car un seul cœur ne va pas expulser une ligne L2 dans son propre L2 et l’étiqueter comme L3, et ainsi de suite.

IBM déclare qu’en utilisant ce système de cache virtuel, il y a l’équivalent de 1,5 fois plus de cache par cœur que l’IBM z15, mais aussi des latences moyennes améliorées pour l’accès aux données. Globalement, IBM revendique une amélioration des performances par socket de > 40 %. D’autres repères ne sont pas disponibles pour le moment.

Comment est-ce possible?

La magie. Honnêtement, la première fois que j’ai vu cela, j’ai été un peu étonné de ce qui se passait réellement.

Dans la séance de questions-réponses qui a suivi la session, le Dr Christian Jacobi (architecte en chef de Z) a déclaré que le système est conçu pour suivre les données en cas d’échec du cache, utilise les diffusions et que les bits d’état de la mémoire sont suivis pour les diffusions vers des puces externes. Celles-ci traversent l’ensemble du système et lorsque les données arrivent, elles s’assurent qu’elles peuvent être utilisées et confirment que toutes les autres copies sont invalidées avant de travailler sur les données. Dans le canal slack dans le cadre de l’événement, il a également déclaré que de nombreux comptages de cycles se poursuivent !

Je vais m’en tenir à la magie.

À vrai dire, beaucoup de travail est consacré à quelque chose comme ça, et il y a probablement encore beaucoup de considérations à soumettre à IBM au sujet de son fonctionnement, comme l’alimentation active, ou si les caches sont mis hors tension en veille ou même exclus de l’acceptation expulsions pour garantir la cohérence des performances d’un seul cœur. Cela me fait penser à ce qui pourrait être pertinent et possible dans le monde x86, ou même avec des appareils grand public.

Je m’en voudrais de parler des caches si je ne mentionnais pas la prochaine technologie V-cache d’AMD, qui est configurée pour activer 96 Mo de cache L3 par puce plutôt que 32 Mo en ajoutant une puce L3 de 64 Mo empilée verticalement sur le dessus. Mais qu’est-ce que cela signifierait pour les performances si cette puce n’était pas L3, mais considérait plutôt 8 Mo supplémentaires de L2 par cœur, avec la possibilité d’accepter des lignes de cache L3 virtuelles ?

En fin de compte, j’ai parlé avec des pairs de l’industrie de l’idée de mise en cache virtuelle d’IBM, avec des commentaires allant de « ça ne devrait pas bien fonctionner » à « c’est complexe » et « s’ils peuvent le faire comme indiqué, c’est plutôt cool ».