Pourquoi la taille du cache L1 est-elle plus petite que celle du cache L2 dans la plupart des processeurs?
pourquoi la taille du cache L1 est-elle plus petite que celle du cache L2 dans la plupart des processeurs ?
7 réponses
il y a différentes raisons à cela.
L2 existe dans le système pour accélérer le cas où il ya un cache L1 miss. Si la taille de L1 était la même ou plus grande que la taille de L2, alors L2 ne pourrait pas accommoder plus de lignes de cache que L1, et ne serait pas en mesure de traiter les erreurs de cache L1. Du point de vue de la conception et des coûts, le cache L1 est relié au processeur et plus rapide que le cache L2. L'idée générale des caches est que vous accélérez l'accès au matériel plus lent en ajouter du matériel intermédiaire qui est plus performant (et coûteux) que le matériel le plus lent et encore moins cher que le matériel plus rapide que vous avez. Même si vous décidez de doubler le cache L1, vous incrémenterez également L2, pour accélérer les erreurs de cache L1.
alors pourquoi y a-t-il un cache L2? Eh bien, le cache L1 est habituellement plus performant et plus coûteux à construire, et il est relié à un seul noyau. Cela signifie que l'augmentation de la taille L1 par une quantité fixe aura ce coût multiplié par 4 dans un processeur dual core, ou par 8 en un quad core. L2 est généralement partagé par différents noyaux --selon l'architecture, il peut être partagé entre un couple ou tous les noyaux dans le processeur, de sorte que le coût de l'augmentation de L2 serait plus faible même si le prix de L1 et L2 étaient les mêmes --ce qui n'est pas le cas.
L1 est très étroitement couplé au noyau CPU, et est accessible sur chaque accès mémoire (très fréquent). Ainsi, il a besoin de retourner les données très rapidement (généralement à l'intérieur sur le cycle d'horloge). La latence et le débit (bande passante) sont tous deux critiques pour les performances de la cache de données L1. (par exemple, quatre cycles de latence, et deux lectures de support et une écriture par le noyau CPU chaque cycle d'horloge). Il a besoin de beaucoup de ports de lecture/écriture pour supporter cette bande passante d'accès élevée. Construire une grande cache avec ces les propriétés sont impossibles. Ainsi, les concepteurs le gardent petit, par exemple 32KB dans la plupart des processeurs aujourd'hui.
L2 n'est accessible que sur les L1 manquées, donc les accès sont moins fréquents (généralement 1/20ème de la L1). Ainsi, L2 peut avoir une latence plus élevée (par exemple de 10 à 20 cycles) et avoir moins de ports. Cela permet aux concepteurs de faire plus grand.
L1 et L2 jouent des rôles très différents. Si L1 est agrandie, cela augmentera la latence d'accès de L1 qui réduire drastiquement les performances, car cela rendra toutes les charges dépendantes plus lentes et plus difficiles à masquer pour une exécution hors ordre. La taille de L1 est à peine discutable.
si nous supprimons L2, les échecs de L1 devront passer au niveau suivant, disons mémoire. Cela signifie que beaucoup d'accès sera à la mémoire qui impliquerait nous avons besoin de plus de bande passante mémoire, ce qui est déjà un goulot d'étranglement. Ainsi, le maintien de la L2 est favorable.
les Experts se réfèrent souvent à L1 comme un le filtre de latence (car il rend le cas commun des hits L1 plus rapide) et L2 comme un filtre de bande passante car il réduit l'utilisation de bande passante de mémoire.
Note: j'ai supposé un niveau 2 hiérarchie de cache dans mon argument pour le rendre plus simple. Dans la plupart des puces multicore d'aujourd'hui, il y a un cache L3 partagé entre tous les noyaux, alors que chaque noyau a sa propre L1 privée et peut-être L2. Dans ces puces, le cache de dernier niveau partagé (L3) joue le rôle de bande passante mémoire filtrer. L2 joue le rôle de filtre de bande passante sur puce, c'est-à-dire qu'il réduit l'accès à l'interconnexion sur puce et à la L3. Cela permet aux concepteurs d'utiliser une connexion à bande passante plus basse comme un anneau, et un port L3 lent, ce qui leur permet de rendre L3 plus grand.
peut-être vaut-il la peine de mentionner que le nombre de ports est un point de conception très important parce qu'il affecte combien de zone de puce le cache consomme. Les Ports ajoutent des fils au cache qui consomme beaucoup de zone de puce et puissance.
@Aater la réponse explique certains principes de base . Je vais ajouter quelques détails + un exemple de l'organisation du cache réel sur Intel Haswell et AMD Piledriver, avec des latences et d'autres propriétés, pas seulement la taille.
pour plus de détails sur IvyBridge, voir ma réponse sur" comment cache peut-il être aussi rapide?" , avec une discussion sur la latence globale de l'utilisation de la charge, y compris le temps de calcul de l'adresse, et les largeurs des bus de données entre différents niveaux de cache.
L1 doit être très rapide (latence et débit), même si cela signifie un taux de réponse limité . L1d doit également prendre en charge " single-byte stores sur presque toutes les architectures, et (dans certains designs) accès non aligné. Cela rend difficile d'utiliser ECC (codes de correction d'erreurs) pour protéger les données, et en fait certains L1D designs (Intel) juste utilisez la parité, avec une meilleure ECC seulement dans les niveaux externes de cache (L2 / L3) où L'ECC peut être fait sur de plus gros morceaux pour les frais généraux inférieurs.
il est impossible de concevoir un niveau unique de cache qui pourrait fournir la faible latence moyenne de requête (moyenne sur toutes les hits et les erreurs) d'un moderne cache à niveaux multiples . Depuis les systèmes modernes ont plusieurs noyaux très affamés tous partageant une connexion à la même latence relativement élevée DRAM, ce qui est essentiel.
chaque noyau a besoin de son propre L1 privé pour la vitesse, mais au moins le dernier niveau de cache est typiquement partagé, donc un programme multi-threadé qui lit les mêmes données à partir de plusieurs threads n'a pas à aller à DRAM pour lui sur chaque noyau. (Et d'agir comme un backstop pour les données écrites par un noyau et lues par un autre). cela nécessite au moins deux niveaux de cache pour un système multi-noyau sain, et fait partie de la motivation pour plus plus de 2 niveaux dans les conceptions actuelles. Les processeurs multi-core x86 modernes ont un cache rapide à 2 niveaux dans chaque cœur, et un plus grand cache plus lent partagé par tous les cœurs.
L1 taux de succès est encore très important, de sorte L1 caches ne sont pas que des petites / simple / rapide comme ils pourraient l'être, parce que cela permettrait de réduire le taux de réussite. Pour obtenir la même performance globale, il faudrait donc des niveaux de cache plus élevés pour être plus rapides. Si les niveaux supérieurs gèrent plus de trafic, leur latence est une composante plus importante de la la latence moyenne, et ils goulot d'étranglement sur leur débit plus souvent (ou besoin de débit plus élevé).
haut débit signifie souvent être capable de gérer plusieurs lectures et écritures à chaque cycle, c'est-à-dire plusieurs ports. Cela prend plus de superficie et de puissance pour la même capacité qu'un cache à faible débit, donc c'est une autre raison pour L1 de rester petit.
L1 utilise également des trucs de vitesse qui ne travailler si elle était plus grande . c'est-à-dire que la plupart des conceptions utilisent virtuellement indexé, physiquement étiqueté (VIPT) L1, mais avec tous les bits d'index venant d'en bas de la page offset afin qu'ils se comportent comme PIPT (parce que les bits bas d'une adresse virtuelle sont les mêmes que dans l'adresse physique). Cela évite synonymes / homonymes (faux hits ou les mêmes données étant dans la cache deux fois, et voir la réponse détaillée de Paul Clayton sur la question liée), mais encore permet qu'une partie du contrôle hit/miss se déroule en parallèle avec la recherche TLB. Un cache VIVT n'a pas à attendre le TLB, mais il doit être invalidé à chaque changement des tables de page.
sur x86 (qui utilise des pages de mémoire virtuelle 4kiB), les caches L1 associatives 8-way 32kiB sont courantes dans les conceptions modernes. Les 8 balises peuvent être récupérées en se basant sur les 12 bits les plus bas de l'adresse virtuelle, parce que ces bits sont les mêmes dans les adresses virtuelles et physiques (ils sont en dessous de l'offset de la page pour les pages de 4kiB). Ce hack de vitesse pour les caches L1 ne fonctionne que s'ils sont suffisamment petits et associatifs pour que l'index ne dépende pas du résultat TLB. 32kiB / 64B lignes / 8-way associativité = 64 (2^6) ensembles. Ainsi, les 6 bits les plus bas d'une adresse sélectionnent des octets dans une ligne, et les 6 bits suivants index un ensemble de 8 balises. Cet ensemble de 8 balises est récupéré en parallèle avec la recherche TLB, de sorte que les balises peuvent être vérifiées en parallèle avec les bits de sélection de la page physique de la TLB résultat pour déterminer laquelle (si elle existe) des 8 façons du cache détient les données.
fabriquer un cache L1 plus grand signifierait qu'il devait soit attendre le résultat TLB avant même de pouvoir commencer à récupérer les tags et les charger dans les comparateurs parallèles, soit augmenter l'associativité pour garder log2(sets) + log2(line_size) <= 12. (Plus d'associativité signifie plus de façons par ensemble => moins d'ensembles totaux = moins de bits d'index). Ainsi, par exemple, un cache 64kiB devrait être 16-way associatif: toujours 64 sets, mais chaque sets a deux fois plus de moyens. Cela rend l'augmentation de la taille de L1 au-delà de la taille actuelle prohibitivement coûteuse en termes de puissance, et probablement même de latence.
dépenser plus de votre budget d'énergie sur la logique de cache L1D laisserait moins d'énergie disponible pour l'exécution hors-ordre, le décodage, et bien sûr cache L2 et ainsi de suite . Obtenir le noyau entier pour fonctionner à 4GHz et soutenir ~4 instructions par horloge (sur high-ILP code sans fondre nécessite une conception équilibrée. Voir cet article: microprocesseurs modernes: un Guide de 90 minutes! .
plus un cache est grand, plus vous le perdez en le vidant, donc un grand cache VIVT L1 serait pire que le VIPT-that-works-like-PIPT actuel. Et une latence plus grande mais plus élevée L1D serait probablement aussi pire.
selon @PaulClayton , les caches de L1 récupèrent souvent tous les data dans un ensemble en parallèle avec les tags, il est donc prêt à être sélectionné une fois que l'étiquette droite est détectée. Le coût de l'alimentation de le faire échelles avec l'associativité, de sorte que un grand hautement associatif L1 serait vraiment mauvais pour la tension d'utilisation ainsi que de mourir de la zone (et de temps de latence) . (Comparé à L2 et L3, ce ne serait pas beaucoup de zone, mais la proximité physique est importante pour la latence. Les retards de propagation de la vitesse de la lumière sont importants lorsque les cycles d'horloge sont 1/4 d'un nanoseconde.)
les caches plus lentes (comme L3) peuvent fonctionner à une tension plus basse / vitesse d'horloge pour faire moins de chaleur. Ils peuvent même utiliser différents arrangements de transistors pour chaque cellule de stockage, pour rendre la mémoire plus optimisée pour la puissance que pour la grande vitesse.
il y a beaucoup de raisons liées à l'utilisation de la puissance pour les caches multi-niveaux. Puissance / chaleur est l'une des contraintes les plus importantes dans la conception CPU moderne, parce que le refroidissement d'une puce minuscule est difficile. Tout est une compromis entre vitesse et puissance (et/ou zone). En outre, de nombreux CPU sont alimentés par des batteries ou sont dans des centres de données qui ont besoin d'un refroidissement supplémentaire.
L1 est presque toujours divisé en instruction séparée et des caches de données. au lieu d'un port de lecture supplémentaire dans une L1 unifiée pour supporter le code-fetch, nous pouvons avoir un cache L1I séparé lié à une I-TLB séparée. (Les CPU modernes ont souvent un TLB-L2, qui est un deuxième niveau de cache pour les traductions qui sont partagées par le I-TLB et le D-TLB, pas un TLB utilisé par le cache L2 régulier). Cela nous donne un total de 64kib de cache L1, statiquement partitionné dans des caches de code et de données, pour beaucoup moins cher (et probablement moins de latence) qu'un cache L1 unifié monster 64k avec le même débit total. Comme il y a habituellement très peu de chevauchement entre le code et les données, il s'agit d'une grande victoire.
L1I peut être placé physiquement près de la logique du code-fetch, tandis que L1D peut être physiquement proche des unités de chargement/stockage. Les retards dans les lignes de transmission de la vitesse de la lumière sont importants lorsqu'un cycle d'horloge ne dure qu'un tiers d'une nanoseconde. Le routage du câblage est également important: par exemple Intel Broadwell a 13 couches de cuivre au-dessus du silicium .
Split L1 aide beaucoup avec la vitesse, mais la L2 unifiée est le meilleur choix. Certaines charges de travail ont un code très petit mais touchent beaucoup de données. Il fait sens pour de plus haut niveau les caches doivent être unifiées pour s'adapter aux différentes charges de travail, au lieu de se diviser statiquement en code vs. données. (par exemple, la quasi-totalité de L2 sera mise en cache des données, pas de code, lors de l'exécution d'une grande matrice multiplier, vs. ayant beaucoup de code chaud lors de l'exécution d'un programme C++ gonflé, ou même une mise en œuvre efficace d'un algorithme compliqué (par exemple, exécuter gcc)). Le Code peut être copié en tant que données, pas toujours simplement chargé à partir du disque dans la mémoire avec DMA.
Les Caches ont aussi besoin d'une logique pour suivre les erreurs en suspens (puisque l'exécution hors-ordre signifie que de nouvelles requêtes peuvent être générées avant que la première erreur ne soit résolue). Avoir beaucoup de ratés en suspens signifie que vous chevauchez la latence des ratés, en obtenant un débit plus élevé. Dupliquer la logique et / ou le partitionnement statique entre le code et les données en L2 ne serait pas bon.
de plus grandes caches à faible trafic sont également un bon endroit pour mettre la logique pré-fetching. Matériel pré-fetching permet une bonne performance pour des choses comme la boucle sur un tableau sans Chaque morceau de code ayant besoin du logiciel-instructions de préfetch. (SW prefetch était important pendant un certain temps, mais les préfetchers HW sont plus intelligents qu'ils ne l'étaient, de sorte que le conseil dans Ulrich Drepper autrement excellent ce que chaque programmeur devrait savoir sur la mémoire est périmé pour de nombreux cas d'utilisation.)
Faible trafic de niveau supérieur caches peuvent permettre la latence pour faire des choses intelligentes comme l'utilisation d'un Politique de remplacement adaptatif au lieu de la LRU habituelle. Intel IvyBridge et plus tard CPUs font ce , pour résister à des modèles d'accès qui n'obtiennent pas de résultats de cache pour un ensemble de travail juste un peu trop grand pour s'intégrer dans le cache. (par exemple, en bouclant certaines données dans la même direction deux fois signifie qu'il est probablement expulsé juste avant qu'il ne soit réutilisé.)
Un exemple réel: Intel Haswell . Sources: David Kanter de la microarchitecture de l'analyse et Agner Brouillard résultats des tests de l' (microarch pdf) . Voir aussi les manuels D'optimisation D'Intel (liens dans le wiki x86 tag).
J'ai aussi écrit une réponse séparée sur: quelle technique de mappage de cache est utilisée dans le processeur intel core i7?
Intel designs modernes utilisent une grande cache L3 partagée par tous les noyaux comme un backstop pour le trafic de cohérence de cache . Il est physiquement distribué entre les noyaux, avec 2048 ensembles * 16-way (2MiB) par noyau (avec une politique de remplacement adaptative à IvyBridge et plus tard ).
les niveaux inférieurs de cache sont par noyau.
- L1 : par carotte 32kiB chacun d'instruction et de données (split), 8-way associatif. "1519110920 de" Latence = 4 cycles . Au moins 2 ports de lecture + 1 port d'écriture. ( peut-être même plus de ports pour gérer le trafic entre L1 et L2 , ou peut-être recevoir une ligne de cache de L2 est en conflit avec le retrait d'un magasin.) Peut suivre 10 erreurs de cache en suspens (10 tampons de remplissage).
- L2 : unifiés par coeur 256kiB, 8-way associatif. latence = 11 ou 12 cycles . Lire bande passante: 64 octets / cycle. La logique de préfetching principale préfigure en L2. Peut suivre 16 erreurs en suspens. Peut fournir 64B par cycle au L1I ou au L1D. Le nombre réel de ports est inconnu.
- L3 : unifiée, partagée par tous les cœurs) 8MiB (pour un quad-core i7). Inclusivement (de toutes les caches L2 et L1 par carotte). 12 ou 16 voies associatives. "1519110920 de" Latence = 34 cycles . Agit comme un backstop pour cache-cohérence, de sorte que les données partagées modifiées n'ont pas besoin de sortir de la mémoire principale et de revenir en arrière.
un autre exemple réel: AMD Piledriver : (par exemple Opteron et CPU desktop FX.) La taille de la ligne Cache est toujours 64B, comme Intel et AMD l'utilisent depuis plusieurs années maintenant. Texte principalement copié à partir de Agner Fog microarch pdf, avec des informations supplémentaires à partir de certaines diapositives , j'ai trouvé , et plus de détails sur le écrire-à travers L1 + 4K écrire-combinant cache sur le blog D'Agner , avec un commentaire que seul L1 est WT, et non L2 .
- l1i : 64 kB, 2-way, partagé entre deux noyaux (la version AMD de SMD a plus de partitionnement statique que L'Hyperthreading, et ils appellent chacun un noyau. Chaque paire partage une unité vectorielle / FPU et d'autres ressources pipelinières.)
- L1D : 16 ko, 4-way, par cœur. "1519110920 de" Latence = 3-4 c . (Notez que les 12 bits en dessous de l'offset de la page sont toujours utilisés pour index, donc l'astuce habituelle VIPT fonctionne.) (débit: deux opérations par horloge, l'une d'entre elles étant un magasin). Policy = Write-Through , avec un cache 4K combinant l'écriture.
- L2 : 2 MO, 16-way, partagé entre deux noyaux. Latence = 20 horloges . Lire le débit 1 par 4 horloge. Ecrire le débit 1 par 12 horloge.
- L3 : 0 - 8 MB, 64-way, partagé entre tous les cœurs. "1519110920 de" Latence = 87 horloge . Lire le débit 1 par 15 Horloge. Débit d'écriture 1 par 21 horloge
Agner Fog rapporte qu'avec les deux noyaux d'une paire active, le débit L1 est plus faible que lorsque l'autre moitié d'une paire est au ralenti. Ce n'est pas on sait ce qui se passe, puisque les caches L1 sont supposées être séparées pour chaque noyau.
je pense que la raison principale pour cela est, que L1-Cache est plus rapide et donc plus cher.
pour ceux qui s'intéressent à ce type de questions, mon université recommande Architecture informatique: une approche Quantitative et organisation et conception informatiques: L'Interface matériel/logiciel . Bien sûr, si vous n'avez pas le temps pour cela, un aperçu rapide est disponible sur Wikipedia .
les autres réponses ici donnent des raisons spécifiques et techniques pour lesquelles L1 et L2 sont dimensionnés tels qu'ils sont, et alors que beaucoup d'entre eux sont des considérations motivantes pour des architectures particulières, ils ne sont pas vraiment nécessaires: la pression architecturale sous-jacente conduisant à augmenter les tailles (privées) de cache que vous vous éloignez du noyau est assez universelle et est le même que le raisonnement pour les caches multiples en premier lieu.
les trois faits de base sont:
- les accès à la mémoire pour la plupart des applications présentent un haut degré de localisation temporelle, avec une distribution non uniforme.
- pour une grande variété de processus et de conceptions, la taille et la vitesse de la cache (latence et débit) peuvent être échangées entre elles 1 .
- chaque niveau distinct de cache implique des coûts de conception et de performance supplémentaires.
ainsi à une base niveau, vous pourriez être en mesure de dire le double de la taille du cache, mais encourir une pénalité de latence de 1,4 par rapport au cache plus petit.
ainsi, il devient un problème d'optimisation: combien de caches devez-vous avoir et quelle taille doivent-ils être? Si l'accès à la mémoire était totalement uniforme dans la taille de jeu de travail, vous finiriez probablement avec un seul cache assez grand, ou pas de cache du tout. Cependant, l'accès est fortement non uniforme, de sorte qu'un cache petit et rapide peut capturer un grand nombre de accès disproportionnés par rapport à sa taille.
si fact 2 n'existait pas, vous créeriez juste un cache L1 très grand et très rapide dans les autres contraintes de votre puce et vous n'auriez pas besoin d'autres niveaux de cache.
si fact 3 n'existait pas, vous finiriez avec un grand nombre de" caches " à grain fin, plus rapides et petits au centre, et plus lents et plus grands à l'extérieur, ou peut-être un seul cache avec des temps d'accès variables: plus rapides pour les parties les plus proches du noyau. Dans pratique, la règle 3 signifie que chaque niveau de cache a un coût supplémentaire, donc vous finissez généralement avec quelques niveaux quantifiés de cache 2 .
Autres Contraintes
cela donne un cadre de base pour comprendre les décisions de comptage et de dimensionnement de cache, mais il y a aussi des facteurs secondaires en jeu. Par exemple, Intel x86 a des tailles de page 4K et leurs caches L1 utilisent une architecture VIPT . VIPT signifie que le la taille du cache divisée par le nombre de voies ne peut pas être plus grande 3 que 4 KiB. Ainsi, un cache L1 8-way utilisé sur la demi-douzaine de conceptions Intel peut être au plus 4 KiB * 8 = 32 KiB. Ce n'est probablement pas un hasard si c'est exactement la taille du cache L1 sur ces designs! S'il n'y avait pas cette contrainte, il est tout à fait possible que vous ayez vu des caches de L1 et/ou des caches plus larges (par exemple, 64 KiB, 4-way).
1 bien sûr, il y a d'autres facteurs impliqués dans le compromis, comme la superficie et la puissance, mais en maintenant ces facteurs constants, le compromis taille-vitesse s'applique, et même si on ne maintient pas constant le comportement de base est le même.
2 en plus de cette pression, il y a un avantage d'ordonnancement pour les caches à latence connue, comme la plupart des conceptions L1: et Out-of-order scheduler peut présenter de façon optimiste des opérations qui dépendent d'un charge mémoire sur le cycle que le cache L1 retournerait, lisant le résultat du réseau de contournement. Cela réduit la controverse et peut-être élimine un cycle de latence du chemin critique. Cela met une certaine pression sur le niveau de cache le plus proche pour avoir une latence uniforme/prévisible et entraîne probablement moins de niveaux de cache.
3 en principe, vous pouvez utiliser les caches VIPT sans cette restriction, mais seulement en exigeant la prise en charge du système D'exploitation (par exemple, la coloration de la page) ou avec d'autres contraintes. Le x86 arch n'a pas fait ça et ne peut probablement pas commencer maintenant.
logiquement, la question se répond d'elle-même.
si L1 était plus grand que L2 (combiné), alors il n'y aurait pas besoin de Cache L2.
pourquoi stocker vos affaires sur cassette si vous pouvez tout stocker sur disque dur ?