Qu'est-ce que le cache du disque dur et à quoi sert-il ? Impact de la capacité du cache sur la taille de la mémoire du processeur de performance Core i5 de 3e génération

Bonne journée à tous. Aujourd'hui, nous allons essayer de vous expliquer une chose telle qu'une cache. Le cache du processeur est une matrice de traitement de données ultra-rapide qui est 16 à 17 fois plus rapide que la RAM standard en matière de DDR4.

De cet article, vous apprendrez:

C'est la quantité de mémoire cache qui permet au CPU de fonctionner à des vitesses maximales, sans attendre que la RAM traite les données et envoie les résultats des calculs finis à la puce pour un traitement ultérieur. Un principe similaire peut être tracé dans le disque dur, seul un tampon de 8 à 128 Mo y est utilisé. Une autre chose est que les vitesses sont beaucoup plus faibles, mais le processus est similaire.

Qu'est-ce qu'un cache processeur ?

Comment fonctionne le processus de calcul en général ? Toutes les données sont stockées dans la RAM, qui est conçue pour le stockage temporaire d'informations importantes sur l'utilisateur et le système. Le processeur sélectionne pour lui-même un certain nombre de tâches qui sont pilotées dans un bloc ultra-rapide appelé mémoire cache, et commence à faire ses tâches directes.

Les résultats du calcul sont à nouveau envoyés à la RAM, mais dans une quantité beaucoup plus petite (au lieu de mille valeurs de sortie, nous obtenons beaucoup moins), et un nouveau tableau est pris pour le traitement. Et ainsi de suite jusqu'à ce que le travail soit terminé.

La vitesse de travail est déterminée par l'efficacité de la RAM. Mais pas un seul module DDR4 moderne, y compris les solutions d'overclocking avec des fréquences inférieures à 4000 MHz, n'était proche des capacités du processeur le plus rachitique avec son cache "lent".

