2010-10-03 4 views
2

Je lis ces jours-ci sur les barrières de mémoire et les barrières comme un moyen de synchroniser le code multithread et d'éviter le réordonnancement du code.Barrières de mémoire/barrières en C++: boost ou autres bibliothèques en ont-elles?

Je développe généralement en C++ sous Linux et j'utilise massivement les librairies boost mais je n'arrive pas à trouver de classe en rapport avec ça. Savez-vous si la barrière de la barrière de la mémoire est présente dans boost ou s'il y a un moyen d'atteindre le même concept? Si ce n'est pas à quelle bonne bibliothèque puis-je regarder?

Répondre

0

Il existe une classe/concept boost::barrier mais c'est un peu haut niveau. En parlant de cela, pourquoi avez-vous besoin d'une barrière de bas niveau? Les primitives de synchronisation devraient suffire, n'est-ce pas? Et ils devraient utiliser des barrières de mémoire si nécessaire, directement ou indirectement à travers d'autres primitives de niveau inférieur. Si vous pensez toujours avoir besoin d'une implémentation de bas niveau, je ne connais aucune classe ou bibliothèque qui implémente des barrières, mais il y a du code spécifique à l'implémentation dans le noyau Linux. Recherchez mb(), rmb() ou wmb() dans include/asm-{arch}/system.h.

+0

Salut Aib! Je ne suis pas en mesure de vous dire maintenant pourquoi cela est nécessaire. Je lis à propos de "éviter de réordonner" problème et je vois le code qui n'utilise pas de verrou du tout .. Je regarde ici http://www.cs.umd.edu/~pugh/java/memorymodel/DoubleCheckedLocking .html comme point de départ ,, – user311906

+0

Ah, je vois. Ils essaient d'éviter de synchroniser toute la méthode (ce qui est la solution la plus simple, quoique plus lente). – aib

+0

Remarque: «Modifier la sémantique pour exiger que la libération d'un verrou soit une barrière de mémoire complète entraînerait des pénalités de performance. Une autre solution plus simple et plus lente ici. Pour autant que je sache (je suis trop fatigué, désolé), la solution proposée sépare les barrières des serrures pour augmenter les performances. Je pense que vous allez avoir besoin d'une barrière de mémoire de bas niveau (c'est-à-dire une instruction unique, non portable) ici. – aib

5

Il n'y a pas encore de barrières de mémoire de bas niveau dans boost, mais il existe une bibliothèque boost.atomic qui les fournit.

Les compilateurs fournissent leurs propres fonctions intrinsèques ou de bibliothèque, telles que __sync_synchronize() de gcc ou _mm_mfence() pour Visual Studio.

La bibliothèque C++ 0x fournit des opérations atomiques incluant des barrières de mémoire sous la forme std::atomic_thread_fence. Bien que gcc ait fourni diverses formes de l'atomique C++ 0x depuis la version V4.4, ni V4.4 ni V4.5 n'incluent cette forme de clôture. Ma bibliothèque (commerciale) just::thread fournit une implémentation complète des atomiques C++ 0x, y compris des clôtures pour g ++ 4.3 et 4.4, et Microsoft Visual Studio 2005, 2008 et 2010.

+0

Salut! THanks.Proposé? Si je ne me trompe pas, le boost.atomic que vous voulez dire est en boost/interprocess/details donc dans la librairie interprocess. Je vais vérifier ... – user311906

+0

Boost.Atomic est une nouvelle bibliothèque, pas un sous-ensemble de Boost.Interprocess. L'intention de boost.atomic est de mettre en œuvre l'ensemble complet des types atomiques de style C++ 0x, y compris les clôtures et le modèle 'atomic '. Boost.Interprocess et d'autres bibliothèques de boost définissent des opérations atomiques spécifiques sur des types spécifiques qui font ce dont ils ont besoin et rien d'autre. –

+0

Merci beaucoup! – user311906

1

L'endroit où des barrières de mémoire sont requises est en utilisant des mécanismes de synchronisation du noyau dans un environnement SMP - généralement pour des raisons de performances. Il existe une barrière de mémoire implicite dans toute opération de synchronisation du noyau (par exemple des sémaphores de signalisation, des mutations de verrouillage et de déverrouillage) et une commutation de contenu pour se prémunir contre les risques de cohérence des données. Je viens de me retrouver avec des implémentations (modérément) portables de la barrière de mémoire (ARM et x86), et j'ai trouvé que l'arborescence des sources Linux était la meilleure source pour cela. Linux a des variantes SMP des macros mb(), rmb() et wmb() - qui, sur certaines plateformes, entraînent des barrières plus spécifiques (et éventuellement moins coûteuses) que les variantes non-SMP.
Cela ne semble pas être un problème sur x86 et en particulier ARM où, bien que les deux sont mis en œuvre de la même manière.

C'est ce que j'ai chipé ensemble des fichiers d'en-tête linux (adapté pour ARMv7 et processeurs x86/x64 non anciennes)

#if defined(__i386__) || defined(__x64__) 

#define smp_mb() asm volatile("mfence":::"memory") 
#define smp_rmb() asm volatile("lfence":::"memory") 
#define smp_wmb() asm volatile("sfence" ::: "memory") 
#endif 

#if defined(__arm__) 

#define dmb() __asm__ __volatile__ ("dmb" : : : "memory") 

#define smp_mb() dmb() 
#define smp_rmb() dmb() 
#define smp_wmb() dmb() 
#endif 

Naturellement, barboter avec des barrières de mémoire a le risque connexe que le code résultant est pratiquement impossible à tester, et tous les bugs qui en résultent seront obscurs et difficiles à reproduire conditions de course:/

Il y a, incidemment, une très bonne description des barrières de mémoire dans le Linux kernel documentation.

Questions connexes