Hiérarchie de mémoire

5.5 Hiérarchie de mémoire

Objectifs d'apprentissage

À la fin de cette section, vous serez capable de :

  • Discuter de divers outils de mémoire et de stockage
  • Différencier les différents types de technologies de stockage
  • Expliquer comment la localité est utilisée pour optimiser les programmes

Pour que le processeur puisse faire son travail, qui est d'effectuer les calculs, il doit être alimenté en instructions et en données. Cela signifie que la performance globale dépend à la fois de la vitesse de calcul et de la vitesse à laquelle les données et les instructions sont reçues. Peu importe la rapidité de votre processeur, vous n'obtiendrez pas de bonnes performances si le flux d'instructions et de données n'est pas suffisamment rapide. Tout fonctionnait bien aux débuts de l'informatique, des années 1940 jusqu'au début des années 1990, puis l'informatique a rencontré un obstacle — un mur de la mémoire.

Les chercheurs de l'industrie et du monde universitaire ont réalisé de grands progrès en matière de performances des processeurs en innovant des façons d'utiliser les transistors que leur fournissait la loi de Moore. Ils ont utilisé ces transistors, dont le nombre doublait par puce en moyenne tous les 18 mois, pour ajouter plus de fonctionnalités au processeur, ce qui a conduit à de meilleures performances du processeur. Cependant, la même chose n'a pas été faite avec la mémoire, ce qui a entraîné un décalage de vitesse entre la mémoire et le processeur. L'écart a commencé petit, puis s'est élargi jusqu'à devenir un goulot d'étranglement de la performance. La Figure 5.19 montre la tendance de l'écart de performance processeur-mémoire.

Un graphique linéaire illustrant l'élargissement de l'écart de performance entre la vitesse du processeur et la vitesse de la mémoire au fil du temps.
Figure 5.19 L'écart entre la vitesse du processeur et la vitesse de la mémoire augmente. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Dans cette section, nous explorons la technologie de mémoire. Nous discuterons des différentes technologies de construction de la mémoire, expliquerons ce que nous entendons par hiérarchie de mémoire et verrons ce que les chercheurs ont fait pour gérer l'écart processeur-mémoire.

Mémoire et stockage

Quelle est notre liste de souhaits pour la mémoire parfaite ? Probablement la vitesse — nous voulons une mémoire rapide. Mais attention — la vitesse de la mémoire est différente de la capacité de la mémoire. La capacité de la mémoire a augmenté au fil des ans à un rythme beaucoup plus rapide que la vitesse de la mémoire. Nous voulons également une capacité infinie et une persistance ; c'est-à-dire que lorsque l'alimentation est coupée, nous voulons que la mémoire conserve son contenu.

Ensuite, nous voulons pouvoir stocker une grande quantité de données dans une zone aussi petite que possible grâce à la densité, ce qui est particulièrement utile pour les appareils portables tels que votre montre intelligente ou votre smartphone. Et qu'en est-il du coût ? Si la mémoire est très chère, l'ensemble du système informatique (computer system) est très cher, ce qui signifie que personne ne l'achète ; les concepteurs doivent alors intégrer une mémoire de plus petite taille dans le système informatique pour maintenir le prix bas. Mais une mémoire plus petite signifie moins de fonctionnalités pour le système informatique et des performances globales inférieures.

La réalité est beaucoup moins idéale. Il n'existe pas de technologie unique qui excelle dans tous ces aspects. Certaines technologies sont rapides mais plus chères, volatiles et moins denses, tandis que d'autres sont bon marché et persistantes mais relativement plus lentes que d'autres technologies. Si nous ne choisissons qu'une seule technologie, nous nous retrouvons avec un système non fonctionnel. Par exemple, si nous choisissons la technologie rapide et volatile mais coûteuse, le système informatique résultant, qui est probablement très cher, doit être alimenté indéfiniment pour conserver les données. Si nous choisissons la technologie persistante et bon marché mais lente, le système peut être inutilisable en raison de sa lenteur.

Le mot stockage est généralement utilisé avec la persistance (stockage à long terme) tandis que le mot mémoire est utilisé pour la volatilité (stockage à court terme), même si cette distinction pourrait s'estomper dans les futures technologies. Comment pouvons-nous obtenir le meilleur des deux mondes ?

