Qual è il significato degli accessi alla memoria "non temporali" in x86


123

Questa è una domanda di basso livello. Nell'assembly x86 ci sono due istruzioni SSE:

MOVDQA xmmi, m128

e

MOVNTDQA xmmi, m128

Il Manuale dello sviluppatore del software IA-32 dice che NT in MOVNTDQA sta per Non-Temporal , e che altrimenti è lo stesso di MOVDQA.

La mia domanda è: cosa significa non temporale ?


6
Notare che SSE4.1 MOVNTDQA xmmi, m128è un carico NT, mentre tutte le altre istruzioni NT sono archivi, ad eccezione di prefetchnta. La risposta accettata qui sembra parlare solo di negozi. Questo è quello che sono riuscito a trovare sui carichi di NT . TL: DR: si spera che la CPU faccia qualcosa di utile con il suggerimento NT per ridurre al minimo l'inquinamento della cache, ma non sovrascrive la semantica fortemente ordinata della memoria WB "normale", quindi devono usare la cache.
Peter Cordes,

5
Aggiornamento: i caricamenti di NT potrebbero non fare nulla di utile tranne che sulle regioni di memoria UCSW sulla maggior parte delle CPU (ad esempio la famiglia Intel SnB). NT / streaming negozi sicuramente lavorare sulla memoria normale, però.
Peter Cordes

4
@ Peter: Intendi la memoria USWC, giusto? Non ho mai sentito parlare della memoria UCSW o USWC prima. Cercare su Google l'acronimo sbagliato non è stato utile :-)
Andrew Bainbridge

4
@ AndrewBainbridge: Sì, l'attributo del tipo di memoria WC. Uncacheable Speculative Write-Combining. Penso di aver scritto in maiuscolo UnCacheable e di ricordare che doveva essere lungo 4 lettere. : P
Peter Cordes

Risposte:


147

Le istruzioni SSE non temporali (MOVNTI, MOVNTQ, ecc.), Non seguono le normali regole di coerenza della cache. Pertanto le memorie non temporali devono essere seguite da un'istruzione SFENCE affinché i loro risultati possano essere visti da altri processori in modo tempestivo.

Quando i dati vengono prodotti e non (immediatamente) consumati di nuovo, il fatto che le operazioni di archiviazione in memoria leggano prima una riga completa della cache e quindi modificano i dati memorizzati nella cache è dannoso per le prestazioni. Questa operazione spinge i dati fuori dalle cache che potrebbero essere nuovamente necessari a favore di dati che non verranno utilizzati a breve. Ciò è particolarmente vero per strutture di dati di grandi dimensioni, come le matrici, che vengono riempite e quindi utilizzate in seguito. Prima che l'ultimo elemento della matrice venga riempito, la dimensione pura elimina i primi elementi, rendendo inefficace il caching delle scritture.

Per questa e altre situazioni simili, i processori forniscono supporto per operazioni di scrittura non temporali. Non temporale in questo contesto significa che i dati non verranno riutilizzati presto, quindi non c'è motivo di memorizzarli nella cache. Queste operazioni di scrittura non temporali non leggono una riga della cache e quindi la modificano; invece, il nuovo contenuto viene scritto direttamente in memoria.

Fonte: http://lwn.net/Articles/255364/


15
Bella risposta, vorrei solo far notare che sul tipo di processore con istruzioni NT, anche con un'istruzione non non temporale (cioè un'istruzione normale), la cache di linea non viene "letta e poi modificata". Per una normale istruzione che scrive su una riga che non è nella cache, una riga è riservata nella cache e una maschera indica quali parti della riga sono aggiornate. Questa pagina web lo chiama "nessuno stallo nel negozio": ptlsim.org/Documentation/html/node30.html . Non sono riuscito a trovare riferimenti più precisi, ne ho sentito parlare solo da ragazzi il cui compito è implementare simulatori di processori.
Pascal Cuoq

2
In realtà, ptlsim.org è un sito web che parla di un simulatore di processore accurato al ciclo, esattamente lo stesso tipo di cose che stanno facendo i ragazzi che mi hanno detto di "nessuno stallo in negozio". Farei
Pascal Cuoq

