La risposta più semplice: è necessario utilizzare uno dei 3 recinzioni (LFENCE
, SFENCE
, MFENCE
) per fornire uno di coerenza dei dati 6:
- Relaxed
- Consumare
- Acquisisci
- uscita
- Acquire-Release
- Sequenziale
C++ 11:
Inizialmente, si dovrebbe prendere in considerazione questo problema dal punto di vista del grado di ordine di accesso alla memoria, che è ben documentato e standardizzato in C++ 11.Si consiglia di leggere prima: http://en.cppreference.com/w/cpp/atomic/memory_order
x86/x86_64:
1. Coerenza Acquire-uscita: Quindi, è importante capire che nel x86 per accedere alla RAM convenzionale (contrassegnato da predefinito come WB - Write Back, e lo stesso effetto con WT (Write Throught) o UC (Uncacheable)) usando asm MOV
senza alcun comando aggiuntivo fornisce automaticamente l'ordine di memoria per la coerenza di acquisizione - std::memory_order_acq_rel
. I.e. per questa memoria ha senso usare solo std::memory_order_seq_cst
solo per fornire coerenza sequenziale. Vale a dire quando si utilizza: std::memory_order_relaxed
o std::memory_order_acq_rel
quindi il codice assembler compilato per std::atomic::store()
(o std::atomic::load()
) sarà lo stesso - solo MOV
senza alcun L/S/MFENCE
.
Nota: Ma devi sapere, che non solo CPU, ma e C++ - compilatore può riordinare le operazioni con la memoria, e tutti i 6 barriere di memoria influiscono sempre sul C++ - il compilatore a prescindere dalla architettura della CPU.
Quindi, è necessario sapere, come può essere compilato da C++ a ASM (codice macchina nativo) o come si può scrivere sull'assembler. Per fornire qualsiasi consistenza escludere sequenziale è possibile semplice scrittura MOV
, ad esempio MOV reg, [addr]
e MOV [addr], reg
ecc
2. sequenziale Consistenza: Ma per fornire coerenza sequenziale è necessario utilizzare implicita (LOCK
) o recinzioni espliciti (L/S/MFENCE
) come descritto qui: Why GCC does not use LOAD(without fence) and STORE+SFENCE for Sequential Consistency?
LOAD
(senza recinto) e STORE
+ MFENCE
LOAD
(senza recinto) e LOCK XCHG
MFENCE
+ LOAD
e STORE
(senza recinzione)
LOCK XADD
(0) e STORE
(senza recinzione)
Ad esempio, GCC utilizzi 1, ma usa MSVC 2. (Ma dovete sapere, che MSVS2012 ha un bug: Does the semantics of `std::memory_order_acquire` requires processor instructions on x86/x86_64?)
Poi, si può leggere Herb Sutter, il tuo link: https://onedrive.live.com/view.aspx?resid=4E86B0CF20EF15AD!24884&app=WordPdf&authkey=!AMtj_EflYn2507c
eccezione alla regola:
Questa regola vale per l'accesso utilizzando MOV
di RAM convenzionale segnata per impostazione predefinita come WB - Write Back. La memoria è contrassegnata nel Page Table, in ciascuna PTE (tabella pagina Enrty) per ogni pagina (memoria continua da 4 KB).
Ma ci sono alcune eccezioni:
Se noi segni di memoria Page Table come Scrivi combinato (ioremap_wc()
in POSIX), quindi automaticamente fornisce Acquisire solo coerenza, e dobbiamo agire come nel paragrafo successivo.
See risposta alla mia domanda: https://stackoverflow.com/a/27302931/1558037
- scrive di memoria non vengono riordinati con le altre scritture, con le seguenti eccezioni:
- scrive eseguiti con l'CLFLUSH l'istruzione;
- archivi di streaming (scritture) eseguiti con le istruzioni di spostamento non temporali (MOVNTI, MOVNTQ, MOVNTDQ, MOVNTPS e MOVNTPD); e
- operazioni di stringa (vedere Sezione 8.2.4.1).
In entrambi i casi 1 & 2 è necessario utilizzare ulteriori SFENCE
tra due operazioni di scrittura allo stesso indirizzo anche se si vuole acquisire-Release coerenza, perché qui automaticamente fornisce solo Acquisire Coerenza e si deve fare di uscita (SFENCE
) da soli.
risposta alle vostre due domande:
A volte quando si fa un negozio di una CPU scriverà al suo buffer negozio invece della cache L1. Non capisco comunque i termini su che una CPU farà questo?
Dal punto di vista dell'utente, la cache L1 e il buffer di memorizzazione si comportano in modo diverso. L1 veloce, ma Store-Buffer più veloce.
Store-buffer - è un semplice coda dove i negozi scrive solo, e che non possono essere riordinate - è fatto per aumentare le prestazioni e nascondere latenza di accesso alla cache (L1 - 1 ns, L2 - 3ns, L3 - 10ns) (CPU-Core pensa che Write sia memorizzato nella cache ed esegua il comando successivo, ma allo stesso tempo le tue scritture vengono salvate solo nello Store-Buffer e saranno salvate nella cache L1/2/3 in seguito), cioè CPU-Core non ha bisogno di aspettare quando le scritture saranno state archiviate nella cache.
Cache L1/2/3 - assomigliano all'array associato trasparente (indirizzo - valore). È veloce ma non il più veloce, perché x86 fornisce automaticamente la coerenza di acquisizione utilizzando il protocollo cache coherentMESIF/MOESI. È fatto per una programmazione multithread più semplice, ma diminuisce le prestazioni. (Veramente, possiamo usare algoritmi e strutture dati di Content Contentions senza usare cache coerente, cioè senza MESIF/MOESI per esempio su PCI Express). Protocolli MESIF/MOESI funziona su QPI che collega Core in CPU e Core tra diverse CPU in sistemi multiprocessore (ccNUMA).
CPU2 potrebbe desiderare di caricare un valore che è stato scritto in al buffer negozio di CPU1. A quanto ho capito, il problema è che CPU2 non può vedere il nuovo valore nel buffer di memoria della CPU1.
Sì.
Perché il protocollo MESI solo include buffer di svuotamento come parte del protocollo ??
protocollo MESI non può semplicemente includere i buffer negozio vampate di calore come parte del suo protocollo, in quanto:
- MESI/MOESI/protoclos MESIF non sono legati alla Store-buffer e non sanno su di esso .
- Automatic flushing Store Buffer ad ogni Writes ridurrebbe le prestazioni e lo renderebbe inutile.
- Flusso manuale Memorizza buffer su tutti i core della CPU remoti (non sappiamo su quale core store-buffer contenga la scrittura richiesta) utilizzando un comando - ridurrebbe le prestazioni (in 8 CPU x 15 core = 120 core allo stesso tempo di lavaggio Store-Buffer - questo è terribile)
Ma manualy Conservare Svuotamento buffer sulle attuali CPU-core - Sì, è possibile farlo eseguire SFENCE
comando. È possibile utilizzare SFENCE
in due casi:
- Per garantire la coerenza sequenziale sulla RAM con Write Torna cacheable
- Per garantire la coerenza Acquire-uscita sul eccezioni alla regola: RAM con Scrivere combinato memorizzabile nella cache, per le scritture eseguite con l'istruzione CLFLUSH e per i non-temporale SSE/AVX comandi
Nota:
Abbiamo bisogno di LFENCE
in ogni caso su x86/x86_64? - la questione non è sempre chiaro: Does it make any sense instruction LFENCE in processors x86/x86_64?
altra piattaforma:
Poi, si può leggere come nella teoria (per un processore sferica sotto vuoto), con Store-Buffer e invalidare-coda, il tuo link: http://www.puppetmastertrading.com/images/hwViewForSwHackers.pdf
e come è possibile fornire la consistenza sequenziale su altre piattaforme, non solo con L/S/MFENCE e BLOCCO ma con LL/SC: http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
"* Perché non è possibile il protocollo MESI sufficiente includere scaricare i buffer di deposito come parte del suo pr otocol ?? * "Se i buffer del negozio dovevano avere un ordine rigoroso rispetto al flusso di istruzioni, non servirebbero a nulla. Senza un simile ordine, quando li svuoti? In sostanza, il tuo suggerimento è "perché non rallentiamo tutto fino alla velocità inter-core piuttosto che richiedere alle persone di identificare le cose specifiche che devono subire questa penalità?" –
Su x86 è praticamente necessario utilizzare la scherma solo se si utilizza un tipo di memoria diverso dalla cache di write-back o se si utilizzano istruzioni non temporali.Vedi anche [questa risposta] (http://stackoverflow.com/a/8883426/547981), e la sezione manuale a cui si fa riferimento. – Jester
Senza alcuna sincronizzazione esplicita, CPU2 potrebbe vedere il vecchio valore anche se il negozio è già stato memorizzato nel buffer del buffer di CPU1, non c'è niente di sbagliato in questo. Solo una volta che CPU1 rende visibile il negozio, CPU2 "deve" vederlo. – Leeor