2011-09-08 16 views
10

So che le CPU moderne possono essere eseguite fuori servizio, tuttavia ritirano sempre i risultati in ordine, come descritto da wikipedia.Esecuzioni fuori servizio e recinzioni di memoria

"Out di processori Oder riempire queste 'slot' nel tempo con altre istruzioni che sono pronti, poi ri-ordinare i risultati alla fine di far sembrare che le istruzioni sono stati elaborati come normale."

Ora, quando si utilizzano le piattaforme multicore, è necessario utilizzare recinzioni di memoria perché, a causa dell'esecuzione fuori servizio, è possibile stampare qui il valore errato di x.

Processor #1: 
while f == 0 
    ; 
print x; // x might not be 42 here 

Processor #2: 
x = 42; 
// Memory fence required here 
f = 1 

Ora la mia domanda è, dal momento che in ordine processori (core in caso di processori multicore presumo) sempre in pensione i risultati in-order, allora che cosa è la necessità di recinzioni di memoria. I core di un processore multicore non vedono i risultati ritirati solo da altri core o vedono anche i risultati in volo?

intendo nell'esempio ho dato sopra, quando Processor 2 in pensione alla fine i risultati, frutto di x dovrebbe venire prima f, giusto? So che durante l'esecuzione dell'ordine potrebbe aver modificato f prima del x ma non deve essersi ritirato prima dello x, giusto?

Ora con il ritiro in ordine dei risultati e il meccanismo di coerenza della cache in atto, perché mai avresti bisogno di recinti di memoria in x86?

+0

Si noti che le schermate di memoria vengono sempre in coppia nel codice corretto: quando due thread comunicano, * ogni * thread deve eseguire un ordinamento di accessi alla memoria (= fence). Di solito, uno di questi recinti ha una semantica di rilascio, l'altro ha acquisito la semantica. Nel tuo pseudocodice, Processor # 2 dovrebbe eseguire una fence di scrittura tra i compiti (semantica di rilascio) e Processor # 1 dovrebbe aggiungere una fence di lettura (acquisire semantica) tra il ciclo e 'print'. Alcune recinzioni potrebbero non essere necessarie su piattaforme specifiche, ma qualsiasi codice sorgente dovrebbe contenere entrambe le recinzioni (che possono essere compilate a noops). – cmaster

risposta

15

Questo tutorial spiega i problemi: http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

FWIW, dove accadono le questioni di ordinamento della memoria sui moderni processori x86, il motivo è che, mentre il modello di coerenza di memoria x86 offre molto forte consistenza, sono necessarie barriere esplicite per gestire in lettura coerenza dopo-scrittura. Questo è dovuto a qualcosa chiamato "store buffer".

Cioè, x86 è sequenzialmente coerente (bello e facile da ragionare) tranne che i carichi possono essere riordinati nei negozi precedenti. Cioè, se il processore esegue la sequenza

store x 
load y 

poi sul bus processore puo 'essere visto come

load y 
store x 

La ragione di questo comportamento è il buffer negozio suddetta, che è una piccola buffer per le scritture prima che escano sul bus di sistema. Il carico di latenza è, OTOH, un problema critico per le prestazioni, e quindi i carichi sono autorizzati a "saltare la coda".

Vedere sezione 8.2 in http://download.intel.com/design/processor/manuals/253668.pdf

+2

+1 per menzionare il buffer del negozio –

+0

Janneb, puoi spiegare un po 'il buffer del negozio e perché sono importanti in questo contesto? – MetallicPriest

+0

Non memorizza nella cache la coerenza assicurati che ci sia coerenza tra lettura e scrittura in x86? – MetallicPriest

7

La recinzione memoria assicura che tutte le modifiche alle variabili prima della recinzione sono visibili a tutti gli altri nuclei, in modo che tutti i nuclei hanno una vista fino a data dei dati.

