Aller au contenu principal

Architecture & systèmes · L1 · Section 2/6

Mémoire et processeur

Progression

Points d’expérience : XPSérie de jours consécutifs : · —Progression du module : — / —compris

#Mémoire et processeur

La hiérarchie mémoire est l'élément essentiel de l'architecture des ordinateurs modernes: elle nourrit le processeur en données et instructions malgré la lenteur relative de la mémoire principale. Cette architecture en couches va des registres ultrarapides jusqu'à la RAM, en passant par plusieurs niveaux de cache (L1, L2, L3). Comprendre cette hiérarchie, le rôle du TLB dans la traduction d'adresses, la cohérence de cache entre cœurs et les techniques d'optimisation de la localité permet d'écrire du code nettement plus performant, à algorithme égal.

#Prérequis et objectifs

Prérequis: tableaux et boucles en Python, page « Architecture de Von Neumann » (cycle d'instruction, registres PC et ACC).

Objectifs d'apprentissage:

  • décrire la hiérarchie mémoire (registres, L1, L2, L3, RAM) et chiffrer l'impact d'un cache-miss sur les performances;
  • expliquer le rôle du TLB dans l'adressage virtuel, ainsi que les notions de pages, fautes mineures et majeures;
  • comprendre la cohérence de cache (protocole MESI) et le phénomène de false sharing sur architectures multi-cœurs;
  • appliquer des principes de localité et mesurer leur effet avec une expérience reproductible.

#Hiérarchie mémoire

La hiérarchie mémoire équilibre vitesse et capacité: les registres du processeur offrent un accès quasi instantané, puis viennent les caches L1, L2 et L3, de plus en plus grands mais un peu plus lents, la RAM, et finalement le disque. Le matériel exploite la localité temporelle (une donnée accédée sera probablement réaccédée) et spatiale (ses voisines le seront aussi) en chargeant les données par lignes de cache complètes, typiquement 64 octets.

Conséquence directe pour le code: lire un tableau dans l'ordre mobilise une ligne de cache pour plusieurs éléments utiles, tandis qu'un grand pas gaspille la plupart des octets chargés. Les stratégies d'écriture, write-back (différée) ou write-through (immédiate), influencent aussi les performances. Optimiser un parcours revient à respecter cette localité pour maximiser les hits dans les caches rapides.

#Une mémoire, matériellement

Une mémoire est une unité fonctionnelle qui reçoit, conserve et restitue des informations. Trois bus la relient au reste du système :

  • le bus d'adresses, codé sur mm bits : il désigne la case à atteindre, donc la mémoire contient 2m2^m mots ;
  • le bus de données, codé sur nn bits : il porte l'information échangée, donc il fixe le format des mots manipulés ;
  • le bus de contrôle : CS (chip select) active la mémoire, R/W choisit le sens du transfert.

Deux conséquences pratiques. D'abord, la capacité s'exprime toujours par le couple (nombre de mots × largeur du mot) : une mémoire « 4K × 16 » contient 4096 mots de 16 bits, ce qui demande 12 lignes d'adresses et 16 lignes de données. Ensuite, une case non écrite contient une valeur par défaut, pas zéro : lire avant d'écrire donne un résultat arbitraire, ce qui explique une bonne part des bogues de « variable non initialisée ».

Le schéma interne est étonnamment simple et relie directement ce chapitre à l'électronique numérique : une cellule mémoire est une bascule D, les nn cellules d'un mot partagent la même horloge, et l'accès à une case est réalisé par un démultiplexeur qui active la ligne d'horloge de la bonne cellule. Un décodeur d'adresses et un tableau de bascules : c'est tout. On retrouve là exactement les briques qui composent le processeur.

#Classification des mémoires

Les mémoires se classent d'abord selon leur volatilité — l'aptitude à conserver l'information hors tension.

Les mémoires mortes (non volatiles) gardent leur contenu sans alimentation. La famille s'est étendue par étapes : ROM (masquée à la fabrication), PROM (programmable une fois par l'utilisateur), EPROM (effaçable aux ultraviolets), EEPROM (effaçable électriquement, octet par octet) et Flash (effaçable électriquement, par blocs — la mémoire de programme des microcontrôleurs et des SSD).

