Qu'est-ce que Barrière mémoire ?

Instruction garantissant que les opérations mémoire antérieures à la barrière deviennent visibles aux autres cœurs avant les opérations postérieures. Aussi appelée fence, par exemple fence en RISC-V.

Nom japonais: メモリバリア

« Barrière mémoire » apparaît dans 2 questions d'entraînement réparties sur 1 thèmes, dont Multicœur et synchronisation.

Domaine: Multicœur et synchronisation

Ce que garantit une barrière mémoire

Une barrière mémoire, aussi appelée fence, est une instruction qui sépare les opérations mémoire d'un thread entre celles qui la précèdent et celles qui la suivent, et garantit que les premières deviennent visibles aux autres cœurs avant que les suivantes ne soient effectuées. Sans elle, un processeur peut laisser des chargements et des écritures vers des adresses différentes s'achever dans le désordre, par exemple en gardant les écritures dans un tampon d'écriture pendant que les chargements suivants progressent. Les résultats vus par le thread émetteur lui-même ne changent jamais ; les barrières n'importent donc que lorsque des données sont partagées entre cœurs ou avec des périphériques comme les moteurs DMA.

L'exemple du tampon d'écriture

Supposons que le cœur 0 exécute x = 1 puis r1 = y, tandis que le cœur 1 exécute y = 1 puis r2 = x, avec x et y valant 0 au départ. Sous cohérence séquentielle, une écriture a lieu en premier, donc au moins un chargement doit renvoyer 1. Sur les processeurs réels, y compris x86, chaque écriture peut attendre dans le tampon d'écriture de son cœur pendant que le chargement suivant lit l'ancienne valeur dans le cache ; r1 et r2 peuvent donc valoir 0 tous les deux. Placer une barrière complète entre l'écriture et le chargement dans chaque thread force l'écriture à devenir visible avant l'exécution du chargement, ce qui exclut ce résultat.

Les instructions de barrière des ISA réelles

RISC-V fournit fence, dont les opérandes indiquent quels accès antérieurs doivent être ordonnés avant quels accès ultérieurs : fence rw, rw ordonne ainsi toutes les lectures et écritures ; ses instructions atomiques et load-reserved/store-conditional portent des bits acquire et release. Arm dispose de dmb (data memory barrier) pour l'ordonnancement, de dsb lorsqu'il faut attendre l'achèvement, et d'instructions load-acquire et store-release. Sur x86, dont l'ordre total des écritures (TSO) préserve déjà la plupart des ordres, mfence ou une instruction verrouillée n'est nécessaire que pour ordonner une écriture avant un chargement ultérieur. Les barrières ne sont pas gratuites, car elles peuvent bloquer le cœur jusqu'à ce que les écritures en attente soient vidées.

Barrières dans les verrous et les compilateurs

La plupart des programmeurs n'écrivent jamais directement de barrière. L'acquisition d'un verrou inclut une sémantique acquire, de sorte que les accès ultérieurs ne peuvent pas remonter avant elle, et la libération inclut une sémantique release, de sorte que les écritures antérieures sont visibles avant que le verrou ne soit libéré ; c'est pourquoi les données protégées par un verrou passent correctement d'un thread à l'autre. Les langages exposent les mêmes idées via les atomiques avec ordres mémoire, comme en C11 et C++11. Une barrière de compilation est autre chose : elle empêche le compilateur de réordonner les accès de part et d'autre d'un point, mais n'émet aucune instruction et ne contraint donc pas le matériel.

S'entraîner : questions sur Barrière mémoire

Quel est le rôle d’une instruction de barrière mémoire (fence) ?

  1. AGarantir que les opérations mémoire antérieures à la barrière sont vues des autres cœurs avant celles qui la suivent
  2. BCloisonner physiquement la mémoire et en interdire l’accès
  3. CArrêter l’exécution du programme jusqu’à ce que tous les threads soient arrivés
Afficher la réponse et l'explication

Réponse : A. Garantir que les opérations mémoire antérieures à la barrière sont vues des autres cœurs avant celles qui la suivent

Le CPU pouvant réordonner les opérations mémoire, échanger des données avec d’autres cœurs dans un ordre défini exige une instruction qui empêche ce réordonnancement. La barrière mémoire fait terminer (rendre visibles aux autres cœurs) toutes les lectures et écritures précédentes avant d’effectuer les suivantes. La prise et la libération d’un verrou incluent aussi un effet de barrière, ce qui assure la transmission correcte des variables protégées par le verrou.

Questions fréquentes

Quelle est la différence entre une barrière mémoire et une fence ?

C'est le même concept sous deux noms. Les deux désignent une instruction qui maintient les opérations mémoire qui la précèdent ordonnées avant celles qui la suivent, du point de vue des autres cœurs ; RISC-V appelle son instruction fence, et Arm appelle les siennes des barrières.

x86 a-t-il besoin de barrières mémoire ?

Moins souvent que les architectures faiblement ordonnées, car l'ordre total des écritures de x86 maintient la plupart des chargements et écritures dans l'ordre du programme. Une barrière comme mfence, ou une instruction verrouillée, reste nécessaire lorsqu'une écriture doit devenir visible avant un chargement ultérieur vers une adresse différente.

Quelle est la différence entre une barrière de compilation et une barrière mémoire ?

Une barrière de compilation empêche seulement le compilateur de déplacer des accès mémoire de part et d'autre et ne génère aucune instruction machine. Une barrière mémoire est une instruction matérielle qui contraint l'ordre dans lequel le processeur rend les accès visibles aux autres cœurs.

« Barrière mémoire » dans les explications

Questions mentionnant « Barrière mémoire » (2)

  1. Quel est le rôle d’une instruction de barrière mémoire (fence) ?
  2. Les deux threads ci-dessus s’exécutent simultanément sur des cœurs différents (sans réordonnancement par le compilateur). Quel résultat est impossible en cohérence séquentielle mais possible sur un CPU réel comme x86 ?

Termes associés

Cohérence séquentielle Acquisition-libération (acquire-release) Compare-and-swap Course aux données (data race) Espionnage de bus (snooping) Faux partage (false sharing) Instruction atomique Interblocage (deadlock) LR/SC Mémoire transactionnelle

Retour au glossaire