Concepts en pratique

Plus vous en savez

Connaître le matériel est toujours bénéfique pour un programmeur logiciel. Le cache, par exemple, est transparent pour le programmeur ; cependant, si le programmeur connaît le cache et son fonctionnement, il peut écrire du code qui présente de la localité (locality) et obtient de bonnes performances.

Si vous écrivez un programme qui accède à une matrice, et que vous savez comment la matrice est stockée en mémoire, vous pouvez ajuster votre code pour accéder à la matrice ligne par ligne (ou colonne par colonne) afin d'augmenter la localité, ce qui rendra votre programme beaucoup plus rapide.

La hiérarchie de mémoire

Nous avons cinq éléments sur notre liste de souhaits pour une mémoire idéale et, puisqu'il n'existe pas de technologie unique qui excelle dans les cinq, nous devons combiner plusieurs technologies pour nous rapprocher du système de mémoire idéal. Ce système de mémoire idéal doit être rapide, dense, persistant, de grande capacité et peu coûteux. Les technologies que nous utilisons actuellement ont les caractéristiques suivantes :

  • Technologie 1 : très rapide mais chère, moins dense et volatile
  • Technologie 2 : plus rapide et plus dense, mais volatile et modérément chère
  • Technologie 3 : persistante et peu coûteuse mais lente
  • Technologie 4 : persistante et très peu coûteuse mais très lente

Nous devons tirer le meilleur parti de toutes ces technologies, et la meilleure façon de les combiner doit garantir que nous avons une capacité plus élevée avec les technologies 3 et 4, mais que les technologies 1 et 2 sont plus proches du processeur afin qu'elles puissent répondre plus rapidement au processeur. La manière évidente de procéder est d'utiliser un agencement de stockage disponible sur un système informatique sous la forme d'un triangle, comme le montre la Figure 5.20. Nous appelons cette conception hiérarchie de mémoire (memory hierarchy).

Une image montrant la hiérarchie de mémoire.
Figure 5.20 La hiérarchie de mémoire tire le meilleur parti de toutes les technologies. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Le Tableau 5.3 donne les noms des technologies que nous discuterons plus tard dans cette section. Le processeur est connecté au premier cache à l'aide d'un ensemble de fils appelé le bus (bus). Si le processeur ne trouve pas ce qu'il cherche, il passe au niveau suivant, et ainsi de suite.

  Nom de la technologie Cas d'utilisation
Technologie 1 Mémoire vive statique (SRAM) Mémoire cache
  • Volatile
  • Très rapide
  • Coûteuse
  • Petite taille (de quelques Ko à quelques Mo)
Technologie 2 Mémoire vive dynamique (DRAM) Mémoire principale
  • Volatile
  • Rapide
  • Moins coûteuse
  • Taille moyenne (1 Go à 128 Go)
Technologie 3 Disque électronique (SSD) Stockage
  • Persistant
  • Lent
  • Bon marché
  • Grande taille (de quelques Go à quelques To)
Technologie 4 Disque dur (HDD) Stockage
  • Persistant
  • Très lent
  • Très bon marché
  • Plusieurs To de stockage
Tableau 5.3 Technologies utilisées pour le stockage dans un système informatique typique

Technologies de mémoire

La mémoire est volatile, du moins pour l'instant, la recherche explorant d'autres technologies pour les mémoires persistantes, la vitesse, le stockage et le coût. Cela couvre les technologies 1 et 2 et, par conséquent, elles sont plus proches du processeur. Les technologies 1 et 2 couvrent deux types de mémoires qui incluent toutes deux la mémoire vive (RAM) (random access memory (RAM)), qui permet au processeur d'accéder à n'importe quelle partie de la mémoire dans n'importe quel ordre. La technologie 2 est appelée DRAM, et la technologie 1 est appelée SRAM. Explorons chacune d'elles à tour de rôle.

Mémoire : DRAM