Se non si inserisce una fence di memoria, i core potrebbero funzionare con dati errati, questo può essere visto soprattutto in scenari, dove più core potrebbero lavorare sugli stessi dataset. In questo caso puoi assicurarti che quando la CPU 0 ha fatto qualche azione, tutte le modifiche apportate al set di dati sono ora visibili a tutti gli altri core, che possono quindi lavorare con informazioni aggiornate.

Alcune architetture, tra cui l'onnipresente x86/x64, forniscono diverse istruzioni barriera di memoria, tra cui un'istruzione a volte chiamato "recinto pieno". Una recinzione completa garantisce che tutte le operazioni di carico e di stoccaggio precedenti alla recinzione siano state confermate prima di eventuali carichi e di depositi emessi in seguito alla recinzione.

Se un nucleo doveva iniziare a lavorare con dati obsoleti sul set di dati, come poteva mai ottenere i risultati corretti? Non poteva importare se il risultato finale dovesse essere presentato come se tutto fosse stato fatto nel giusto ordine.

La chiave è nel buffer negozio, che si trova tra la cache e la CPU, e fa questo:

tampone

negozio invisibile per CPU remota

negozio buffer consente scrive nella memoria e/o cache per essere salvati ottimizzare interconnessione accessi

ciò significa che le cose saranno scritti a questo buffer, e poi ad un certo punto sarà il buffer essere scritti nella cache. Quindi la cache potrebbe contenere una vista di dati che non è la più recente, e quindi un'altra CPU, attraverso la coerenza della cache, non avrà anche i dati più recenti. È necessario un flush del buffer del negozio affinché i dati più recenti siano visibili, questo, penso che sia essenzialmente ciò che la recinzione della memoria causerà a livello hardware.

EDIT:

Per il codice è stato utilizzato come esempio, Wikipedia dice:

Una barriera di memoria può essere inserito prima assegnazione del processore # 2 di af per garantire che il nuovo valore di x è visibile ad altri processori o prima della modifica del valore di f.

2

Giusto per rendere esplicito ciò che è implicito nelle risposte precedenti, questo è corretto, ma è distinto da accessi alla memoria:

CPU in grado di eseguire in ordine, però hanno sempre ritirano i risultati in- ordine

Il ritiro dell'istruzione è separato dall'eseguire l'accesso alla memoria, l'accesso alla memoria può essere completato in un altro momento al ritiro delle istruzioni.

Ogni core agirà come se i propri accessi alla memoria si verificano al momento del pensionamento, ma altri core potrebbero vedere quegli accessi in momenti diversi.

(On x86 e ARM, io soltanto negozi sono observably soggetti a questo, ma per esempio, alfa può caricare un vecchio valore dalla memoria. X86 SSE2 ha istruzioni con guarentees più debole del normale comportamento x86).

PS. A memoria, lo Sparc ROCK abbandonato poteva infatti ritirarsi fuori servizio, consumando energia e transistor determinando quando ciò era innocuo. È stato abbandonato a causa del consumo di energia e del conteggio dei transistor ... Non credo che nessuna CPU di uso generale sia stata acquistata sul mercato con il ritiro fuori dall'ordinazione.

+1

Ci sono state proposte teoriche per il ritiro fuori dall'ordinazione per rendere possibile nascondere la latenza della memoria con una finestra out-of-order dell'istruzione di 1k, senza semplicemente aumentare un ROB normale a voci 1k poco pratiche. In particolare, il processore kilo-instruction. Google ha trovato questo link su un sito a caso: http://cgi.di.uoa.gr/~halatsis/Advanced_Comp_Arch/General_presentations/ACM_online-Seminars/Valero/kilo-Instruction.pdf. E anche https://www.csl.cornell.edu/~martinez/doc/taco04.pdf. –

+1

E BTW, un singolo core vede i propri accessi di memoria avvenire in ordine, ma non devono aspettare il pensionamento. Il forwarding del negozio consente a un carico di accedere ai dati memorizzati di recente senza attendere che il negozio si ritiri e (a un certo punto dopo) di eseguire il commit sulla cache L1D. http://blog.stuffedcow.net/2014/01/x86-memory-disambiguation/ –