1
Dalle risposte e dai commenti qui stackoverflow.com/questions/44864033/… sembra che SFENCEpotrebbe non essere necessario. Almeno nello stesso thread. Potresti anche guardare?
Serge Rogatch

1
@SergeRogatch dipende dallo scenario di cui stai parlando, ma sì, ci sono scenari in cui sfenceè richiesto per i negozi NT, mentre non è mai richiesto solo per i negozi normali. I negozi NT non sono ordinati rispetto ad altri negozi (NT o meno), come visto da altri thread , senza un'estensione sfence. Per le letture dallo stesso thread che ha fatto i negozi, tuttavia, non è mai necessario sfence: un dato thread vedrà sempre i propri negozi nell'ordine del programma, indipendentemente dal fatto che siano negozi NT o meno.
BeeOnRope

40

Espo è praticamente azzeccato. Volevo solo aggiungere i miei due centesimi:

La frase "non temporale" significa mancanza di località temporale. Le cache sfruttano due tipi di località: spaziale e temporale e, utilizzando un'istruzione non temporale, segnali al processore che non ti aspetti che l'elemento di dati venga utilizzato nel prossimo futuro.

Sono un po 'scettico sull'assembly codificato a mano che utilizza le istruzioni di controllo della cache. Nella mia esperienza queste cose portano a bug più dannosi di qualsiasi aumento delle prestazioni effettive.


domanda sull '"assembly codificato manualmente che utilizza le istruzioni di controllo della cache". So che hai detto esplicitamente "codificato a mano" che dire di qualcosa come un JavaVM. È un caso d'uso migliore? JavaVM / Compiler ha analizzato il comportamento statico e dinamico del programma e utilizza queste istruzioni non temporali.
Pat

4
Lo sfruttamento delle proprietà di località note (o della loro mancanza) del dominio, dell'algoritmo o dell'applicazione problematica non dovrebbe essere evitato. Evitare l'inquinamento della cache è davvero un'attività di ottimizzazione molto interessante ed efficace. Inoltre, perché l'avversione verso l'assemblea? Sono disponibili enormi quantità di opportunità di guadagno sulle quali un compilatore non può capitalizzare
awdz9nld

5
È decisamente vero che un programmatore esperto di basso livello può superare un compilatore per kernel di piccole dimensioni. Questo è ottimo per pubblicare articoli e post sui blog e ho fatto entrambi. Sono anche ottimi strumenti didattici e aiutano a capire cosa sta "realmente" succedendo. Nella mia esperienza, però, in pratica, dove hai un sistema reale con molti programmatori che ci lavorano e la correttezza e la manutenibilità sono importanti, il vantaggio della codifica di basso livello è quasi sempre superato dai rischi.
Pramod

4
@Pramod lo stesso argomento si generalizza facilmente all'ottimizzazione in generale e non è realmente nell'ambito della discussione - chiaramente quel trade-off è già stato considerato o comunque ritenuto irrilevante dato che stiamo già parlando di istruzioni non temporali
awdz9nld

7

Secondo il Manuale dello sviluppatore del software per le architetture Intel® 64 e IA-32, Volume 1: Architettura di base, capitolo "Programmazione con Intel Streaming SIMD Extensions (Intel SSE)":

Memorizzazione nella cache di dati temporali e non temporali

