2012-01-12 9 views
27

Sono un principiante quando si tratta di questo. Qualcuno potrebbe fornire una spiegazione semplificata delle differenze tra le seguenti barriere di memoria?C++ Memory Barriers for Atomics

  • Le finestre MemoryBarrier();
  • La recinzione _mm_mfence();
  • L'assembly inline asm volatile ("" : : : "memory");
  • L'intrinseca _ReadWriteBarrier();

Se non c'è una spiegazione semplice alcuni link ad articoli o libri buoni sarebbe probabilmente aiutami a capire Fino ad ora stavo bene usando solo gli oggetti scritti da altri che avvolgono queste chiamate, ma mi piacerebbe avere una comprensione migliore del mio attuale pensiero, che è fondamentalmente sulla falsariga di come ci sia più di un modo per implementare le barriere di memoria sotto le copertine.

+4

ti sei dimenticato di C++ 11s 'atomic_thread_fence' – Grizzly

+0

Beh, questo è ciò che sta portando a ... abbiamo il nostro oggetto template atomico per i tipi interi e sto volendo passare agli atomici standard C++ 11. Prima di farlo, voglio capire l'implementazione di base di come funzionano entrambi. – AJG85

risposta

28

Entrambe MemoryBarrier (MSVC) e _mm_mfence (supportate da diversi compilatori) forniscono una memoria di memoria hardware, che impedisce al processore di spostare le letture e le scritture attraverso la recinzione.

La differenza principale è che MemoryBarrier ha implementazioni specifiche per piattaforma x86, x64 e IA64, dove come _mm_mfence utilizza specificamente l'istruzione SS, quindi non è sempre disponibile.

Su x86 e x64 MemoryBarrier è implementato con un xchg e lock or rispettivamente, e ho visto alcune affermazioni che questo è più veloce di mfence. Tuttavia i miei benchmark mostrano il contrario, quindi apparentemente dipende molto dal modello del processore.

Un'altra differenza è che mfence può anche essere utilizzato per ordinare negozi/carichi non temporali (movntq ecc.).

GCC dispone anche di __sync_synchronize che genera una recinzione hardware.

asm volatile ("" : : : "memory") in GCC e _ReadWriteBarrier in MSVC forniscono solo un recinto di memoria a livello di compilatore, impedendo al compilatore di riordinare gli accessi alla memoria. Ciò significa che il processore è ancora libero di riordinare.

Le recinzioni del compilatore sono generalmente utilizzate in combinazione con operazioni che presentano una sorta di recinzione hardware implicita. Per esempio. su x86/x64 tutti i negozi hanno un recinto di rilascio e i carichi hanno un recinto di acquisizione, quindi è sufficiente un recinto del compilatore quando si implementa l'acquisizione del carico e lo store-release.

+0

perfetto! grazie, questo ha aiutato molto – AJG85

3

Vedere la risposta here sulla semantica hardware delle recinzioni. Ciò che non è menzionato è che impediscono anche il riordino di carichi, negozi o carichi di negozi & (a seconda della recinzione) attraverso le recinzioni, sia a livello di compilatore che a livello di hardware.