Comme vous le savez maintenant, la mémoire stocke les instructions et les données, qui sont représentées par des 1 et des 0. Un type de mémoire, la mémoire vive dynamique (DRAM) (dynamic random access memory (DRAM)), se compose d'un grand nombre de condensateurs. Un condensateur (capacitor) est un très petit composant électrique qui stocke une charge électrique. Un condensateur peut être dans l'un des deux états : soit il contient une charge, auquel cas nous disons qu'un 1 est stocké dans ce condensateur, soit il ne contient pas de charge, ce qui signifie un 0. Avec des millions de condensateurs, nous pouvons stocker un grand nombre de 1 et de 0. C'est ce que vous trouvez dans les spécifications de votre ordinateur portable ; lorsque vous dites que vous avez 32 Go de RAM, cela signifie qu'il y a environ 32 milliards d'octets en mémoire. Chaque octet se compose de 8 bits. Chaque bit nécessite un condensateur.

Les condensateurs ont cependant une caractéristique peu enviable. Lorsqu'une charge est laissée sur un condensateur pendant un certain temps, le condensateur commence à se décharger et perd sa charge. Cela signifie que nous perdons les données stockées en mémoire. Pour cette raison, des circuits sont intégrés à la DRAM (DRAM) qui, toutes les quelques millisecondes, vérifient les condensateurs et y ajoutent une charge. Nous appelons cela le cycle de rafraîchissement (refresh cycle). Cela se fait dynamiquement, d'où le nom de RAM dynamique ou DRAM.

Les condensateurs ne sont pas autonomes. Des transistors sont utilisés avec eux pour aider à organiser ces condensateurs en lignes (également appelées lignes de mots) et en colonnes (également appelées lignes de bits) pour adresser des bits spécifiques. La Figure 5.21 montre une vue simplifiée de la DRAM. La cellule, qui stocke 1 bit, est composée du condensateur et de quelques transistors.

Une image montrant une vue simplifiée d'une DRAM.
Figure 5.21 Cette vue simplifiée de la DRAM montre une banque. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Ce qui est montré dans la Figure 5.21 est appelé une banque. Plusieurs banques forment une puce. Plusieurs puces forment un rang. Une petite carte mémoire qui contient plusieurs banques de mémoire est un module de mémoire double en ligne (DIMM) (dual in-line memory module (DIMM)). Plusieurs DIMM forment un canal. Cette organisation est montrée dans la Figure 5.22. La raison de cette organisation est double. Premièrement, si nous avions un énorme tableau 2D de cellules de mémoire, ce serait trop complexe, lent et gourmand en énergie, donc le diviser en parties rend ces parties plus simples et cela signifie plus rapide et moins gourmand en énergie. Deuxièmement, s'il y a plusieurs adresses mémoire qui doivent être accédées et qu'elles tombent dans différentes banques, par exemple, la mémoire peut répondre en parallèle.

Une image montrant comment les banques de mémoire DRAM sont organisées.
Figure 5.22 Les banques de mémoire DRAM peuvent être organisées en puces, rangs, DIMM et canaux. (source : modification de « 168 pin and 184 pin DIMM memory modules » par Veeblefetzer/Wikimedia Commons, CC BY 4.0)

Vous avez dû entendre le terme machines 64 bits, n'est-ce pas ? La plupart de nos systèmes informatiques (computer systems) sont aujourd'hui en 64 bits. L'une des définitions de ce terme est que la connexion entre le processeur et la mémoire a une largeur de 64 bits ; sa mémoire peut envoyer ou recevoir des données du processeur par blocs de 64 bits.

La courbe que nous avons vue dans la Figure 5.19 montre la lente augmentation de la vitesse de la DRAM, ce qui affecte les performances du système global. Si le processeur doit aller chercher en mémoire chaque instruction et chaque donnée, les performances globales du système sont très faibles ; par conséquent, les concepteurs d'ordinateurs accélèrent les choses en utilisant une technologie plus rapide avec la DRAM. Cette technologie plus rapide, la technologie 1 de la Figure 5.20, est appelée SRAM.

Mémoire : SRAM

Plusieurs raisons expliquent la lenteur de l'obtention des données de la DRAM vers le processeur. L'une est la vitesse beaucoup plus lente de la technologie DRAM par rapport au processeur. La deuxième raison est que le fait de quitter la puce qui contient le processeur et d'aller vers le bus pour atteindre la mémoire DRAM est un processus lent. Pour surmonter cela, nous devons avoir une technologie de mémoire (memory technology) plus rapide à l'intérieur de la puce, avec le processeur.

