2015-09-21 8 views
13

Le garanzie Intel modello di memoria:Il modello di memoria Intel rende ridondanti SFENCE e LFENCE?

  • negozi non saranno ri-ordinati con altri negozi
  • carichi non saranno ri-ordinati con altri carichi

http://bartoszmilewski.com/2008/11/05/who-ordered-memory-fences-on-an-x86/

ho visto sostiene che SFENCE è ridondante su x86-64 a causa del modello di memoria Intel, ma mai LFENCE. Le regole del modello di memoria di cui sopra rendono ridondanti entrambe le istruzioni?

+0

Err, che dire degli ordini di magazzino-carico e carico-negozio? –

+0

@IwillnotexistIdonotexist: MFENCE è una barriera di StoreLoad (e anche tutti e 3 altri tipi). E sì, ne hai ancora bisogno. : P Non sono sicuro che carichi/negozi movNT possano mostrare il riordino di LoadStore, o se hanno omesso un'istruzione di barriera LoadStore separata ipotizzando che tipicamente (sempre?) Sia necessaria una barriera di StoreLoad ogni volta che si richiede la barriera di LoadStore. Dal momento che riguarda solo i movnt streaming ops comunque, è un caso speciale di un caso speciale, e x86 va bene senza di esso. : P –

+0