Les mémoires vives (volatiles) perdent leur contenu à la coupure, et se divisent en deux technologies :

  • la SRAM (statique), à base de bascules, rapide et chère : c'est la technologie des caches ;
  • la DRAM (dynamique), qui stocke chaque bit dans un condensateur à rafraîchir périodiquement : c'est la mémoire principale. Elle se décline en générations asynchrones — FPM (Fast Page Mode, jusqu'en 1990), EDO (Extended Data Out, de 1995 à 1997), BEDO — puis synchrones : SDRAM, DDR-SDRAM, RDRAM.

Les mémoires externes ou de masse ne sont pas adressables octet par octet : disques durs, disques optiques (CD-ROM, CD-R, CD-RW, DVD), bandes magnétiques (DAT, DLT). C'est le dernier niveau de la hiérarchie, celui dont la latence se compte en millisecondes.

Cette classification explique la hiérarchie décrite plus haut : plus une mémoire est rapide, plus elle est chère par bit et plus elle est petite. On les empile donc, du registre au disque.

#La carte mémoire d'un microcontrôleur réel

La théorie devient concrète dès qu'on ouvre la documentation d'un microcontrôleur. Sur l'ATmega2560 utilisé en TP, l'espace d'adressage des données se lit d'un seul tableau :

PlageContenu
$0000$001F32 registres de travail (r0 à r31)
$0020$005Fregistres des ressources internes, accessibles directement par IN/OUT
$0060$01FFregistres étendus d'entrée/sortie
$0200$1FFFmémoire de données SRAM

Ce plan mémoire est un cas d'école d'entrées/sorties mappées en mémoire : les registres de configuration des périphériques (PORTB, DDRB, ADCSRA…) occupent des adresses comme les autres, et on les lit ou les écrit avec les mêmes instructions que la mémoire. Programmer un microcontrôleur, c'est donc écrire dans des adresses bien choisies : un PORTB n'est pas une variable, c'est un périphérique.

Deux repères complètent le tableau. La pile vit dans la SRAM ; le pointeur de pile SP est en réalité constitué de deux registres, SPH et SPL, qu'il faut initialiser à la dernière adresse de la SRAM avant tout appel de sous-programme. Et les registres de travail r0 à r31 ne sont pas un espace séparé : ce sont les 32 premiers octets de l'espace d'adressage, ce qui explique qu'on puisse les traiter comme de la mémoire.

#Exécution

Le pipeline d'instructions, la prédiction de branchement et l'exécution hors-ordre maintiennent le processeur constamment occupé. En revanche, un cache-miss profond ou une mauvaise prédiction de branchement font chuter l'IPC (instructions par cycle) et augmentent la latence effective. Sur des parcours mémoire irréguliers, le coût des ratés de TLB (Translation Lookaside Buffer) s'ajoute à celui des ratés de cache et aggrave la pénalité.

Lien avec l'ISA: au niveau du jeu d'instructions, rien de tout cela n'est visible. C'est le contrat même du ISA: même programme, même sémantique, seules les latences changent. Le matériel cache prédiction de branchement, réordonnancement et hiérarchie mémoire derrière des instructions ordinaires, et c'est pourquoi un même code binaire peut accélérer d'une génération de CPU à la suivante.

#Expérience: localité de cache

L'expérience ci-dessous compare un parcours séquentiel et un parcours par pas de 32. Elle est observable: chaque exécution affiche deux temps mesurés, et le rapport entre les deux est la donnée à retenir.

Chargement de l’éditeur...