La solution consiste à utiliser la mémoire vive statique (SRAM) (static random access memory (SRAM)) qui conserve les données dans la mémoire de l'ordinateur tant que la machine est sous tension. Cela signifie qu'elle n'a pas besoin d'un rafraîchissement comme la DRAM et qu'elle est conçue avec une technologie plus rapide que la DRAM. Cependant, les SRAM sont plus grandes en surface ; un seul bit nécessite une grande surface dans la puce car il a besoin de quatre à six transistors, ce qui est beaucoup plus grand que le condensateur (capacitor) dans la DRAM. De plus, à l'intérieur de la puce, nous n'avons pas beaucoup d'espace en raison de l'existence du processeur lui-même. Ainsi, la SRAM (SRAM) est une petite mémoire rapide à l'intérieur de la puce qui est connectée au processeur d'un côté et à la DRAM hors puce de l'autre côté, comme le montre la Figure 5.23. La DRAM est de l'ordre de 8 à 64 Go, tandis que la SRAM va de quelques Ko à quelques Mo.

Une image montrant comment une SRAM est connectée au processeur d'un côté et à la mémoire DRAM de l'autre côté.
Figure 5.23 La SRAM a été introduite pour surmonter la lenteur de la DRAM. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Une distinction importante entre la mémoire cache (cache memory) et la DRAM est que la première est transparente pour le programmeur (c'est-à-dire que son utilisation ne peut pas être gérée par le programmeur), mais pas la seconde. Votre ordinateur portable a 32 Go de RAM, ce qui est la taille de la DRAM (DRAM), mais vous ne savez peut-être pas combien de cache votre processeur possède. Cependant, si vous savez comment le cache fonctionne, vous pouvez écrire des programmes plus efficaces, comme nous l'apprenons lorsque nous parlons de localité (locality).

Dans la Figure 5.23, la SRAM est plus communément appelée mémoire cache (cache memory), qui est la mémoire permettant une récupération rapide des données. Voyons comment le cache et la mémoire DRAM fonctionnent ensemble. Désormais, chaque fois que nous disons cache, nous entendons la SRAM, et chaque fois que nous disons mémoire, nous entendons la DRAM.

Supposons que le processeur exécute un programme qui accède consécutivement au tableau A. Le processeur commence par A[0] et demande à la mémoire cache si elle contient A[0]. Initialement, le cache est vide, il ne contient donc pas les données nécessaires, ce qui est appelé un échec de cache (cache miss). Le cache récupère alors les données de la mémoire. Mais au lieu de simplement récupérer A[0], il récupère A[0], A[1], A[2], …, A[x]. Le nombre d'éléments supplémentaires que le cache apporte dépend de la conception du cache. Dans la plupart des processeurs actuellement disponibles, le cache apporte généralement 64 octets de la mémoire. Ainsi, si le tableau A est un tableau d'entiers, c'est-à-dire que chaque élément a une longueur de 4 octets, alors le cache apporte 16 éléments de la mémoire, de A[0] à A[15]. Le processeur obtient le A[0] qu'il souhaite, et les éléments supplémentaires apportés de la mémoire, qui sont dans le cache. Maintenant, si le processeur veut A[1], il le trouve immédiatement dans le cache, ce qui est appelé un succès de cache (cache hit). Cependant, si le processeur a plutôt besoin de A[17], alors nous avons un autre échec de cache et le cache accède à nouveau à la mémoire pour apporter plusieurs éléments, y compris A[17].

La SRAM et la DRAM, ou cache et mémoire, sont toutes deux volatiles — chaque fois qu'il y a une perturbation de courant ou que la machine est à court de batterie, tout ce qui se trouve dans le cache et la mémoire disparaît. Et nous ne pouvons pas construire un ordinateur complet avec uniquement de la mémoire volatile ; nous avons également besoin d'un stockage persistant.

Technologies de stockage

Le stockage existe dans les systèmes informatiques (computer system) pour garantir que les données continuent d'exister même après l'arrêt de l'ordinateur. Le stockage, présenté comme les technologies 3 et 4 dans la Figure 5.20, possède quelques caractéristiques qui diffèrent de la DRAM et de la SRAM (technologies 1 et 2). La première, et la plus importante, est qu'elles sont persistantes — elles sont non volatiles. La deuxième caractéristique est qu'elles sont plus lentes que la DRAM et la SRAM, mais ont des coûts inférieurs et des capacités plus élevées. Il est à noter que les technologies 3 et 4 n'ont pas besoin d'exister ensemble dans un système informatique ; vous pouvez avoir un ordinateur avec l'une ou l'autre, ou les deux.

Outre le stockage qui existe à l'intérieur du système informatique, il y a beaucoup de stockage dans l'infonuage. C'est-à-dire que le stockage n'existe pas dans votre ordinateur, mais vous pouvez y accéder via Internet. Ce stockage est géré par de grandes entreprises technologiques. Par exemple, nous avons Azure de Microsoft, AWS d'Amazon, Google Drive de Google, et ainsi de suite. Ces entreprises servent des millions d'utilisateurs et isolent les données des utilisateurs les unes des autres. Il existe des techniques pour permettre à chaque utilisateur d'accéder au stockage infonuagique et même aux logiciels dans l'infonuage.

Maintenant, il est temps de leur donner des noms. La technologie 3 est appelée disque électronique (SSD) et la technologie 4 est appelée disque dur (HDD). Quelles sont les différences et où s'inscrit le terme couramment rencontré de « clé USB » (flash drive) ? Commençons par la technologie la plus ancienne.

Disque dur

Les disques durs (Hard disk) ont été les principales solutions de stockage pour tous les ordinateurs dans les années 1980, 1990 et jusqu'au milieu des années 2000. Un disque dur (HDD) (hard disk drive (HDD)) stocke les données sur un plateau rotatif, a une très grande capacité et utilise un petit moteur pour faire tourner les plateaux afin d'obtenir les données. Vous pouvez facilement acheter un disque de 8 To pour un montant modeste. L'industrie a mis environ 25 ans pour passer d'un disque de 5 Mo à 1 To, et seulement deux ans pour passer de 1 To à 2 To, et, après cela, la capacité a augmenté de 60 % par an. Nous avons donc une très grande taille à un prix bas, mais aussi un disque très lent. Il est plusieurs ordres de grandeur plus lent que la mémoire DRAM. La raison est montrée dans la Figure 5.24. La principale raison pour laquelle le disque est lent est due au mouvement mécanique. Par conséquent, les concepteurs d'ordinateurs ont cherché un stockage qui ne nécessite pas de lecteurs à mouvement mécanique et qui n'a pas de pièces mobiles.

Une image d'un disque dur (HDD) complet et de ses divisions.
Figure 5.24 (a) Le disque dur (HDD) complet est (b) divisé en plateaux, et chaque plateau est divisé en pistes et secteurs. (source a : modification de « Open HDD » par Gratuit/Freeimageslive, CC BY 3.0 ; source b : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Disque électronique

Le terme état solide signifie qu'un système n'a pas de pièces mobiles et est censé être rapide. Un disque électronique (SSD) (solid-state drive (SSD)) stocke les données sur une puce et est deux à trois ordres de grandeur plus rapide qu'un HDD. Un SSD a deux parties principales : le stockage lui-même et les circuits qui accèdent au stockage. De nos jours, les SSD utilisent une technologie de stockage appelée mémoire flash (flash memory), qui est un type de stockage non volatile pouvant être effacé et reprogrammé électroniquement. C'est ce que vous utilisez dans vos clés USB, juste un peu plus rapide. La mémoire flash dans les SSD est basée sur des portes NAND (NAND). Une porte NON-ET (NAND gate) est un type de porte logique utilisée pour stocker des bits dans la mémoire flash. La mémoire flash est organisée en pages, et un groupe de pages est appelé un bloc (block).

Les circuits qui contrôlent la mémoire flash, appelés la couche de traduction (translation layer), ont une fonction importante. Ils mappent les adresses aux pages. L'un des inconvénients des cellules de stockage qui composent une page est qu'elles s'usent après 100 000 à 1 million d'accès. La couche de traduction essaie donc de modifier le mappage pour garantir que les accès sont également répartis entre les différentes cellules. C'est un processus compliqué et c'est l'une des raisons pour lesquelles les SSD sont plus chers que les HDD. La lecture séquentielle d'un SSD atteint 7000 Mo/s et l'écriture séquentielle atteint 5000 Mo/s. L'accès aléatoire à un SSD a une vitesse inférieure pour les lectures et les écritures.

Plus sur la mémoire cache

Comme vous l'avez appris, la mémoire cache est utilisée comme une mémoire rapide et petite à l'intérieur du processeur pour combler l'écart entre la vitesse du processeur et la vitesse de la mémoire. Étant donné que la latence est le taux de transfert de données, supposons que la latence d'accès à la mémoire DRAM est de M cycles et que la latence d'accès au cache est de m. Supposons également que pour un programme spécifique, la probabilité de succès de cache (cache hit) = p. Alors la latence moyenne du cache + Mémoire combinés = mp + (1 – p)(M + m) = m + (1 – p)M.

N'oubliez pas que chaque fois qu'il y a un échec de cache, nous avons déjà passé m cycles à chercher dans le cache, puis nous allons à la mémoire, ce qui prend encore M cycles. Si nous regardons l'équation m + (1 – p)M, nous voyons que pour obtenir de bonnes performances, nous devons faire une ou plusieurs des choses suivantes :

  • Avoir un cache plus rapide et un m plus faible.
  • Augmenter le taux de succès du cache et réduire p.
  • Avoir une mémoire plus rapide et un M plus faible.

Pour avoir un cache plus rapide, nous devons le rendre plus petit en capacité, mais un cache plus petit diminue le taux de succès (hit rate), qui est le nombre, généralement un pourcentage, de fois où le cache a été utilisé pour récupérer des données. Nous ne pouvons pas facilement avoir une mémoire plus rapide pour réduire M, donc la solution est d'avoir plus d'un niveau de caches. Le niveau 1 (L1), le plus proche du processeur, est de petite capacité et très rapide mais avec un taux de succès potentiellement faible. En cas d'échec de cache L1, au lieu d'aller à la mémoire hors puce, nous allons au cache L2, qui est toujours sur puce et de plus grande capacité que le L1. La plupart des processeurs ont maintenant jusqu'à trois niveaux de caches, comme le montre la Figure 5.25.

Un diagramme montrant les trois niveaux de mémoire cache dans un processeur.
Figure 5.25 La plupart des processeurs ont maintenant trois niveaux de mémoire cache. (source : Copyright Rice University, OpenStax, sous licence CC BY 4.0)

Localité

Tout au long de notre discussion sur la hiérarchie de mémoire (memory hierarchy), nous avons déterminé ce qui suit :

  • La mémoire est lue par blocs de 64 bits consécutifs, soit 8 octets.
  • Chaque fois qu'il y a un échec de cache (cache miss), le cache s'efforce d'apporter un bloc de cache, et non les quelques octets dont le processeur a besoin. La plupart des caches ont maintenant un bloc de cache de 64 octets. Ces 64 octets sont des octets consécutifs apportés du cache de niveau inférieur, qui proviennent du cache encore plus bas (c'est-à-dire de L3 à L2 à L1). Le cache L3 a apporté le bloc (block) de la mémoire.

Lorsqu'un processeur visite de manière répétée les mêmes emplacements mémoire, il présente de la localité (locality). Nous pouvons en déduire que si un programme accède aux données de manière consécutive, il obtient de meilleures performances, appelée localité (locality) spatiale (spatial). De plus, si nous réutilisons les données autant que possible, nous obtenons de meilleures performances car les données sont disponibles dans le cache, et nous pouvons augmenter les succès de cache. Nous appelons ce deuxième critère la localité temporelle (temporal locality).

Nous pouvons obtenir des performances encore meilleures si le programmeur écrit du code efficace qui utilise au mieux le matériel sous-jacent. Un programme efficace possède une caractéristique très importante appelée localité. Par exemple, si vous voulez additionner deux tableaux (c'est-à-dire A[0] + B[0], A[1] + B[1]), alors vous obtiendrez de bonnes performances si vous accédez à ces deux tableaux séquentiellement de l'élément 0 jusqu'à la fin des tableaux, ce qui est un exemple de localité spatiale. Donc, chaque fois que vous écrivez un programme, faites très attention à la façon dont vous accédez aux données.

Les instructions résident également en mémoire. Si nous avons une boucle for qui est exécutée plusieurs milliers de fois, les instructions du corps de la boucle sont réutilisées à chaque itération, ce qui est un exemple de localité temporelle.