Quelle est la signification des accès mémoire «non temporels» dans x86

123

C'est une question quelque peu basique. Dans l'assemblage x86, il existe deux instructions SSE:

MOVDQA xmmi, m128

et

MOVNTDQA xmmi, m128

Le manuel du développeur de logiciels IA-32 indique que le NT dans MOVNTDQA signifie Non-Temporel , et que sinon c'est la même chose que MOVDQA.

Ma question est: que signifie non temporel ?

Nathan Fellman
la source
6
Notez que SSE4.1 MOVNTDQA xmmi, m128est une charge NT, tandis que toutes les autres instructions NT sont stockées, à l'exception de prefetchnta. La réponse acceptée ici semble ne parler que des magasins. C'est ce que j'ai pu découvrir à propos des charges NT . TL: DR: avec un peu de chance, le CPU fait quelque chose d'utile avec le conseil NT pour minimiser la pollution du cache, mais ils ne remplacent pas la sémantique fortement ordonnée de la mémoire WB "normale", ils doivent donc utiliser le cache.
Peter Cordes
5
Mise à jour: les charges NT peuvent ne rien faire d'utile sauf sur les régions mémoire UCSW sur la plupart des processeurs (par exemple la famille Intel SnB). Cependant, les magasins NT / streaming fonctionnent définitivement sur la mémoire normale.
Peter Cordes
4
@Peter: Vous parlez de la mémoire USWC, n'est-ce pas? Je n'ai jamais entendu parler de mémoire UCSW ou USWC auparavant. Googler le mauvais acronyme n'a pas été utile :-)
Andrew Bainbridge
4
@AndrewBainbridge: Oui, l'attribut de type de mémoire WC. Combinaison d'écriture spéculative impossible à cacher. Je pense que je mettais en majuscule UnCacheable et que je me souvenais qu'il était censé contenir 4 lettres. : P
Peter Cordes

Réponses:

147

Les instructions SSE non temporelles (MOVNTI, MOVNTQ, etc.) ne suivent pas les règles normales de cohérence du cache. Par conséquent, les mémoires non temporelles doivent être suivies d'une instruction SFENCE pour que leurs résultats soient vus par d'autres processeurs en temps opportun.

Lorsque des données sont produites et ne sont pas (immédiatement) consommées à nouveau, le fait que les opérations de stockage en mémoire lisent d'abord une ligne de cache complète, puis modifient les données mises en cache, nuit aux performances. Cette opération pousse les données hors des caches qui pourraient être à nouveau nécessaires au profit de données qui ne seront pas utilisées bientôt. Cela est particulièrement vrai pour les grandes structures de données, telles que les matrices, qui sont remplies puis utilisées plus tard. Avant que le dernier élément de la matrice ne soit rempli, la taille pure expulse les premiers éléments, rendant la mise en cache des écritures inefficace.

Pour cette situation et des situations similaires, les processeurs prennent en charge les opérations d'écriture non temporelles. Non temporel dans ce contexte signifie que les données ne seront pas réutilisées bientôt, il n'y a donc aucune raison de les mettre en cache. Ces opérations d'écriture non temporelles ne lisent pas une ligne de cache, puis la modifient; au lieu de cela, le nouveau contenu est directement écrit dans la mémoire.

Source: http://lwn.net/Articles/255364/

