Risposte:
Per aumentare le prestazioni, le CPU moderne spesso eseguono istruzioni in modo non ordinato per sfruttare al massimo il silicio disponibile (comprese le letture / scritture della memoria). Poiché l'hardware impone l'integrità delle istruzioni, non lo noterai mai in un singolo thread di esecuzione. Tuttavia, per più thread o ambienti con memoria volatile (ad esempio I / O mappato in memoria) questo può portare a comportamenti imprevedibili.
Una barriera / barriera della memoria è una classe di istruzioni che indica che le operazioni di lettura / scrittura della memoria avvengono nell'ordine previsto. Ad esempio un "recinto completo" significa che tutte le letture / scritture prima del recinto vengono commesse prima di quelle dopo il recinto.
Nota che i recinti della memoria sono un concetto hardware. Nei linguaggi di livello superiore siamo abituati a trattare con mutex e semafori - questi possono essere implementati utilizzando recinti di memoria a basso livello e l'uso esplicito di barriere di memoria non è necessario. L'utilizzo di barriere di memoria richiede uno studio attento dell'architettura hardware e si trova più comunemente nei driver di dispositivo che nel codice dell'applicazione.
Il riordino della CPU è diverso dalle ottimizzazioni del compilatore, sebbene gli artefatti possano essere simili. È necessario adottare misure separate per impedire al compilatore di riordinare le istruzioni se ciò può causare un comportamento indesiderato (ad esempio, l'uso della parola chiave volatile in C).
Copiando la mia risposta a un'altra domanda, quali sono alcuni trucchi che un processore fa per ottimizzare il codice? :
Il più importante sarebbe il riordino dell'accesso alla memoria.
In assenza di barriere di memoria o istruzioni di serializzazione, il processore è libero di riordinare gli accessi alla memoria. Alcune architetture di processori hanno limitazioni su quanto possono essere riordinate; Alpha è noto per essere il più debole (cioè quello che può riordinare di più).
Un ottimo trattamento dell'argomento può essere trovato nella documentazione dei sorgenti del kernel Linux, in Documentation / memory-barriers.txt .
La maggior parte delle volte, è meglio usare primitive di blocco dal compilatore o dalla libreria standard; questi sono ben testati, dovrebbero avere tutte le barriere di memoria necessarie in atto e sono probabilmente abbastanza ottimizzati (l'ottimizzazione delle primitive di bloccaggio è complicato; anche gli esperti possono sbagliarle a volte).
Alpha is known for being the weakest
, perché weakest
? Non è meglio che riordini di più, quindi di conseguenza sarà l'esecuzione molto più veloce? (Non sono un utente alpha, ma chiedo informazioni sull'effetto di very reordering
vs restricted reordering
). Quindi quali sono gli svantaggi del riordino dei lotti (eccetto per il rischio di comportamenti indefiniti, ma immagino che la maggior parte delle CPU moderne avrebbe dovuto risolvere un buon riordino e implementare solo un riordino definito, altrimenti non avrebbe senso la decisione presa).
Nella mia esperienza si riferisce a una barriera di memoria , che è un'istruzione (esplicita o implicita) per sincronizzare l'accesso alla memoria tra più thread.
Il problema si verifica nella combinazione di moderni compilatori aggressivi (hanno una straordinaria libertà di riordinare le istruzioni, ma di solito non sanno nulla dei tuoi thread) e moderne CPU multicore.
Una buona introduzione al problema è la " Dichiarazione " Il blocco a doppio controllo è rotto ". Per molti è stata la sveglia che ci fossero i draghi.
Le barriere implicite della memoria completa sono solitamente incluse nelle routine di sincronizzazione dei thread della piattaforma, che ne coprono il nucleo. Tuttavia, per la programmazione senza blocchi e l'implementazione di modelli di sincronizzazione personalizzati e leggeri, spesso è necessaria solo la barriera, o anche solo una barriera unidirezionale.
La barriera di memoria, nota anche come memar o barriera di memoria, è una classe di istruzioni che fa sì che un'unità di elaborazione centrale (CPU) imponga un vincolo di ordinamento sulle operazioni di memoria emesse prima e dopo l'istruzione di barriera.
Le CPU utilizzano ottimizzazioni delle prestazioni che possono comportare l'esecuzione fuori ordine, incluso il carico di memoria e le operazioni di archiviazione. Il riordino delle operazioni di memoria normalmente passa inosservato all'interno di un singolo thread di esecuzione, ma causa comportamenti imprevedibili in programmi e driver di dispositivo simultanei a meno che non vengano controllati attentamente. La natura esatta di un vincolo di ordinamento dipende dall'hardware e definita dal modello di memoria dell'architettura. Alcune architetture forniscono più barriere per applicare diversi vincoli di ordinamento.
Le barriere di memoria vengono in genere utilizzate quando si implementa un codice macchina di basso livello che opera su una memoria condivisa da più dispositivi. Tale codice include primitive di sincronizzazione e strutture dati prive di blocco su sistemi multiprocessore e driver di dispositivo che comunicano con l'hardware del computer.