I dati a cui fa riferimento un programma possono essere temporali (i dati verranno riutilizzati) o non temporali (i dati verranno referenziati una volta e non saranno riutilizzati nell'immediato futuro). Ad esempio, il codice del programma è generalmente temporale, mentre i dati multimediali, come l'elenco di visualizzazione in un'applicazione grafica 3D, sono spesso non temporali. Per fare un uso efficiente delle cache del processore, è generalmente desiderabile memorizzare nella cache i dati temporali e non memorizzare nella cache i dati non temporali. Il sovraccarico delle cache del processore con dati non temporali viene talvolta definito "inquinamento delle cache". Le istruzioni di controllo della cache SSE e SSE2 consentono a un programma di scrivere dati non temporali in memoria in un modo che riduce al minimo l'inquinamento delle cache.

Descrizione del carico non temporale e istruzioni di memorizzazione. Fonte: manuale per sviluppatori di software per architetture Intel 64 e IA-32, volume 2: riferimento al set di istruzioni

LOAD (MOVNTDQA — Carica suggerimento allineato non temporale a doppia parola quadrupla)

Carica una doppia parola quadrupla dall'operando di origine (secondo operando) all'operando di destinazione (primo operando) utilizzando un suggerimento non temporale se la sorgente di memoria è il tipo di memoria WC (write combination) [...]

[...] il processore non legge i dati nella gerarchia della cache, né recupera la riga della cache corrispondente dalla memoria nella gerarchia della cache.

Si noti che, come commenta Peter Cordes, non è utile sulla normale memoria WB (write-back) sui processori correnti perché il suggerimento NT viene ignorato (probabilmente perché non ci sono prefetcher HW compatibili con NT) e si applica la semantica di caricamento fortemente ordinata . prefetchntapuò essere utilizzato come carico che riduce l'inquinamento dalla memoria WB

STORE (MOVNTDQ: archivia interi compressi utilizzando un suggerimento non temporale)

Sposta gli interi compressi nell'operando di origine (secondo operando) nell'operando di destinazione (primo operando) utilizzando un suggerimento non temporale per impedire la memorizzazione nella cache dei dati durante la scrittura in memoria.

[...] il processore non scrive i dati nella gerarchia della cache, né recupera la riga della cache corrispondente dalla memoria nella gerarchia della cache.

Utilizzando la terminologia definita in Criteri e prestazioni di scrittura della cache , possono essere considerati come write-around (no-write-allocate, no-fetch-on-write-miss).

Infine, potrebbe essere interessante rivedere le note di John McAlpin sui negozi non temporali .


3
SSE4.1 MOVNTDQAfa qualcosa di speciale solo sulle regioni di memoria WC (combinazione di scrittura non memorizzabile nella cache), ad esempio la RAM video. Non è affatto utile sulla normale memoria WB (write-back) sull'HW corrente, il suggerimento NT viene ignorato e si applica la semantica di carico fortemente ordinata. prefetchntapuò essere utile, tuttavia, come un carico che riduce l' inquinamento dalla memoria del WB. Le attuali architetture x86 supportano carichi non temporali (dalla memoria "normale")? .
Peter Cordes

2
È corretto, gli archivi NT funzionano bene sulla memoria WB e sono debolmente ordinati e di solito sono una buona scelta per scrivere ampie regioni di memoria. Ma i carichi NT non lo sono. Il manuale x86 su carta consente al suggerimento NT di fare qualcosa per i carichi dalla memoria WB, ma nelle attuali CPU non fa nulla . (Probabilmente perché non ci sono prefetcher HW compatibili con NT.)
Peter Cordes

Ho aggiunto le informazioni pertinenti alla risposta. Grazie mille.
chus

1
@LewisKelsey: i negozi NT hanno la precedenza sul tipo di memoria. Ecco perché possono essere ordinati debolmente sulla memoria WB. L'effetto principale è evitare le RFO (apparentemente inviano un invalidato che cancella anche altre linee sporche quando raggiungono mem). Possono anche diventare visibili fuori ordine, quindi non devono aspettare fino a quando un precedente archivio di cache-miss (normale) non ha eseguito il commit o fino a quando un precedente caricamento di cache-miss non ottiene i dati. cioè il tipo di collo di bottiglia richiesto in La memoria all'esterno di ogni core è sempre concettualmente piatta / uniforme / sincrona in un sistema multiprocessore? .
Peter Cordes

1
@LewisKelsey: una macchina per l'ordinazione della memoria azzerata potrebbe eliminare qualsiasi carico da un archivio UC che non avrebbe dovuto essere eseguito in anticipo, se necessario. Oltre a questo, l'ordine di commit non entra in gioco fino a quando il negozio non si ritira dal back-end fuori servizio. Ciò non può accadere finché non è stato eseguito l'uop store-address, a quel punto è possibile controllare il tipo di memoria per l'indirizzo. Un uop store-address controlla il TLB quando viene eseguito; è così che le CPU possono rilevare i negozi in errore prima che si ritirino. Non può aspettare che la voce SB sia pronta per il commit su L1d; a quel punto l'esecuzione è passata.
Peter Cordes
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.