2012-03-04 16 views
53

Qualcuno può spiegare cosa è std :: memory_order in inglese e come usarli con std :: atomic <>?C++, std :: atomic, cosa è std :: memory_order e come usarli?

Ho trovato il riferimento e alcuni esempi qui, ma non capisco affatto. http://en.cppreference.com/w/cpp/atomic/memory_order

Grazie.

+0

+1 molto buona domanda. speriamo in alcune buone risposte! –

+0

Ho trovato questo (piuttosto denso) [risposta] (http://stackoverflow.com/a/7463092/726300) utile in passato come introduzione all'ordinazione della memoria. –

+0

Sembra che questo argomento possa andare piuttosto in profondità. Come ha suggerito zvrba, come un principiante come me, usare il valore predefinito "ordinamento sequenziale-consistente" potrebbe essere una buona idea. – 2607

risposta

18

Qualcuno può spiegare che cosa è std :: memory_order in parole povere,

La spiegazione migliore "Plain English" che ho trovato per i diversi ordinamenti di memoria è l'articolo di Bartoz Milewski su Atomics rilassati: http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/

e il follow-up post: http://bartoszmilewski.com/2008/12/23/the-inscrutable-c-memory-model/

Ma nota che, mentre questi articoli sono una buona introduzione, che pre-data in cui il C++ 11 standard e non vi dirà eV tutto ciò che devi sapere per usarli in sicurezza.

e come utilizzarli con std :: atomico <>?

Il mio miglior consiglio per voi qui è: non. Gli atomici rilassati sono (probabilmente) la cosa più difficile e pericolosa in C++ 11.Attenersi a std::atomic<T> con l'ordine di memoria predefinito (consistenza sequenziale) fino a quando non si è veramente sicuri di avere un problema di prestazioni che può essere risolto utilizzando gli ordini di memoria rilassati.

Nel secondo articolo linkato sopra, Bartoz Milewski giunge alla seguente conclusione:

Non avevo idea di quello che mi stavo cacciando quando si cerca di ragionare su C++ Atomics deboli. La teoria dietro di loro è così complessa che è impossibile usare il limite . Sono state necessarie tre persone (Anthony, Hans e me) e una modifica allo standard per completare la dimostrazione di un algoritmo relativamente semplice . Immagina di fare lo stesso per una coda priva di lock su atomici deboli!

+0

grazie per il vostro consiglio. Come principiante, ho trovato questo molto utile. – 2607

+0

buon collegamento e buon consiglio, grazie! – hacoo

+0

Vedi gli articoli di Jeff Preshing, come [questo su acquisizione/rilascio] (http: // preshing.com/20120913/acquire-and-release-semantics /), per materiale di introduzione eccellente che descrive C++ 11 e descrive le cose in termini di tipi di riordino della memoria consentiti/non consentiti. (Ad esempio, è consentito il riordino StoreLoad) –

14

No. Una spiegazione "inglese normale" occupa 32 pagine e può essere trovata here.

Se non vuoi leggerlo, puoi dimenticarti dell'ordine di memoria perché la pagina che hai linkato dice che l'impostazione predefinita è l'ordinamento sequenziale, che è "fai sempre la cosa sana".

Per utilizzare qualsiasi altra impostazione si in realtà necessario leggere e comprendere la suddetta carta e gli esempi in esso.

+0

Buono, link. Grazie. –

5

In breve, il compilatore e la CPU possono eseguire le istruzioni in ordine diverso da come le hai scritte. Per un singolo thread questo non è un problema in quanto sembrerà corretto. Per più thread su più processori questo diventa un problema. L'ordine di memoria in C++ limita ciò che il tuo compilatore/CPU può fare e risolve tali problemi.

Ad esempio, se si guarda il mio articolo su double-check locking, è possibile vedere come l'ordine si confonde con tale modello, menzionando l'opzione di memoria atomica per ripararlo.

Riguardo al riordino stesso, è possibile considerare anche CPU Reordering - anche in questo caso il compilatore potrebbe eseguire anche i riordini.

Tenere presente che qualsiasi documento su questo argomento (incluso il mio) offerta parla di scenari teorici. Le CPU più comuni, come x86, hanno un ordine molto forte che garantisce che molti ordini espliciti semplicemente non sono necessari. Pertanto, anche se non si utilizzano gli atomici C++ 11 corretti, il codice probabilmente funzionerà ancora.

Come menzionato da zvrba, l'argomento è in realtà piuttosto dettagliato. Il documento del kernel linux su memory barriers contiene anche molte informazioni dettagliate.

30

I valori std::memory_order consentono di specificare i vincoli a grana fine sull'ordine di memoria fornito dalle operazioni atomiche. Se si stanno modificando e accedendo a variabili atomiche da più thread, passare i valori std::memory_order alle operazioni consente di rilassare i vincoli sul compilatore e sul processore sull'ordine in cui le operazioni su tali variabili atomiche diventano visibili ad altri thread, e gli effetti di sincronizzazione hanno quelle operazioni sui dati non atomici nella tua applicazione.

L'ordinamento di default del std::memory_order_seq_cst è più vincolato, e fornisce le proprietà "intuitivi" ci si potrebbe aspettare: se infilare un memorizza alcuni dati e quindi imposta una bandiera atomica usando std::memory_order_seq_cst, quindi se thread B vede il flag è impostato allora può vedere i dati scritti dal thread A. Gli altri valori di ordine della memoria non forniscono necessariamente questa garanzia e devono quindi essere usati con molta attenzione.

La premessa fondamentale è: non utilizzare qualcosa di diverso std::memory_order_seq_cst (impostazione predefinita) a meno che (a) si ha realmente davvero sapere cosa si sta facendo, e può dimostrare che l'utilizzo rilassato è sicuro in tutti i casi, e (b) il tuo profiler dimostra che la struttura dei dati e le operazioni con cui intendi utilizzare gli ordini rilassati sono un collo di bottiglia.

mio libro, C++ Concurrency in Action dedica un intero capitolo (45 pagine) per i dettagli del modello di memoria C++, operazioni atomiche ei std::memory_order vincoli, e un ulteriore capitolo (44 pagine) utilizzando operazioni atomiche per la sincronizzazione in blocco privo strutture di dati e le conseguenze dei vincoli di ordine rilassato.

I miei post sul blog Dekker's algorithm e Peterson's algorithm per l'esclusione reciproca illustrano alcuni dei problemi.

+1

Rilassato è abbastanza sicuro per quello che è veramente necessario per-- leggere valori isolati che non hanno valori dipendenti/corrispondenti e quindi nessun rischio di problemi di ordinazione. Per esempio. un 'booster dovrebbeHalt' per chiedere a un thread di fermarsi. Nella mia esperienza, tale isolamento non è raro nel normale sviluppo del software. E sostengo che per l'altro caso (dipendenze tra più variabili), un blocco è quasi sempre migliore in primo luogo. L'unico modo in cui vedo le persone che hanno difficoltà con questo è con strutture di dati collegate con fantasia atomica, che è la cosa reale da tenere d'occhio a meno che non ci sia un bisogno serio. – VoidStar

Problemi correlati