2012-01-15 2 views
5

Supposons qu'il y a deux threads s'exécutant sur x86 CPU0 et CPU1 respectivement. Discussion en cours d'exécution sur CPU0 exécute les commandes suivantes:Est-ce que deux magasins CPU consécutifs sur x86 sont vidés dans le cache en maintenant l'ordre?

A=1 
B=1 

ligne de cache contenant un premier temps détenu par CPU1 et contenant B appartenant à CPU0.

J'ai deux questions:

  1. Si je comprends bien, les deux magasins seront mis dans le tampon de stockage de CPU. Cependant, pour le premier magasin A=1, le cache de CPU1 doit être invalidé tandis que le second magasin B=1 peut être vidé immédiatement puisque CPU0 possède la ligne de cache le contenant. Je sais que le processeur x86 respecte les commandes des magasins. Est-ce que cela signifie que B=1 ne sera pas écrit dans le cache avant A=1?

  2. Supposons en CPU1 les commandes suivantes sont exécutées:

alors que (B = 0);
print A

est-il suffisant pour ajouter que lfence entre les commandes et whileprint dans CPU1 sans ajouter sfence entre A=1 et B=1 à CPU0 pour obtenir 1 toujours imprimé sur x86?

while (B=0); 
lfence 
print A 
+0

Même si x86 le garantit, pourquoi prendre le risque? Pourquoi ne pas simplement utiliser les bonnes barrières? –

+1

Zan, il peut être avantageux à plusieurs endroits si la CPU le garantit. Par exemple, les spinlocks sont implémentés sans utiliser de préfixe de verrouillage dans le noyau car ils peuvent se le permettre. Et la clôture n'est pas la solution à cette question sinon, il faut utiliser un verrou approprié. – Saurabh

+0

La réponse à la ** première question - Oui **. La réponse à la ** 2-ème question - Oui, mais seulement en assembleur (pas en C/C++) **. Comme on l'a dit à juste titre, «LFENCE» n'est pas nécessaire ici sur x86 - il fournit automatiquement la cohérence. Notez que le processeur x86 ne peut pas réorganiser 'load' et toutes les instructions suivantes, mais C/C++ peut le réorganiser. Sur C++ vous utiliserez ** acquérir la consistance **: 'extern std :: atomique B;' 'while (B.load (std :: memory_order_acquire) == 0);' 'std :: cout << A;' http://fr.cppreference.com/w/cpp/atomic/memory_order – Alex

Répondre

8

En x86, les écritures par un seul processeur sont observées dans le même ordre par tous les processeurs. Pas besoin de clôturer dans votre exemple, ni dans aucun programme normal sur x86. Votre programme:

while(B==0); // wait for B == 1 to become globally observable 
print A;  // now, A will always be 1 here 

Ce qui se passe exactement dans le cache est spécifique au modèle. Toutes sortes d'astuces et de comportements spéculatifs peuvent se produire dans le cache, mais le comportement observable suit toujours les règles.

Voir le Guide de programmation système Intel Volume 3, section 8.2.2. pour les détails sur l'ordre de la mémoire.

Questions connexes