En effet, la vitesse du processeur dépasse les performances de la RAM en moyenne 15 fois, voire plus. Et ne regardez pas seulement les paramètres de fréquence, en plus d'eux, il y a suffisamment de différences.
En théorie, il s'avère que même les super puissants Intel Xeon et AMD Epyc sont obligés de rester inactifs, mais en fait, les deux puces de serveur fonctionnent à leur limite. Et tout cela parce qu'ils collectent la quantité de données requise par la taille du cache (jusqu'à 60 Mo ou plus) et traitent les données instantanément. La RAM sert comme une sorte d'entrepôt à partir duquel les tableaux sont récupérés pour les calculs. L'efficacité de calcul de l'ordinateur augmente et tout le monde est content.

Une brève excursion dans l'histoire

La première mention de la mémoire cache remonte à la fin des années 80. Jusque-là, la vitesse du processeur et de la mémoire étaient à peu près les mêmes. Le développement rapide des puces nécessitait une sorte de "béquille" pour augmenter la vitesse de la RAM, mais l'utilisation de puces ultra-rapides était très coûteuse, et ils ont donc décidé de se contenter d'une option plus économique - l'introduction d'une mémoire haute vitesse tableau dans le CPU.

Le module de mémoire cache est apparu pour la première fois dans l'Intel 80386. À cette époque, les latences DRAM oscillaient autour de 120 nanosecondes, tandis qu'un module SRAM plus moderne réduisait la latence à un impressionnant 10 nanosecondes à ce moment-là. Une image approximative est plus clairement démontrée dans la confrontation entre HDD et SSD.

Initialement, la mémoire cache était soudée directement sur les cartes mères, en raison du niveau du processus technique de l'époque. À partir de l'Intel 80486, 8 Ko de mémoire ont été incorporés directement dans la matrice du processeur, augmentant encore les performances et réduisant la surface de la matrice.

Cette technologie de mise en page n'est restée pertinente que jusqu'à la sortie du Pentium MMX, après quoi la mémoire SRAM a été remplacée par une SDRAM plus avancée.
Et les processeurs sont devenus beaucoup plus petits, et donc le besoin de circuits externes a disparu.

Niveaux de cache

Sur le marquage des processeurs modernes, en plus de et, vous pouvez trouver une taille de cache de 1,2 et 3 niveaux. Comment est-il défini et qu'affecte-t-il ? Comprenons en termes simples.

  • Le cache de premier niveau (L1) est la puce la plus importante et la plus rapide de l'architecture CPU. Un processeur peut accueillir le nombre de modules égal au nombre de cœurs. Il est à noter que le microcircuit ne peut stocker en mémoire les données les plus demandées et les plus importantes qu'à partir de son noyau. La taille du tableau est souvent limitée à 32-64 Ko.
  • Cache du deuxième niveau (L2) - la baisse de vitesse est compensée par une augmentation de la taille du tampon, qui atteint 256 voire 512 Ko. Le principe de fonctionnement est le même que celui de L1, mais la fréquence de demande de mémoire est plus faible, en raison du stockage de données moins prioritaires.
  • Le cache de troisième niveau (L3) est la partition la plus lente et la plus volumineuse parmi toutes celles répertoriées. Pourtant, ce tableau est beaucoup plus rapide que la RAM. La taille peut atteindre 20, voire 60 Mo, lorsqu'il s'agit de puces de serveur. L'intérêt de la baie est énorme : c'est un maillon clé dans l'échange de données entre tous les cœurs du système. Sans L3, tous les éléments de la puce seraient dispersés.

En vente, vous pouvez trouver une structure de mémoire à deux et trois niveaux. Quel est le meilleur? Si vous utilisez le processeur uniquement pour les programmes de bureau et les jeux occasionnels, vous ne sentirez aucune différence. Si le système est assemblé avec un œil sur les jeux 3D complexes, l'archivage, le rendu et les graphismes, l'augmentation dans certains cas ira de 5 à 10 %.
Un cache L3 ne se justifie que si vous avez l'intention de travailler régulièrement avec des applications multi-thread qui nécessitent des calculs complexes réguliers. Pour cette raison, les modèles de serveur utilisent souvent de grands caches L3. Bien qu'il y ait des moments où cela ne suffit pas, vous devez donc installer en plus les modules dits L4, qui ressemblent à un microcircuit séparé connecté à la carte mère.

Comment connaître le nombre de niveaux et la taille du cache de votre processeur ?

Commençons par le fait que cela peut se faire de 3 façons :

  • via la ligne de commande (cache L2 et L3 uniquement) ;
  • en recherchant des spécifications sur Internet ;
  • à l'aide d'utilitaires tiers.

Si nous prenons comme base le fait que pour la plupart des processeurs L1 est de 32 Ko, et que L2 et L3 peuvent fluctuer considérablement, nous avons besoin des 2 dernières valeurs. Pour les rechercher, ouvrez la ligne de commande via "Démarrer" (entrez la valeur "cmd" via la barre de recherche).

Le système affichera une valeur anormalement élevée pour L2. Vous devez le diviser par le nombre de cœurs de processeur et connaître le résultat final.

Si vous allez rechercher des données sur le réseau, recherchez d'abord le nom exact de la CPU. Faites un clic droit sur l'icône "Poste de travail" et sélectionnez "Propriétés". Dans la colonne "Système", il y aura un élément "Processeur", dont nous avons réellement besoin. Réécrivez son nom dans le même Google ou Yandex et voyez la valeur sur les sites. Pour des informations fiables, mieux vaut choisir les portails officiels du constructeur (Intel ou AMD).
La troisième méthode ne pose pas non plus de problèmes, mais nécessite l'installation de logiciels supplémentaires tels que GPU-Z, AIDA64 et d'autres utilitaires pour étudier les spécifications de la pierre. Une option pour les fans d'overclocking et d'essaimage dans le détail.

Résultats

Vous comprenez maintenant ce qu'est la mémoire cache, de quoi dépend sa taille et à quelles fins un tableau de données ultra-rapide est utilisé. À l'heure actuelle, les solutions les plus intéressantes du marché en termes de grandes quantités de mémoire cache sont les appareils AMD Ryzen 5 et 7 avec leurs 16 Mo L3.

Dans les articles suivants, nous aborderons des sujets tels que les processeurs, les avantages des puces, etc. et reste avec nous. Jusqu'à ce que nous nous revoyions, au revoir.

Tous les utilisateurs connaissent bien les éléments d'un ordinateur tels qu'un processeur chargé de traiter les données, ainsi qu'une mémoire vive (RAM ou RAM) chargée de les stocker. Mais tout le monde ne sait probablement pas qu'il existe également un cache de processeur (Cache CPU), c'est-à-dire la RAM du processeur lui-même (la mémoire dite super-RAM).

Quelle est la raison qui a poussé les développeurs informatiques à utiliser une mémoire spéciale pour le processeur ? La RAM n'est-elle pas suffisante pour un ordinateur ?

En effet, pendant longtemps, les ordinateurs personnels se sont passés d'aucune sorte de mémoire cache. Mais, comme vous le savez, le processeur est le périphérique le plus rapide d'un ordinateur personnel et sa vitesse a augmenté avec chaque nouvelle génération de CPU. Actuellement, sa vitesse se mesure en milliards d'opérations par seconde. Dans le même temps, la RAM standard n'a pas augmenté ses performances de manière significative au cours de son évolution.

De manière générale, il existe deux technologies principales pour les puces mémoire : la mémoire statique et la mémoire dynamique. Sans entrer dans les détails de leur structure, nous dirons seulement que la mémoire statique, contrairement à la mémoire dynamique, ne nécessite pas de régénération ; de plus, 4 à 8 transistors sont utilisés pour un bit d'information en mémoire statique, tandis que 1 à 2 transistors sont utilisés en mémoire dynamique. En conséquence, la mémoire dynamique est beaucoup moins chère que la mémoire statique, mais en même temps beaucoup plus lente. Actuellement, les puces RAM sont fabriquées sur la base de la mémoire dynamique.

Évolution approximative du rapport de la vitesse des processeurs et de la RAM :

Ainsi, si le processeur prenait des informations de la mémoire principale tout le temps, il devrait alors attendre la mémoire dynamique lente, et il serait inactif tout le temps. Dans le même cas, si la mémoire statique était utilisée comme RAM, le coût de l'ordinateur augmenterait plusieurs fois.

C'est pourquoi un compromis raisonnable a été élaboré. La partie principale de la RAM est restée dynamique, tandis que le processeur disposait de son propre cache rapide basé sur des puces de mémoire statiques. Son volume est relativement faible - par exemple, le volume du cache L2 n'est que de quelques mégaoctets. Cependant, il convient de rappeler ici que toute la RAM des premiers ordinateurs IBM PC était inférieure à 1 Mo.

De plus, l'opportunité de mettre en œuvre la technologie de mise en cache est également influencée par le fait que différentes applications qui se trouvent dans la RAM chargent le processeur différemment et, par conséquent, de nombreuses données nécessitent un traitement prioritaire par rapport au reste.

Histoire de la cache

À proprement parler, avant que la mémoire cache ne soit transférée aux ordinateurs personnels, elle avait été utilisée avec succès dans les supercalculateurs pendant plusieurs décennies.

Pour la première fois, une mémoire cache de seulement 16 Ko est apparue dans un PC basé sur le processeur i80386. Les processeurs d'aujourd'hui utilisent différents niveaux de cache, du premier (le cache le plus rapide de la plus petite taille - généralement 128 Ko) au troisième (le cache le plus lent de la plus grande taille - jusqu'à des dizaines de Mo).

Au début, la mémoire cache externe du processeur était située sur une puce séparée. Au fil du temps, cependant, cela a conduit au fait que le bus situé entre le cache et le processeur est devenu un goulot d'étranglement, ralentissant l'échange de données. Dans les microprocesseurs modernes, les premier et deuxième niveaux de mémoire cache sont situés dans le cœur du processeur lui-même.

Pendant longtemps, il n'y avait que deux niveaux de cache dans les processeurs, mais pour la première fois dans le processeur Intel Itanium, une mémoire cache de troisième niveau est apparue, commune à tous les cœurs de processeur. Il existe également des développements de processeurs avec un cache à quatre niveaux.

Architectures et principes de fonctionnement du cache

On connaît à ce jour deux principaux types d'organisation de la mémoire cache, issus des premiers développements théoriques dans le domaine de la cybernétique - les architectures Princeton et Harvard. L'architecture de Princeton implique un seul espace mémoire pour stocker les données et les commandes, tandis que celle de Harvard en a un séparé. La plupart des processeurs d'ordinateurs personnels de la gamme x86 utilisent un type distinct de mémoire cache. De plus, un troisième type de mémoire cache est également apparu dans les processeurs modernes - le soi-disant tampon de traduction associatif, conçu pour accélérer la conversion des adresses de mémoire virtuelle du système d'exploitation en adresses de mémoire physique.

Simplifié, le schéma d'interaction entre la mémoire cache et le processeur peut être décrit comme suit. Tout d'abord, la présence des informations nécessaires au processeur est vérifiée dans le plus rapide - le cache de premier niveau, puis - dans le cache de deuxième niveau, et ainsi de suite. Si les informations nécessaires n'ont été trouvées à aucun niveau du cache, elles signalent une erreur ou un manque de cache. S'il n'y a aucune information dans le cache, le processeur doit les prendre de la RAM ou même de la mémoire externe (du disque dur).

L'ordre dans lequel le processeur recherche les informations en mémoire :

C'est ainsi que le processeur recherche des informations

Pour contrôler le fonctionnement de la mémoire cache et son interaction avec les unités de calcul du processeur, ainsi que la RAM, il existe un contrôleur spécial.

Schéma d'organisation de l'interaction du cœur du processeur, du cache et de la RAM :

Le contrôleur de cache est le lien clé entre le processeur, la RAM et le cache.

Il convient de noter que la mise en cache des données est un processus complexe qui utilise de nombreuses technologies et algorithmes mathématiques. Parmi les concepts de base utilisés en cache, on peut distinguer les méthodes d'écriture d'un cache et l'architecture d'associativité de la mémoire cache.

Méthodes d'écriture du cache

Il existe deux méthodes principales pour écrire des informations dans le cache :

  1. La méthode de réécriture (réécriture) - les données sont d'abord écrites dans le cache, puis, lors de l'apparition de certaines conditions, dans la RAM.
  2. La méthode d'écriture directe (par écriture) - les données sont écrites simultanément dans la RAM et le cache.

Architecture d'associativité du cache

L'architecture d'associativité du cache définit la manière dont les données de la RAM sont mappées au cache. Il existe les principales variantes suivantes de l'architecture d'associativité de mise en cache :

  1. Cache à mappage direct - une zone spécifique du cache est responsable d'une zone spécifique de RAM
  2. Cache entièrement associatif - n'importe quelle zone de cache peut être associée à n'importe quelle zone de RAM
  3. Cache mixte (ensemble-associatif)

Différentes architectures d'associativité de cache peuvent généralement être utilisées à différents niveaux de cache. La mise en cache directe mappée en RAM est l'option de mise en cache la plus rapide. Cette architecture est donc généralement utilisée pour les caches volumineux. À son tour, un cache entièrement associatif a moins d'erreurs de cache (échecs).

Conclusion

Dans cet article, vous vous êtes familiarisé avec le concept de mémoire cache, l'architecture de la mémoire cache et les méthodes de mise en cache, et vous avez appris comment cela affecte les performances d'un ordinateur moderne. La présence de mémoire cache peut optimiser considérablement les performances du processeur, réduire son temps d'inactivité et, par conséquent, augmenter les performances de l'ensemble du système.

L'article d'aujourd'hui n'est pas un matériau indépendant - il continue simplement l'étude des performances de trois générations de l'architecture Core sur un pied d'égalité (commencée à la fin de l'année dernière et poursuivie récemment). Certes, aujourd'hui, nous ferons un petit pas de côté - les fréquences des cœurs et de la mémoire cache resteront les mêmes qu'avant, mais la capacité de cette dernière diminuera. Pourquoi est-ce nécessaire ? Nous avons utilisé un Core i7 "complet" des deux dernières générations pour la pureté de l'expérience, en le testant avec le support activé et désactivé de la technologie Hyper-Threading, puisque cela fait un an et demi que le Core i5 est fourni avec non 8 , mais 6 Mio L3. Il est clair que l'effet de la capacité de la mémoire cache sur les performances n'est pas aussi important qu'on le croit parfois, mais il est là, et il n'y a pas moyen de s'en éloigner. De plus, les Core i5 sont des produits plus fabriqués en série que les Core i7, et dans la première génération, personne ne les a «offensés» dans ce paramètre. Mais avant, ils étaient légèrement limités d'une manière différente: la vitesse d'horloge UnCore dans la première génération i5 n'était que de 2,13 GHz, donc notre "Nehalem" n'est pas exactement un représentant de la 700e ligne à 2,4 GHz, mais un processeur légèrement plus rapide . Cependant, nous avons jugé inutile d'allonger fortement la liste des participants et de retravailler les conditions de test - de toute façon, comme nous l'avons prévenu plus d'une fois, tester cette ligne n'apporte aucune nouvelle information pratique : les vrais processeurs fonctionnent dans des modes complètement différents. Mais pour ceux qui veulent bien comprendre tous les points subtils, il nous semble que de tels tests seront intéressants.

Configuration du banc d'essai

Nous avons décidé de nous limiter à seulement quatre processeurs, et il y aura deux participants principaux : les deux Ivy Bridge quad-core, mais avec des capacités de cache L3 différentes. Le troisième est « Nehalem HT » : la dernière fois, il était presque identique à « Ivy Bridge is simple » en termes de score final. Et "juste Nehalem" qui, comme nous l'avons déjà dit, est légèrement plus rapide que le vrai Core i5 de la première génération, fonctionnant à une fréquence de 2,4 GHz (en raison du fait que la fréquence UnCore était légèrement inférieure dans la 700ème ligne) , mais pas trop radical. Mais la comparaison est également intéressante : d'une part, il y a deux étapes pour améliorer la microarchitecture, d'autre part, la mémoire cache est limitée. A priori, nous pouvons supposer que le premier l'emportera dans la plupart des cas, mais combien et en général - comment les «premiers» et «troisièmes» i5 sont comparables (ajustés pour la fréquence UnCore, bien sûr, bien que s'il y a beaucoup de gens qui veulent voir une comparaison absolument exacte, nous ferons plus tard) est déjà un bon sujet de recherche.

Essai

Traditionnellement, nous divisons tous les tests en un certain nombre de groupes et montrons le résultat moyen pour un groupe de tests/applications sur les diagrammes (pour plus de détails sur la méthodologie de test, voir un article séparé). Les résultats dans les diagrammes sont donnés en points, pour 100 points la performance du système de test de référence, le site de l'échantillon de 2011, est prise. Il est basé sur le processeur AMD Athlon II X4 620, mais la quantité de mémoire (8 Go) et la carte vidéo () sont standard pour tous les tests de la «ligne principale» et ne peuvent être modifiées que dans le cadre d'études spéciales. Ceux qui sont intéressés par des informations plus détaillées sont à nouveau traditionnellement invités à télécharger un tableau au format Microsoft Excel, dans lequel tous les résultats sont affichés à la fois en points convertis et sous forme "naturelle".

Travail interactif dans des packages 3D

La capacité de la mémoire cache a un certain effet, mais elle est inférieure à 1 %. En conséquence, les deux ponts Ivy peuvent être considérés comme identiques l'un à l'autre, mais les améliorations de l'architecture permettent au nouveau Core i5 de dépasser facilement l'ancien Core i7 de la même manière que le fait le nouveau Core i7.

Rendu final des scènes 3D

Dans ce cas, bien sûr, aucune amélioration ne peut compenser l'augmentation du nombre de threads traités, mais aujourd'hui, la chose la plus importante pour nous n'est pas cela, mais l'absence totale d'effet de la capacité de la mémoire cache sur les performances. Ici Celeron et Pentium, comme nous l'avons déjà établi, sont des processeurs différents, donc les programmes de rendu sont sensibles à la capacité L3, mais seulement lorsque cette dernière ne suffit pas. Et 6 MiB pour quatre cœurs, comme nous le voyons, suffisent amplement.

Emballage et déballage

Naturellement, ces tâches sont sensibles à la capacité du cache, mais ici l'effet de son augmentation de 6 à 8 Mio est assez modeste : environ 3,6 %. Plus intéressante, en fait, est la comparaison avec la première génération - les améliorations architecturales permettent au nouveau i5 de "écraser" même l'ancien i7 à fréquences égales, mais c'est dans le classement général : en raison du fait que deux tests sur quatre sont à un seul thread et l'autre est à deux threads. La compression des données par 7-Zip est naturellement la plus rapide sur Nehalem HT : huit flux sont toujours plus rapides que quatre à performances comparables. Mais si nous nous limitons à seulement quatre, alors notre "Ivy Bridge 6M" perd non seulement par rapport à son ancêtre, mais aussi par rapport à l'ancien Nehalem : les améliorations de la microarchitecture cèdent complètement à une diminution de la capacité de la mémoire cache.

Encodage audio

Quelque peu inattendue n'était pas la taille de la différence entre les deux Ivy Bridges, mais le fait qu'elle existe. La vérité est si bon marché qu'elle peut également être attribuée aux caractéristiques des erreurs d'arrondi ou de mesure.

Compilation

Les threads sont importants, mais la capacité du cache l'est tout autant. Cependant, comme d'habitude, pas trop - environ 1,5 %. Une comparaison avec le Core de première génération avec l'Hyper-Threading désactivé est plus intéressante : le nouveau Core i5 l'emporte même à fréquence égale, mais l'un des trois compilateurs (de Microsoft, pour être précis) fonctionnait sur les deux processeurs en même temps. Même avec un avantage de 5 secondes pour l'aîné - malgré le fait que dans ce programme, le Ivy Bridge "full-cache" donne 4 secondes de mieux que Nehalem. En général, ici, on ne peut pas considérer que la diminution de la capacité L3 a grandement affecté les Core i5 de deuxième et troisième génération, mais il y a des nuances.

Calculs mathématiques et d'ingénierie

Encore une fois, moins de 1% d'écart avec le cristal "plus ancien" et encore une victoire convaincante sur la première génération sous toutes ses formes. Ce qui est plus une règle qu'une exception pour de tels tests à faible thread, mais pourquoi ne pas s'en assurer une fois de plus ? Surtout sous une forme aussi épurée, lorsque (contrairement aux tests en mode normal) la différence de fréquences (« standard » ou apparaissant du fait du Turbo Boost) ne gêne pas.

Graphiques matriciels

Mais même avec une utilisation plus complète du multithreading, l'image ne change pas toujours. Et la capacité de la mémoire cache ne donne rien du tout.

Graphiques vectoriels

Et là c'est pareil. Certes, seuls quelques threads de calcul sont nécessaires.

Encodage vidéo

Contrairement à ce groupe, où, pourtant, même l'Hyper-Threading ne permet pas à Nehalem de se battre à armes égales avec les adeptes des nouvelles générations. Mais ils ne sont pas trop gênés par une diminution de la capacité de la mémoire cache. Plus précisément, cela n'interfère pratiquement pas du tout, puisque la différence est à nouveau inférieure à 1%.

Logiciel de bureau

Comme prévu, il n'y a aucun gain de performances à augmenter la capacité du cache (plus précisément, sa baisse à la réduire). Bien que si vous regardez les résultats détaillés, vous pouvez voir que le seul test multithread de ce groupe (à savoir, la reconnaissance de texte dans FineReader) est environ 1,5 % plus rapide à 8 MiB L3 qu'à 6 MiB. Il semblerait - qu'est-ce que 1,5%? Pratiquement parlant, rien. Mais d'un point de vue recherche, c'est déjà intéressant : comme vous pouvez le constater, ce sont les tests multi-threads qui manquent le plus souvent de mémoire cache. En conséquence, la différence (bien que faible) est parfois même là où elle ne devrait pas être. Bien qu'il n'y ait rien d'aussi inexplicable à cela - en gros, dans les tests à faible thread, nous avons 3 à 6 Mio par thread, mais dans les tests multithreads, nous obtenons 1,5 Mio au même endroit. Le premier est beaucoup, mais le second peut ne pas suffire.

Java

Cependant, la machine Java n'est pas d'accord avec cette évaluation, mais cela est également compréhensible: comme nous l'avons déjà écrit plus d'une fois, elle est très bien optimisée, pas du tout pour les processeurs x86, mais pour les téléphones et les cafetières, où il peut y avoir beaucoup de cœurs, mais voici le cache très peu de mémoire. Et parfois, il y a peu de cœurs et de mémoire cache - des ressources coûteuses à la fois en termes de surface de puce et de consommation d'énergie. Et, si quelque chose peut être fait avec des cœurs et des mégahertz, alors avec le cache, tout est plus difficile : dans le Tegra 3 quadricœur, par exemple, ce n'est que 1 MiB. Il est clair que la JVM peut "grogner" encore plus (comme tous les systèmes avec bytecode), ce que nous avons déjà vu en comparant Celeron et Pentium, mais plus de 1,5 Mio par thread, si cela peut être utile, alors pas dans ces tâches , qui sont inclus dans SPECjvm 2008.

Jeux

Nous avions de grands espoirs pour les jeux, car ils s'avèrent souvent plus exigeants que même les archiveurs en termes de capacité de mémoire cache. Mais cela arrive quand il est très petit, et 6 MiB - comme on le voit, suffisent. Et, encore une fois, les processeurs du niveau Core quadricœur de toute génération, même à une fréquence de 2,4 GHz, sont une solution trop puissante pour les applications de jeu utilisées, ils ne seront donc évidemment pas le goulot d'étranglement, mais d'autres composants du système. Par conséquent, nous avons décidé de secouer la poussière des modes à faible qualité graphique - il est clair que pour de tels systèmes, c'est trop synthétique, mais tous nos tests sont synthétiques :)

Lorsque toutes sortes de cartes vidéo et ainsi de suite n'interfèrent pas, la différence entre les deux Ivy Bridges atteint déjà "fou" 3%: dans ce cas, vous pouvez l'ignorer en pratique, mais pour la théorie, c'est beaucoup. Plus est sorti juste seulement dans les archiveurs.

Environnement multitâche

Quelque part, nous avons déjà vu cela. Eh bien, oui - lorsque nous avons testé des processeurs à six cœurs sous LGA2011. Et voilà que la situation se répète : la charge est multi-thread, certains des programmes utilisés sont « gourmands » en mémoire cache, mais son augmentation ne fait que réduire les performances moyennes. Comment cela peut-il être expliqué? A moins que l'arbitrage ne se complique et que le nombre de miss augmente. De plus, nous notons que cela ne se produit que lorsque la capacité de L3 est relativement grande et qu'il y a au moins quatre threads de calcul fonctionnant simultanément - dans le segment du budget, une image complètement différente. Dans tous les cas, comme l'ont montré nos récents tests Pentium et Celeron, pour les processeurs double cœur, l'augmentation de L3 de 2 à 3 Mio ajoute 6 % aux performances. Mais quatre et six cœurs ne donnent pas, c'est un euphémisme, rien. Encore moins que rien.

Total

Un résultat global logique : puisqu'aucune différence significative n'a été trouvée entre les processeurs de tailles L3 différentes, il n'y en a pas non plus dans le "général et l'ensemble". Ainsi, il n'y a aucune raison de s'inquiéter de la diminution de la capacité de mémoire cache des Core i5 de deuxième et troisième génération - les prédécesseurs de la première génération ne sont de toute façon pas des concurrents. Oui, et l'ancien Core i7, en moyenne, ne démontre également qu'un niveau de performances similaire (bien sûr, principalement en raison du décalage dans les applications à faible thread - et il existe des scénarios qu'ils peuvent gérer plus rapidement dans des conditions égales). Mais, comme nous l'avons déjà dit, dans la pratique, les vrais processeurs sont loin d'être égaux en termes de fréquences, de sorte que la différence pratique entre les générations est plus grande que ce que l'on peut obtenir dans de telles études.

Une seule question reste ouverte : nous avons dû fortement réduire la fréquence d'horloge pour assurer la parité avec le Core de première génération, mais les schémas observés vont-ils persister dans des conditions plus proches de la réalité ? Après tout, le fait que quatre threads de calcul à faible vitesse ne voient pas la différence entre 6 et 8 Mo de mémoire cache ne signifie pas qu'elle ne sera pas détectée dans le cas de quatre à grande vitesse. Certes, l'inverse ne s'ensuit pas, donc pour clore enfin le sujet des études théoriques, nous avons besoin d'un autre travail de laboratoire, que nous ferons la prochaine fois.

Quelle est l'importance du cache L3 pour les processeurs AMD ?

En effet, il est logique d'équiper les processeurs multicœurs d'une mémoire dédiée qui sera partagée par tous les cœurs disponibles. Dans ce rôle, un cache L3 rapide peut considérablement accélérer l'accès aux données les plus demandées. Ensuite, les cœurs, s'il y a une telle opportunité, n'auront pas à accéder à la mémoire principale lente (RAM, RAM).

Du moins en théorie. AMD a récemment annoncé le processeur Athlon II X4, qui est un modèle Phenom II X4 sans cache L3, laissant entendre qu'il n'est pas nécessaire. Nous avons décidé de comparer directement deux processeurs (avec et sans cache L3) pour voir comment le cache affecte les performances.

Comment fonctionne le cache ?

Avant de plonger dans les tests, il est important de comprendre quelques notions de base. Le principe du cache est assez simple. Le cache met en mémoire tampon les données aussi près que possible des cœurs de traitement du processeur afin de réduire les requêtes CPU vers une mémoire plus distante et plus lente. Sur les plates-formes de bureau modernes, la hiérarchie du cache comprend jusqu'à trois niveaux qui précèdent l'accès à la RAM. De plus, les caches du deuxième et, en particulier, du troisième niveau ne servent pas uniquement à la mise en mémoire tampon des données. Leur but est d'éviter une surcharge du bus CPU lorsque les cœurs doivent échanger des informations.

Coups et ratés

L'efficacité de l'architecture de cache est mesurée par le pourcentage de hits. Les demandes de données pouvant être satisfaites par le cache sont considérées comme des accès. Si ce cache ne contient pas les données requises, la demande est transmise plus loin dans le pipeline de mémoire et un échec est compté. Bien sûr, les échecs entraînent plus de temps pour obtenir les informations. En conséquence, des "bulles" (temps d'arrêt) et des retards apparaissent dans le pipeline de calcul. Les coups, en revanche, vous permettent de maintenir des performances maximales.

Ecriture cache, exclusivité, cohérence

Les politiques de remplacement dictent la manière dont l'espace de cache est rendu disponible pour les nouvelles entrées. Étant donné que les données écrites dans le cache doivent éventuellement apparaître dans la mémoire principale, les systèmes peuvent le faire en même temps que l'écriture dans le cache (écriture directe), ou ils peuvent marquer les données de la zone comme "sales" (écriture différée), et écrire en mémoire lorsqu'il sera expulsé du cache.

Les données de plusieurs niveaux de cache peuvent être stockées de manière exclusive, c'est-à-dire sans redondance. Vous ne trouverez alors pas de lignes de données identiques dans deux hiérarchies de cache différentes. Ou les caches peuvent fonctionner de manière inclusive, c'est-à-dire que les niveaux inférieurs du cache sont garantis pour contenir les données présentes dans les niveaux supérieurs du cache (plus proches du cœur du processeur). AMD Phenom utilise un cache L3 exclusif, tandis qu'Intel suit une stratégie de cache inclusive. Les protocoles de cohérence assurent la cohérence et la mise à jour des données entre les cœurs, les couches de cache et même les processeurs.

Taille du cache

Un cache plus grand peut contenir plus de données, mais tend à augmenter la latence. De plus, un gros cache consomme un nombre considérable de transistors de processeur, il est donc important de trouver un équilibre entre le "budget" des transistors, la taille du die, la consommation électrique et les performances/latences.

Associativité

Les entrées dans la RAM peuvent être directement mappées sur le cache, c'est-à-dire qu'il n'y a qu'une seule position dans le cache pour une copie des données de la RAM, ou elles peuvent être associatives à n voies, c'est-à-dire qu'il y a n emplacements possibles dans le cache où ces données pourraient être stockées. Une associativité plus élevée (jusqu'à des caches entièrement associatifs) offre la meilleure flexibilité de mise en cache car les données existantes dans le cache n'ont pas besoin d'être écrasées. En d'autres termes, un degré n élevé d'associativité garantit un taux de réussite plus élevé, mais il augmente la latence car il faut plus de temps pour tester toutes ces associations pour un succès. En règle générale, le degré d'association le plus élevé est raisonnable pour le dernier niveau de mise en cache, car la capacité maximale y est disponible, et la recherche de données en dehors de ce cache entraînera un accès lent du processeur à la RAM.

Pour donner quelques exemples, les Core i5 et i7 utilisent 32 Ko de cache L1 avec une associativité à 8 voies pour les données et 32 ​​Ko de cache L1 avec une associativité à 4 voies pour les instructions. Il est compréhensible qu'Intel souhaite que les instructions soient disponibles plus rapidement et que le cache L1 pour les données ait un pourcentage de réussite maximal. Le cache L2 d'Intel a une associativité à 8 voies, tandis que le cache L3 d'Intel est encore plus intelligent car il implémente une associativité à 16 voies pour maximiser les hits.

Cependant, AMD poursuit une stratégie différente avec les processeurs Phenom II X4, qui utilisent le cache L1 avec une associativité à 2 voies pour réduire la latence. Pour compenser d'éventuels ratés, la capacité du cache a été doublée : 64 Ko pour les données et 64 Ko pour les instructions. Le cache L2 a une associativité à 8 voies, comme la conception Intel, mais le cache L3 d'AMD fonctionne avec une associativité à 48 voies. Mais la décision de choisir une architecture de cache ou une autre ne peut être jugée sans tenir compte de l'ensemble de l'architecture du processeur. Il est tout à fait naturel que les résultats des tests aient une importance pratique, et notre objectif était simplement un test pratique de toute cette structure complexe de mise en cache à plusieurs niveaux.

Presque tous les développeurs savent que le cache du processeur est une mémoire si petite mais rapide qui stocke les données des zones de mémoire récemment visitées - la définition est courte et assez précise. Néanmoins, la connaissance des détails "ennuyeux" sur les mécanismes du cache est nécessaire pour comprendre les facteurs qui affectent les performances du code.

Dans cet article, nous examinerons un certain nombre d'exemples illustrant les différentes fonctionnalités des caches et leur impact sur les performances. Les exemples seront en C#, le choix du langage et de la plateforme n'affecte pas tant l'évaluation des performances et les conclusions finales. Naturellement, dans des limites raisonnables, si vous choisissez un langage dans lequel lire une valeur dans un tableau revient à accéder à une table de hachage, vous n'obtiendrez aucun résultat se prêtant à l'interprétation. Les notes du traducteur sont en italique.

Habracut - - -

Exemple 1 : accès mémoire et performances

Selon vous, à quel point la deuxième boucle est-elle plus rapide que la première ?
int arr = nouvel entier ;

// d'abord
pour (int je = 0; je< arr.Length; i++) arr[i] *= 3;

// deuxième
pour (int je = 0; je< arr.Length; i += 16) arr[i] *= 3;


La première boucle multiplie toutes les valeurs du tableau par 3, la deuxième boucle ne multiplie que toutes les seizièmes valeurs. Le deuxième cycle ne fait que 6% travaillent le premier cycle, mais sur les machines modernes, les deux cycles prennent approximativement le même temps : 80ms Et 78 millisecondes respectivement (sur ma machine).

La réponse est simple - l'accès à la mémoire. La vitesse de ces boucles est principalement déterminée par la vitesse du sous-système de mémoire, et non par la vitesse de multiplication d'entiers. Comme nous le verrons dans l'exemple suivant, le nombre d'accès à la RAM est le même dans le premier et le second cas.

Exemple 2 : impact des lignes de cache

Allons plus loin - essayons d'autres valeurs de pas, pas seulement 1 et 16 :
pour (int je = 0; je< arr.Length; i += K /* шаг */ ) arr[i] *= 3;

Voici le temps d'exécution de ce cycle pour différentes valeurs du pas K :

Veuillez noter qu'avec des valeurs de pas de 1 à 16, le temps de fonctionnement ne change pratiquement pas. Mais avec des valeurs supérieures à 16, le temps d'exécution est grosso modo divisé par deux à chaque fois que l'on double le pas. Cela ne signifie pas que la boucle commence comme par magie à s'exécuter plus rapidement, mais simplement que le nombre d'itérations diminue également. Le point clé est le même temps de fonctionnement avec des valeurs de pas de 1 à 16.

La raison en est que les processeurs modernes accèdent à la mémoire non pas par octets, mais par de petits blocs appelés lignes de cache. En règle générale, la taille de la chaîne est de 64 octets. Lorsque vous lisez une valeur de la mémoire, au moins une ligne de cache entre dans le cache. L'accès ultérieur à n'importe quelle valeur de cette chaîne est très rapide.

Comme 16 valeurs int occupent 64 octets, les boucles avec des pas de 1 à 16 accèdent au même nombre de lignes de cache, plus précisément à toutes les lignes de cache du tableau. A l'étape 32, une ligne sur deux est accédée, à l'étape 64, une ligne sur quatre.

Comprendre cela est très important pour certaines méthodes d'optimisation. Le nombre d'accès à celui-ci dépend de l'emplacement des données en mémoire. Par exemple, des données mal alignées peuvent nécessiter deux accès RAM au lieu d'un. Comme nous l'avons découvert plus haut, la vitesse de travail sera deux fois plus faible.

Exemple 3 : tailles des caches de premier et de deuxième niveau (L1 et L2)

Les processeurs modernes ont généralement deux ou trois niveaux de caches, communément appelés L1, L2 et L3. Vous pouvez utiliser l'utilitaire CoreInfo ou la fonction API Windows GetLogicalProcessorInfo pour connaître les tailles des caches à différents niveaux. Les deux méthodes fournissent également des informations sur la taille de la ligne de cache pour chaque niveau.

Sur ma machine, CoreInfo signale des caches de données L1 de 32 Ko, des caches d'instructions L1 de 32 Ko et des caches de données L2 de 4 Mo. Chaque cœur a ses propres caches L1 personnels, les caches L2 sont communs pour chaque paire de cœurs :

Carte du processeur logique au cache : *--- Cache de données 0, niveau 1, 32 Ko, Assoc 8, taille de ligne 64 *--- Cache d'instructions 0, niveau 1, 32 Ko, Assoc 8, taille de ligne 64 -*-- Cache de données 1, Niveau 1, 32 Ko, Assoc 8, LineSize 64 -*-- Cache d'instructions 1, Niveau 1, 32 Ko, Assoc 8, LineSize 64 **-- Cache unifié 0, Niveau 2, 4 Mo, Assoc 16, LineSize 64 --*- Data Cache 2, Niveau 1, 32 Ko, Assoc 8, LineSize 64 --*- Instruction Cache 2, Niveau 1, 32 Ko, Assoc 8, LineSize 64 ---* Data Cache 3, Niveau 1, 32 Ko, Assoc 8, LineSize 64 ---* Instruction Cache 3, Niveau 1, 32 Ko, Assoc 8, LineSize 64 --** Unified Cache 1, Niveau 2, 4 Mo, Assoc 16, LineSize 64
Vérifions expérimentalement ces informations. Pour ce faire, parcourons notre tableau en incrémentant toutes les 16 valeurs - un moyen simple de modifier les données de chaque ligne du cache. Quand nous arrivons à la fin, nous revenons au début. Vérifions les différentes tailles de tableau, nous devrions voir une baisse des performances lorsque le tableau ne rentre plus dans les caches des différents niveaux.

Le code est comme ceci :

int pas = 64 * 1024 * 1024 ; // nombre d'itérations
int lengthMod = arr.Length - 1 ; // taille du tableau -- puissance de deux

pour (int je = 0; je< steps; i++)
{
// x & lengthMod = x % arr.Length car puissances de deux
arr[(i * 16) & lengthMod]++ ;
}


Résultats de test:

Sur ma machine, les baisses de performances après 32 Ko et 4 Mo sont perceptibles - ce sont les tailles des caches L1 et L2.

Exemple 4 : Parallélisme d'instructions

Voyons maintenant autre chose. Selon vous, laquelle des deux boucles sera la plus rapide ?
int pas = 256 * 1024 * 1024 ;
entier un = nouvel entier ;

// d'abord
pour (int je = 0; je< steps; i++) { a++; a++; }

// deuxième
pour (int je = 0; je< steps; i++) { a++; a++; }


Il s'avère que la deuxième boucle tourne presque deux fois plus vite, du moins sur toutes les machines que j'ai testées. Pourquoi? Parce que les commandes à l'intérieur des boucles ont des dépendances de données différentes. Les commandes du premier ont la chaîne de dépendances suivante :

Au deuxième cycle, les dépendances sont :

Les parties fonctionnelles des processeurs modernes sont capables d'effectuer un certain nombre de certaines opérations simultanément, généralement pas un très grand nombre. Par exemple, un accès parallèle aux données du cache L1 à deux adresses est possible, ainsi que l'exécution simultanée de deux instructions arithmétiques simples. Dans le premier cycle, le processeur ne peut pas utiliser ces fonctionnalités, mais il le peut dans le second.

Exemple 5 : Associativité du cache

L'une des questions clés auxquelles il faut répondre lors de la conception d'un cache est de savoir si les données d'une certaine zone de mémoire peuvent être stockées dans n'importe quelle cellule du cache ou seulement dans certaines d'entre elles. Trois solutions possibles :
  1. Cache de mappage direct, les données de chaque ligne de cache dans la RAM sont stockées dans une seule cellule de cache prédéfinie. La manière la plus simple de calculer le mappage est : row_in_index % number_of_cache_cells. Deux lignes mappées à la même cellule ne peuvent pas être mises en cache en même temps.
  2. Cache partiellement associatif à N entrées, chaque ligne peut être stockée dans N emplacements de cache différents. Par exemple, dans un cache à 16 voies, une ligne peut être stockée dans l'une des 16 cellules qui composent le groupe. Habituellement, les chaînes avec des bits inférieurs égaux d'indices partagent un groupe.
  3. Cache entièrement associatif, n'importe quelle chaîne peut être stockée dans n'importe quel emplacement de cache. La solution est équivalente à une table de hachage dans son comportement.
Les caches à mappage direct sont sujets aux conflits, par exemple, lorsque deux lignes se disputent une cellule, se poussant alternativement hors du cache, l'efficacité est très faible. En revanche, les caches entièrement associatifs, bien que sans cet inconvénient, sont très complexes et coûteux à mettre en œuvre. Les caches partiellement associatifs sont un compromis typique entre la complexité de la mise en œuvre et l'efficacité.

Par exemple, sur ma machine, le cache L2 de 4 Mo est un cache semi-associatif à 16 voies. Toute la RAM est divisée en ensembles de lignes par les bits les moins significatifs de leurs indices, les lignes de chaque ensemble se disputent un groupe de 16 cellules de cache L2.

Puisque le cache L2 a 65 536 cellules (4 * 2 20/64) et que chaque groupe se compose de 16 cellules, nous avons un total de 4 096 groupes. Ainsi, les 12 bits inférieurs de l'indice de ligne déterminent à quel groupe appartient cette ligne (2 12 = 4 096). En conséquence, les lignes avec des adresses divisibles par 262 144 (4 096 * 64) partagent le même groupe de 16 cellules et se disputent une place dans celui-ci.

Pour que les effets d'associativité fonctionnent, il faut accéder en permanence à un grand nombre de lignes d'un même groupe, par exemple en utilisant le code suivant :

public statique long UpdateEveryKthByte (octet arr, int K)
{
const int rep = 1024 * 1024 ; // nombre d'itérations

Chronomètre sw = Chronomètre.StartNew();

entier p = 0 ;
pour (int je = 0; je< rep; i++)
{
arr[p]++ ;

P+=K; si (p >= arr.Longueur) p = 0 ;
}

Sw.Stop();
return sw.ElapsedMilliseconds ;
}


La méthode incrémente chaque K-ième élément du tableau. Quand nous arrivons à la fin, nous recommençons. Après un assez grand nombre d'itérations (2 20), on s'arrête. J'ai effectué des exécutions pour différentes tailles de tableaux et valeurs de pas K. Résultats (bleu - temps d'exécution long, blanc - petit):

Les zones bleues correspondent aux cas où, avec un changement constant de données, le cache n'est pas en mesure d'accueillir toutes les données requises en même temps. La couleur bleu vif indique un temps de fonctionnement d'environ 80 ms, presque blanc - 10 ms.

Traitons les zones bleues :

  1. Pourquoi des lignes verticales apparaissent-elles ? Les lignes verticales correspondent aux valeurs de pas auxquelles trop de lignes (plus de 16) d'un groupe sont accédées. Pour ces valeurs, le cache 16 voies de ma machine ne peut pas contenir toutes les données dont il a besoin.

    Certaines des mauvaises valeurs de foulée sont des puissances de deux : 256 et 512. Par exemple, considérez la foulée 512 et un tableau de 8 Mo. A cette étape, il y a 32 sections dans le tableau (8 * 2 20 / 262 144), qui se font concurrence pour les cellules dans 512 groupes de cache (262 144 / 512). Il y a 32 parcelles et il n'y a que 16 cellules dans la cache pour chaque groupe, il n'y a donc pas assez d'espace pour tout le monde.

    Les autres valeurs de foulée qui ne sont pas des puissances de 2 sont tout simplement malchanceuses, provoquant de nombreux accès aux mêmes groupes de caches, et provoquant également l'apparition de lignes bleues verticales sur la figure. À ce stade, les amateurs de théorie des nombres sont invités à réfléchir.

  2. Pourquoi les lignes verticales se coupent-elles à une limite de 4 Mo ? Avec une taille de tableau de 4 Mo ou moins, un cache à 16 voies se comporte de la même manière qu'un cache entièrement associatif, c'est-à-dire qu'il peut contenir toutes les données du tableau sans conflits. Il n'y a pas plus de 16 zones qui se battent pour un groupe de cache (262 144 * 16 = 4 * 2 20 = 4 Mo).
  3. Pourquoi y a-t-il un gros triangle bleu en haut à gauche ? Parce qu'avec un petit pas et un grand tableau, le cache n'est pas capable de contenir toutes les données nécessaires. Le degré d'associativité du cache joue ici un rôle secondaire, la limitation est liée à la taille du cache L2.

    Par exemple, avec une taille de tableau de 16 Mo et une foulée de 128, nous accédons tous les 128 octets, mettant ainsi à jour toutes les autres lignes du cache de tableau. Il faut 8 Mo pour stocker une ligne sur deux dans le cache, mais ma machine ne dispose que de 4 Mo.

    Même si le cache était entièrement associatif, cela ne permettrait pas d'y stocker 8 Mo de données. Notez que dans l'exemple ci-dessus avec une foulée de 512 et une taille de tableau de 8 Mo, nous n'avons besoin que de 1 Mo de cache pour stocker toutes les données dont nous avons besoin, mais cela n'est pas possible en raison d'une associativité de cache insuffisante.

  4. Pourquoi le côté gauche du triangle gagne-t-il progressivement en intensité ? L'intensité maximale tombe sur la valeur de pas de 64 octets, qui est égale à la taille de la ligne de cache. Comme nous l'avons vu dans les premier et deuxième exemples, l'accès séquentiel à la même chaîne ne coûte presque rien. Disons qu'avec un pas de 16 octets, on a quatre accès mémoire pour le prix d'un.

    Étant donné que le nombre d'itérations est le même dans notre test pour n'importe quelle valeur de pas, le pas le moins cher entraîne moins de temps d'exécution.

Les effets détectés sont également conservés aux grandes valeurs des paramètres :

L'associativité du cache est une chose intéressante qui peut apparaître sous certaines conditions. Contrairement aux autres problèmes abordés dans cet article, ce n'est pas si grave. Certes, ce n'est pas quelque chose qui nécessite une attention constante lors de l'écriture de programmes.

Exemple 6 : faux partage de cache

Sur les machines multicœurs, vous pouvez rencontrer un autre problème - la correspondance du cache. Les cœurs de processeur ont des caches partiellement ou complètement séparés. Sur ma machine, les caches L1 sont séparés (comme d'habitude) et il y a deux caches L2 partagés par chaque paire de cœurs. Les détails peuvent varier, mais en général, les processeurs multicœurs modernes ont des caches hiérarchiques à plusieurs niveaux. De plus, les caches les plus rapides, mais aussi les plus petits, appartiennent à des cœurs individuels.

Lorsque l'un des cœurs modifie la valeur dans son cache, les autres cœurs ne peuvent plus utiliser l'ancienne valeur. La valeur dans les caches des autres cœurs doit être mise à jour. De plus, il devrait être mis à jour toute la ligne de cache car les caches fonctionnent sur des données au niveau des lignes.

Démontrons ce problème avec le code suivant :

private static int s_counter = new int ;

privé void UpdateCounter(int position)
{
pour (int j = 0; j< 100000000; j++)
{
s_compteur = s_compteur + 3 ;
}
}


Si sur ma machine à quatre cœurs j'appelle cette méthode avec les paramètres 0, 1, 2, 3 simultanément à partir de quatre threads, alors le temps d'exécution sera 4,3 secondes. Mais si j'appelle la méthode avec les paramètres 16, 32, 48, 64, alors le temps d'exécution ne sera que 0,28 seconde.

Pourquoi? Dans le premier cas, les quatre valeurs traitées par les threads à un moment donné sont très susceptibles de se retrouver dans la même ligne de cache. Chaque fois qu'un cœur incrémente une valeur, il marque les emplacements de cache contenant cette valeur dans d'autres cœurs comme non valides. Après cette opération, tous les autres cœurs devront à nouveau mettre en cache la ligne. Cela rend le mécanisme de mise en cache inopérant, ce qui réduit les performances.

Exemple 7 : complexité matérielle

Même maintenant, alors que les principes de fonctionnement du cache ne sont pas un secret pour vous, le matériel vous surprendra toujours. Les processeurs diffèrent les uns des autres par les méthodes d'optimisation, l'heuristique et d'autres subtilités de mise en œuvre.

Le cache L1 de certains processeurs peut accéder à deux cellules en parallèle si elles appartiennent à des groupes différents, mais si elles appartiennent au même groupe, uniquement de manière séquentielle. Autant que je sache, certains peuvent même accéder à différents quartiers de la même cellule en parallèle.

Les processeurs peuvent vous surprendre avec des optimisations intelligentes. Par exemple, le code de l'exemple précédent sur le faux partage de cache ne fonctionne pas comme prévu sur mon ordinateur personnel - dans les cas les plus simples, le processeur peut optimiser les performances et réduire les effets négatifs. Si le code est légèrement modifié, tout se met en place.

Voici un autre exemple d'étranges caprices de fer :

entier statique privé A, B, C, D, E, F, G ;

vide statique privé Bizarrerie()
{
pour (int je = 0; je< 200000000; i++)
{
<какой-то код>
}
}


Si à la place<какой-то код>remplacer trois options différentes, vous pouvez obtenir les résultats suivants :

L'incrémentation des champs A, B, C, D prend plus de temps que l'incrémentation des champs A, C, E, G. Plus étrange encore, l'incrémentation des champs A et C prend plus de temps que les champs A, C Et E, G. Je ne sais pas exactement quelles en sont les raisons, mais peut-être sont-elles associées à des banques de mémoire ( oui, oui, avec les banques d'économie de mémoire habituelles de trois litres, et pas ce que vous pensiez). Si vous avez des idées à ce sujet, n'hésitez pas à commenter.

Sur ma machine, ce qui précède n'est pas observé, cependant, il y a parfois des résultats anormalement mauvais - très probablement, le planificateur de tâches fait ses propres "corrections".

La leçon à tirer de cet exemple est qu'il est très difficile de prédire entièrement le comportement du matériel. Oui, Peut prévoir beaucoup, mais vous devez constamment confirmer vos prédictions par des mesures et des tests.

Conclusion

J'espère que tout ce qui a été discuté vous a aidé à comprendre la structure des caches de processeur. Vous pouvez maintenant mettre en pratique ce que vous avez appris pour optimiser votre code.
Vous avez aimé l'article ? Partager avec des amis: