10

In quali circostanze non è sicuro avere due thread diversi che scrivono simultaneamente su elementi adiacenti dello stesso array su x86? Capisco che su alcune architetture simili a DS9K con modelli di memoria folle questo può causare lacerazione di parole, ma su byte x86 singoli sono indirizzabili. Ad esempio, nel linguaggio di programmazione D real è un tipo a virgola mobile a 80 bit su x86. Sarebbe sicuro di fare qualcosa di simile:Word Tearing su x86

real[] nums = new real[4]; // Assume new returns a 16-byte aligned block. 
foreach(i; 0..4) { 
    // Create a new thread and have it do stuff and 
    // write results to index i of nums. 
} 

Nota: Lo so che, anche se questo è sicuro, a volte può causare problemi falsi di condivisione con la cache, che porta a rallentare le prestazioni. Tuttavia, per i casi d'uso che ho in mente, le scritture non saranno abbastanza frequenti perché ciò non sia importante nella pratica.

Modifica: non preoccuparti di leggere i valori scritti. L'ipotesi è che ci sia essere la sincronizzazione prima di qualsiasi valore letto. Mi interessa solo la sicurezza di scrivendo in questo modo.

+0

Immagino che stiate osservando le scritture sporche degli indirizzi adiacenti? – BCS

risposta

10

L'x86 ha cache coerenti. L'ultimo processore da scrivere su una linea della cache acquisisce tutto e scrive sulla cache. Ciò garantisce che i valori a byte singolo e a 4 byte scritti sui valori corrispondenti vengano aggiornati in modo atomico.

Questo è diverso da "è sicuro". Se i processori scrivono solo in byte/DWORD "posseduti" da quel processore in base alla progettazione, gli aggiornamenti saranno corretti. In pratica, si desidera che un processore legga valori scritti da altri e che richiede la sincronizzazione .

È anche diverso da "efficiente". Se diversi processori possono scrivere in diversi punti della linea della cache, la riga della cache può ping-pong tra le CPU e questo è molto più costoso che se la linea della cache va a una singola CPU e rimane lì. La regola normale consiste nel mettere i dati specifici del processore nella propria linea di cache. Ovviamente, se stai scrivendo solo con quella parola, solo una volta, e la quantità di lavoro è significativa rispetto a uno spostamento della linea di cache, quindi le tue prestazioni saranno accettabili.

+0

Per quanto riguarda il tuo punto di lettura: l'idea era di riempire un enorme array in parallelo usando qualcosa come la mappa parallela. La funzione di mappatura impiegherebbe la maggior parte del tempo, in modo tale che il tempo dedicato alla scrittura sia trascurabile e le linee della cache sarebbero comunque condivise solo in prossimità dei confini delle unità di lavoro. Prima che tutti i valori vengano riletti da questo array, verrebbe utilizzata una sincronizzazione di qualche tipo. – dsimcha

1

Potrei mancare qualcosa, ma non prevedo alcun problema. l'architettura x86 scrive solo ciò di cui ha bisogno, non esegue alcuna scrittura al di fuori dei valori specificati. Lo snooping della cache gestisce i problemi della cache.

1

Stai chiedendo informazioni specifiche su x86, tuttavia il tuo esempio è in qualche lingua di alto livello. La tua domanda specifica su D può essere risolta solo dalle persone che hanno scritto il compilatore che stai utilizzando, o forse dalle specifiche del linguaggio D. Ad esempio, Java richiede che l'accesso agli elementi dell'array non provochi lacerazione.

Per quanto riguarda x86, l'atomicità delle operazioni è specificata nella Sezione 8.1 di Intel's Software Developer's Manual Volume 3A. Secondo esso, le operazioni di un negozio atomico includono: la memorizzazione di un byte, la memorizzazione di parole allineate alla parola e dword allineate con dword su tutte le CPU x86. Specifica inoltre che su P6 e successive CPU l'accesso non allineato a 16, 32 e 64 bit alla memoria cache all'interno di una linea cache è atomico.