@PeterCordes [In una risposta precedente] (http://stackoverflow.com/a/22142537/2809095), ho citato l'elenco completo oi riordini consentiti dagli Intel SDM. Ma quello che stavo guidando con il mio commento sopra è che OP ha sottolineato, per lo più correttamente, che il riordino Load-Load e Store-Store non si verifica. Tuttavia, quelle sono solo due delle quattro possibilità in totale (Load-Store e Store-Load sono le altre due combinazioni), e quelle altre possibilità _can_ si verificano, da dove nasce l'esigenza di 'mfence/sfence/lfence'. –

risposta

12

Sì, SFENCE e LFENCE sono non operativi, tranne quando si utilizzano gli archivi di streaming movnt (non-Temporal) o si lavora con aree di memoria con un tipo impostato su un valore diverso dal normale Write-Back. I negozi NT bypassano la cache oltre ad essere debolmente ordinati (ma x86's normal memory model is strongly ordered (eccetto vedere sotto per le operazioni Fast-String ops)). (I carichi NT (movntdqa) dalla memoria WB sono still strongly ordered, quindi LFENCE è utile solo quando si legge dalla memoria debolmente ordinata). Questo non accade per caso in programmi "normali", quindi devi preoccuparti solo di questo se hai una RAM video o qualcosa del genere.

Questo post: Memory Reordering Caught in the Act è una descrizione più facile da leggere dello stesso caso di cui parla il post di Bartosz, in cui è necessaria una barriera StoreLoad come MFENCE.

Se hai avuto delle domande dopo aver letto il link che hai postato, leggi i post sul blog di Jeff Preshing. Mi hanno dato una buona comprensione dell'argomento. :) Anche se penso di aver trovato il bocconcino su SFENCE/LFENCE di solito un no-op nella pagina di Doug Lea. I post di Jeff non consideravano i carichi/negozi NT.


ho ottenuto curioso di questo un paio di settimane fa, e ha inviato una risposta piuttosto dettagliata ad una recente domanda: Atomic operations, std::atomic<> and ordering of writes. Ho incluso molti link a cose sul modello di memoria di C++ rispetto ai modelli di memoria hardware.

Se stai scrivendo in C++, usare std::atomic<> è un modo eccellente per dire al compilatore quali sono i requisiti di ordinamento che hai, quindi non riordina le operazioni di memoria in fase di compilazione. Puoi e dovresti usare una versione più debole o acquisire semantica laddove appropriato, invece della consistenza sequenziale predefinita, quindi il compilatore non deve emettere alcuna istruzione di barriera su x86. Deve solo mantenere le operazioni nell'origine.


su un'architettura debolmente ordinato come ARM o PPC, o x86 con movnt, è necessario un'istruzione barriera StoreStore tra la scrittura di un buffer e l'impostazione di un flag per indicare i dati sono pronti. Inoltre, il lettore ha bisogno di un'istruzione di barriera LoadLoad tra il controllo del flag e la lettura del buffer.

Non contando movnt, x86 ha già barriere LoadLoad tra ogni carico e barriere StoreStore tra ogni negozio. (Anche l'ordinamento di LoadStore è garantito). MFENCE sono tutti e 4 i tipi di barriere, incluso StoreLoad, che è l'unica barriera x86 che non esegue per impostazione predefinita. MFENCE si assicura che i carichi non usino i vecchi valori precaricati prima che altri thread vedessero i tuoi negozi e potenzialmente ne facessero di propri. (Oltre ad essere un ostacolo per l'ordinazione e l'ordinazione del carico NT store)

Fun fact: x86 lock - le istruzioni prefissate sono anche barriere di memoria complete. Possono essere utilizzati come sostituto di MFENCE nel vecchio codice a 32 bit che potrebbe essere eseguito su CPU che non lo supportano.lock add [esp], 0 è altrimenti un no-op, e fa il ciclo di lettura/modifica/scrittura sulla memoria che è molto probabile caldo nella cache L1 e già nello stato M del protocollo di coerenza MESI.

SFENCE è una barriera di StoreStore.

LFENCE è un LoadLoad e also a LoadStore barrier. (loadNT/LFENCE/storeNT impedisce il deposito di diventare visibili globalmente prima del carico. Credo che questo potrebbe accadere in pratica se l'indirizzo di carico era il risultato di una catena di dipendenza lunga, o il risultato di un altro carico che ha mancato nella cache.)


Fun fact # 2 (grazie @EOF): I negozi da Fast-String Ops (rep stosb/rep movsb su IvyBridge e successivi) sono debolmente ordinati (ma non bypassano la cache).

Intel documenta il fatto che le operazioni Fast-String potrebbero "apparire fuori servizio" nella sezione 7.3.9.3 del loro Manuale per gli sviluppatori di software, vol1. Dicono anche

"Codice d'ordine-dipendente dovrebbe scrivere ad una variabile semaforo discreta dopo eventuali operazioni di stringa per consentire correttamente ordinata di dati per essere visto da tutti i processori "

Essi non menzionano qualsiasi istruzione di barriera. Il modo in cui l'ho letto, c'è una SFENCE implicita dopo rep stosb/rep movsb (almeno una recinzione per i dati di stringa, probabilmente non altri NT in volo deboli ordinati). Ad ogni modo, la dicitura implica che una scrittura sulla bandiera/semaforo diventa globalmente visibile dopo tutte le scritture stringa-spostamento, quindi non è necessario SFENCE/LFENCE nel codice che riempie un buffer con un'operazione di stringa veloce e quindi scrive una bandiera o nel codice che lo legge. (L'ordinamento LoadLoad avviene sempre, quindi si vedono sempre i dati nell'ordine in cui altre CPU lo rendono globalmente visibile. Ad esempio, l'uso di negozi debolmente ordinati per scrivere un buffer non cambia il fatto che i carichi in altri thread sono ancora fortemente ordinati.)

sommario: utilizzare una memoria normale per scrivere un flag che indica che un buffer è pronto. Non permettere ai lettori di controllare l'ultimo byte del blocco scritto con memset/memcpy. Tuttavia, ritengo che i negozi di fast-string impediscano a eventuali negozi successivi di passarli, quindi hai ancora solo bisogno di SFENCE/LFENCE se stai usando movNT.

C'è un bit MSR della CPU che può essere cancellato per disabilitare le operazioni veloci su stringhe, a beneficio dei nuovi server che devono eseguire binari vecchi che scrivano un flag "dati pronto" come parte di un rep stosb o rep movsb.

+3

Non è solo 'movnt' che ha un ordine di memoria più debole. Lo fanno anche le istruzioni memcpy/strcpy ('rep [ne] movs [b/w/d/q]'). – EOF

+0

@EOF: Grazie, non lo sapevo! Strano che il manuale di insn ref non lo menzioni, solo il manuale Vol1. Ho aggiornato la mia risposta con la mia interpretazione di ciò che dicono i documenti: c'è una barriera implicita di StoreStore (per i dati di stringa) dopo un 'rep movsb', quindi devi solo scrivere il tuo flag pronto per i dati separatamente (non come gli ultimi byte di la stringa op). –

+0

@EOF: non è solo "movnt' e' rep [ne] movs [b/w/d/q] '; ma (potenzialmente) ogni singola istruzione che accede alla memoria; dato che il modello di ordinamento della memoria può essere indebolito configurando le PAT/page tables o MTRRs per la memoria a cui si accede come "write combining" (piuttosto che "write back"). – Brendan

Problemi correlati