Exercice observable: ajoutez une mesure avec pas=64 puis pas=128 (même N), et reportez le temps par élément visité, soit temps / (N/pas). Vérification attendue: le temps par élément visité augmente avec le pas, car une ligne de cache de 64 octets ne sert alors plus qu'à un ou deux éléments. Si votre mesure ne montre pas cette tendance, répétez-la et prenez la médiane: sur des temps aussi courts, le bruit de mesure est significatif.

#Simulateur: hiérarchie et miss ratio

Hiérarchie mémoire — simulateur

Ajustez la taille d’ensemble de travail, le pas d’accès et le nombre de threads pour estimer la répartition des hits dans la hiérarchie cache et l’impact sur la latence moyenne.

Ensemble de travail

256 KB

Volume de données actives que le code parcourt en boucle.

Stride / pas d’accès

×8

Distance entre deux accès consécutifs (1 → séquentiel).

Threads concurrents

1

Plus de threads ⇒ compétition sur les caches partagés.

Prélecture matérielle

La prélecture est bénéfique pour les accès réguliers; sur accès aléatoires, elle gaspille de la bande passante.

Répartition des hits

L16.8 %
L224.4 %
L321.6 %
Miss DRAM47.2 %

Latence moyenne estimée

43.9 ns

Combinaison pondérée hits caches + accès DRAM

Bande passante effective

120.0 Go/s

Hypothèse: ligne de cache 64 B

La majorité des accès (47%) finit en DRAM. Réduisez l’ensemble chaud (actuellement 256 KB) ou améliorez la localité (stride 8).

Profils d’accès

  • Localité spatiale : stride 1 exploite les lignes de cache; un stride élevé saute des blocs entiers.
  • Localité temporelle : petits working sets revisitent les mêmes lignes → hits L1/L2.
  • Contention : plusieurs threads partagent L3/DRAM → miss ratio augmente.
  • Prélecture : utile si l’accès est régulier; nuisible sinon.

Cette simulation reste indicative mais permet de raisonner: réduisez l’ensemble de travail « chaud », regroupez les données et préférez des parcours séquentiels pour que les caches fassent leur travail.

#Conseils de performance

Pour exploiter efficacement la hiérarchie mémoire, privilégiez les parcours séquentiels et les structures de données contiguës qui bénéficient naturellement de la localité spatiale. Groupez les champs fréquemment accédés ensemble dans vos structures et limitez l'empreinte mémoire « chaude » (l'ensemble des données activement utilisées) pour qu'elle tienne dans les caches. Les prefetchs (chargements anticipés) explicites n'apportent un bénéfice que si le motif d'accès est prévisible et connu suffisamment en avance; sinon ils gaspillent la bande passante mémoire. Sur les architectures multi-cœurs, évitez le false sharing en séparant les données écrites concurremment par différents threads.

#Mémoire virtuelle et TLB (aperçu)

L'adressage virtuel découpe la mémoire en pages (typiquement 4 Ko) et le TLB met en cache les traductions d'adresses virtuelles vers physiques. Un raté de TLB est coûteux car il nécessite une marche dans les tables de pages, et il s'ajoute aux éventuels ratés de cache. Les accès mémoire irréguliers et les ensembles de travail trop grands pénalisent fortement les performances en multipliant ces ratés. Les structures contiguës, une bonne réutilisation spatiale et temporelle, et parfois les huge pages (pages de grande taille) améliorent nettement la situation. Sur les systèmes SMP, les invalidations de TLB inter-cœurs (« TLB shootdowns ») expliquent certaines pauses observées lors de changements de mappings.

#Quiz

Dans la hiérarchie mémoire, quel niveau est généralement le plus lent parmi ces choix ?
Dans la hiérarchie mémoire, quel niveau est généralement le plus lent parmi ces choix ?
Un tableau est parcouru avec un pas de 64. Pourquoi le temps par élément visité augmente-t-il ?
Un tableau est parcouru avec un pas de 64. Pourquoi le temps par élément visité augmente-t-il ?