2013-06-07 14 views
5

C'è un'illustrazione in kernel fonte Documentazione/memory-barriers.txt, in questo modo:come è una barriera di memoria nel kernel di Linux è usato

CPU 1     CPU 2 
    ======================= ======================= 
      { B = 7; X = 9; Y = 8; C = &Y } 
    STORE A = 1 
    STORE B = 2 
    <write barrier> 
    STORE C = &B   LOAD X 
    STORE D = 4    LOAD C (gets &B) 
          LOAD *C (reads B) 

Senza l'intervento, CPU 2 può percepire gli eventi su CPU 1 in qualche modo efficace a caso, nonostante la barriera scrittura rilasciata da CPU 1:

+-------+  :  :    :  : 
    |  |  +------+    +-------+ | Sequence of update 
    |  |------>| B=2 |-----  --->| Y->8 | | of perception on 
    |  | : +------+  \   +-------+ | CPU 2 
    | CPU 1 | : | A=1 |  \  --->| C->&Y | V 
    |  |  +------+  |  +-------+ 
    |  | wwwwwwwwwwwwwwww |  :  : 
    |  |  +------+  |  :  : 
    |  | : | C=&B |--- |  :  :  +-------+ 
    |  | : +------+ \ |  +-------+  |  | 
    |  |------>| D=4 | ----------->| C->&B |------>|  | 
    |  |  +------+  |  +-------+  |  | 
    +-------+  :  :  |  :  :  |  | 
            |  :  :  |  | 
            |  :  :  | CPU 2 | 
            |  +-------+  |  | 
     Apparently incorrect ---> |  | B->7 |------>|  | 
     perception of B (!)  |  +-------+  |  | 
            |  :  :  |  | 
            |  +-------+  |  | 
     The load of X holds ---> \  | X->9 |------>|  | 
     up the maintenance   \  +-------+  |  | 
     of coherence of B    ----->| B->2 |  +-------+ 
              +-------+ 
              :  : 

non capisco, dal momento che abbiamo una barriera di scrittura, quindi, eventuali s tore deve avere effetto quando C = & B viene eseguito, il che significa da che B equivale a 2. Per CPU 2, B dovrebbe essere 2 quando ottiene il valore di C, che è & B, perché dovrebbe percepire B come 7. Sono davvero confuso.

risposta

8

Il punto mancante chiave è il presupposto errato che per la sequenza:

LOAD C (gets &B) 
LOAD *C (reads B) 

il primo carico deve precedere il secondo carico. A architetture debolmente ordinate possono agire "come se" il seguente accaduto:

LOAD B (reads B) 
LOAD C (reads &B) 
if(C!=&B) 
    LOAD *C 
else 
    Congratulate self on having already loaded *C 

Il speculativa "LOAD B" può accadere, per esempio, perché B era sulla stessa linea di cache di qualche altra variabile di interesse in precedenza o hardware il prefetching lo ha afferrato.

+0

Molto conciso e giusto al punto – dspjm

6

Dalla sezione del documento intitolato "ciò che non può essere assunto DI BARRIERE DI MEMORIA?":

Non v'è alcuna garanzia che una delle accessi alla memoria specificato prima di una barriera di memoria sarà completa dal completamento di una istruzione di memoria ; la barriera può essere considerata per tracciare una linea nella coda di accesso della CPU che gli accessi del tipo appropriato potrebbero non attraversare.

e

Non v'è alcuna garanzia che una CPU vedrà l'ordine corretto degli effetti da accessi un secondo di CPU, anche se la seconda CPU utilizza una barriera di memoria , a meno che il primo CPU anche utilizza una barriera di memoria corrispondente (vedere la sottosezione "Accoppiamento barriera SMP").

barriere Che ricordo (in modo molto semplificato, naturalmente) è assicurarsi né il compilatore né hardware nella CPU di eseguire qualsiasi tentativo intelligente al riordino operazioni di carico (o negozio) attraverso una barriera, e che il La CPU percepisce correttamente le modifiche apportate alla memoria da altre parti del sistema. Questo è necessario quando i carichi (oi negozi) hanno un significato addizionale, come il blocco di un lucchetto prima di accedere a qualunque cosa stiamo chiudendo. In questo caso, lasciare che il compilatore/CPU renda gli accessi più efficienti riordinandoli è pericoloso per il corretto funzionamento del nostro programma.

Durante la lettura di questo documento abbiamo bisogno di mantenere due cose in mente:

  1. che un carico significa trasmettere un valore dalla memoria (o cache) ad un registro della CPU.
  2. A meno che le CPU non condividano la cache (o non abbiano affatto cache), è possibile che i loro sistemi di cache siano momentaneamente sincronizzati.

Il n. 2 è uno dei motivi per cui una CPU può percepire i dati in modo diverso da un altro. Mentre i sistemi di cache sono progettati per fornire buone prestazioni e coerenza nel caso generale, ma potrebbero aver bisogno di aiuto in casi specifici come quelli illustrati nel documento.

In generale, come suggerisce il documento, le barriere nei sistemi che coinvolgono più di una CPU devono essere accoppiate per forzare il sistema a sincronizzare la percezione di entrambe (o di tutte le CPU partecipanti). Immaginate una situazione in cui una CPU completa carichi o negozi e la memoria principale viene aggiornata, ma i nuovi dati devono ancora essere trasmessi alla cache della seconda CPU, con conseguente mancanza di coerenza tra le due CPU.

Spero che questo aiuti. Suggerirei di leggere memory-barriers.txt di nuovo con questo in mente e in particolare la sezione intitolata "THE EFFECTS OF THE CPU CACHE".

Problemi correlati