Espo
la source
15
Bonne réponse, je voudrais juste signaler que sur le type de processeur avec instructions NT, même avec une instruction non-non temporelle (c'est-à-dire une instruction normale), le cache de ligne n'est pas "lu puis modifié". Pour une instruction normale écrivant sur une ligne qui n'est pas dans le cache, une ligne est réservée dans le cache et un masque indique quelles parties de la ligne sont à jour. Cette page Web l'appelle "pas de décrochage en magasin": ptlsim.org/Documentation/html/node30.html . Je n'ai pas pu trouver de références plus précises, je n'en ai entendu parler que de gars dont le travail consiste à implémenter des simulateurs de processeur.
Pascal Cuoq
2
En fait, ptlsim.org est un site Web sur un simulateur de processeur précis au cycle, exactement le même genre de chose que font les gars qui m'ont dit "pas de stand en magasin". Je ferais mieux de les mentionner aussi au cas où ils verraient ce commentaire: unisim.org
Pascal Cuoq
1
D'après les réponses et les commentaires ici stackoverflow.com/questions/44864033/ ... il semble que ce SFENCEne soit pas nécessaire. Au moins dans le même fil. Pourriez-vous aussi regarder?
Serge Rogatch
1
@SergeRogatch cela dépend du scénario dont vous parlez, mais oui, il y a des scénarios où cela sfenceest nécessaire pour les magasins NT, alors que cela n'est jamais requis uniquement pour les magasins normaux. Les magasins NT ne sont pas classés par rapport aux autres magasins (NT ou non), comme le voient d'autres threads , sans fichier sfence. Pour les lectures à partir du même thread qui a fait les magasins, cependant, vous n'en avez jamais besoin sfence: un thread donné verra toujours ses propres magasins dans l'ordre du programme, qu'il s'agisse de magasins NT ou non.
BeeOnRope
40

Espo est à peu près sur la cible. Je voulais juste ajouter mes deux cents:

L'expression «non temporelle» signifie l'absence de localité temporelle. Les caches exploitent deux types de localité - spatiale et temporelle, et en utilisant une instruction non temporelle, vous signalez au processeur que vous ne vous attendez pas à ce que l'élément de données soit utilisé dans un proche avenir.

Je suis un peu sceptique quant à l'assemblage codé à la main qui utilise les instructions de contrôle du cache. D'après mon expérience, ces choses conduisent à plus de bugs pervers que toute augmentation efficace des performances.

Pramod
la source
question sur «l'assemblage codé à la main qui utilise les instructions de contrôle du cache». Je sais que vous avez explicitement dit "codé à la main" qu'en est-il de quelque chose comme un JavaVM. Est-ce un meilleur cas d'utilisation? Le JavaVM / Compiler a analysé le comportement statique et dynamique du programme et utilise ces instructions non temporelles.
Pat
4
Exploiter les propriétés de localité connues (ou leur absence) de votre domaine de problème, de votre algorithme ou de votre application ne doit pas être évité. Eviter la pollution du cache est en effet une tâche d'optimisation très attractive et efficace. Aussi, pourquoi l'aversion pour l'assemblage? Il existe de nombreuses opportunités de gains disponibles sur lesquelles un compilateur ne peut pas capitaliser
awdz9nld
5
Il est certainement vrai qu'un programmeur de bas niveau bien informé peut surpasser un compilateur pour les petits noyaux. C'est parfait pour publier des articles et des articles de blog et j'ai fait les deux. Ce sont aussi de bons outils didactiques et aident à comprendre ce qui se passe «vraiment». D'après mon expérience cependant, dans la pratique, où vous avez un système réel avec de nombreux programmeurs qui y travaillent et que l'exactitude et la maintenabilité sont importantes, les avantages du codage de bas niveau sont presque toujours compensés par les risques.
Pramod
4
@Pramod ce même argument se généralise facilement à l'optimisation en général et n'entre pas vraiment dans le champ de la discussion - il est clair que le compromis a déjà été envisagé ou a été jugé non pertinent étant donné que nous parlons déjà d'instructions non temporelles
awdz9nld
7

Selon le manuel du développeur de logiciels des architectures Intel® 64 et IA-32, volume 1: Architecture de base, chapitre «Programmation avec les extensions Intel Streaming SIMD (Intel SSE)»:

Mise en cache des données temporelles et non temporelles

Les données référencées par un programme peuvent être temporelles (les données seront réutilisées) ou non temporelles (les données seront référencées une fois et ne seront pas réutilisées dans le futur immédiat). Par exemple, le code de programme est généralement temporel, alors que les données multimédias, telles que la liste d'affichage dans une application graphique 3D, sont souvent non temporelles. Pour utiliser efficacement les caches du processeur, il est généralement souhaitable de mettre en cache les données temporelles et non de mettre en cache les données non temporelles. La surcharge des caches du processeur avec des données non temporelles est parfois appelée «polluer les caches». Les instructions de contrôle de la capacité de mise en cache SSE et SSE2 permettent à un programme d'écrire des données non temporelles dans la mémoire d'une manière qui minimise la pollution des caches.

Description du chargement non temporel et instructions de stockage. Source: Manuel du développeur de logiciels des architectures Intel 64 et IA-32, volume 2: Référence du jeu d'instructions

CHARGER (MOVNTDQA - Charger un indice aligné non temporel à quatre mots doubles)

Charge un quadruple mot de l'opérande source (deuxième opérande) vers l'opérande de destination (premier opérande) à l'aide d'un indice non temporel si la source de mémoire est de type mémoire WC (combinaison d'écriture) [...]

[...] le processeur ne lit pas les données dans la hiérarchie d'antémémoire, ni n'extrait la ligne d'antémémoire correspondante de la mémoire dans la hiérarchie d'antémémoire.

Notez que, comme le fait remarquer Peter Cordes, ce n'est pas utile sur la mémoire WB normale (réécriture) sur les processeurs actuels car l'indication NT est ignorée (probablement parce qu'il n'y a pas de prélecteurs HW compatibles NT) et la sémantique de charge complète fortement ordonnée s'applique . prefetchntapeut être utilisé comme charge réduisant la pollution à partir de la mémoire WB

STORE (MOVNTDQ — Stocker les entiers compressés à l'aide d'une indication non temporelle)

Déplace les entiers compressés de l'opérande source (deuxième opérande) vers l'opérande de destination (premier opérande) à l'aide d'un indice non temporel pour empêcher la mise en cache des données pendant l'écriture en mémoire.

[...] le processeur n'écrit pas les données dans la hiérarchie d'antémémoire, ni n'extrait la ligne d'antémémoire correspondante de la mémoire dans la hiérarchie d'antémémoire.

En utilisant la terminologie définie dans les stratégies d'écriture du cache et les performances , ils peuvent être considérés comme une écriture contournée (pas d'allocation d'écriture, pas de récupération en cas d'écriture manquée).

Enfin, il peut être intéressant de revoir les notes de John McAlpin sur les magasins non temporels .

chus
la source
3
SSE4.1 MOVNTDQAne fait rien de spécial sur les régions de mémoire WC (uncacheable Write-Combining), par exemple la RAM vidéo. Ce n'est pas du tout utile sur la mémoire WB normale (réécriture) sur le matériel actuel, l'indication NT est ignorée et la sémantique de charge fortement ordonnée complète s'applique. prefetchntapeut être utile, cependant, comme charge de réduction de la pollution de la mémoire WB. Les architectures x86 actuelles prennent-elles en charge les charges non temporelles (à partir de la mémoire «normale»)? .
Peter Cordes
2
C'est exact, les magasins NT fonctionnent correctement sur la mémoire WB, sont faiblement ordonnés et constituent généralement un bon choix pour l' écriture de grandes régions de mémoire. Mais les charges NT ne le sont pas. Le manuel x86 sur papier permet à l'astuce NT de faire quelque chose pour les charges de la mémoire WB, mais dans les processeurs actuels, il ne fait rien . (Probablement parce qu'il n'y a pas de préchargeurs HW compatibles NT.)
Peter Cordes
J'ai ajouté ces informations pertinentes à la réponse. Merci beaucoup.
chus
1
@LewisKelsey: les magasins NT remplacent le type de mémoire. C'est pourquoi ils peuvent être faiblement ordonnés sur la mémoire WB. Le principal effet est d'éviter les RFO (apparemment, ils envoient une invalidation qui efface même d'autres lignes sales quand elles atteignent mem). Ils peuvent aussi devenir visibles hors de l' ordre, ils ne doivent pas attendre après un cache-miss plus tôt (régulier) commits en magasin, ou jusqu'à ce qu'un cache-miss plus tôt charge reçoit les données. c'est-à-dire le type de goulot d'étranglement demandé dans La mémoire en dehors de chaque cœur est-elle toujours conceptuellement plate / uniforme / synchrone dans un système multiprocesseur? .
Peter Cordes
1
@LewisKelsey: Une machine de commande de mémoire effacée pourrait tuer toutes les charges après un magasin UC qui n'auraient pas dû être faites tôt, si nécessaire. En dehors de cela, l'ordre de validation n'entre en jeu qu'après que le magasin se retire du backend en panne. Cela ne peut se produire qu'après l'exécution de l'adresse de stockage uop, auquel point le type de mémoire de l'adresse peut être vérifié. Une adresse de magasin uop vérifie le TLB lors de son exécution; c'est ainsi que les processeurs peuvent détecter les magasins défectueux avant leur retrait. Il ne peut pas attendre que l'entrée SB soit prête à s'engager dans L1d; à ce stade, l'exécution est passée.
Peter Cordes