2016-03-26 23 views
14

Ho inciampato non una volta in un termine "non coerenti" e di memoria "coerente" nelChe cos'è la memoria coerente su GPU?

tech papers legati alla grafica programming.I sono alla ricerca di una spiegazione semplice e chiara, ma per lo più trovati documenti 'fondamentali' di Tipo this. Sarei felice di ricevere la risposta in stile laico su quale memoria coerente sia effettivamente presente sulle architetture GPU e su come sia confrontata con altri tipi di memoria (probabilmente non coerenti).

+1

"coerente" significa che se un oggetto dati è accessibile da più agenti (o su più percorsi), ognuno vedrà esattamente lo stesso stato. I due agenti possono essere una CPU e una GPU. L'esempio per due percorsi di lettura può essere tramite cache di trama rispetto alla cache L1. Mantenere la coerenza di solito richiede meccanismi hardware aggiuntivi, ad es. bit per il tracciamento dello stato delle linee della cache MESI o MOESI e possono portare a una quantità significativa di traffico di coerenza per la spedizione dei dati in giro, soprattutto se ci sono molti agenti. – njuffa

+1

La cache di texture in GPU è un tipico esempio di meccanismo "incoerente". Se i dati sottostanti a una mappatura della trama cambiano, qualsiasi contenuto memorizzato nella cache della trama non può essere invalidato o aggiornato, e i successivi accessi alla cache della trama comportano la lettura dei dati non aggiornati. – njuffa

risposta

16

La memoria è memoria. Ma cose diverse possono accedere a quella memoria. La GPU può accedere alla memoria, la CPU può accedere alla memoria, forse altri bit hardware, qualunque sia.

Una cosa particolare ha un accesso "coerente" alla memoria se le modifiche apportate da altri a quella memoria sono visibili al. Ora, potresti pensare che sia follia. Dopotutto, se la memoria è stata cambiata, come potrebbe qualcuno forse non riuscire a vederlo?

In poche parole, cache.

Si scopre che la modifica della memoria è costosa. Quindi facciamo tutto il possibile per evitando cambiando la memoria a meno che non sia assolutamente necessario. Quando si scrive un singolo byte dalla CPU a un puntatore in memoria, la CPU non scrive ancora quel byte. O almeno, non per memoria. Lo scrive su una copia locale di quella memoria chiamata "cache".

Il motivo è che, in generale, le applicazioni non scrivono (o leggono) singoli byte. Hanno maggiori probabilità di scrivere (e leggere) molti byte, in piccoli blocchi. Quindi, se hai intenzione di eseguire un'operazione costosa come un carico di memoria o un archivio, devi caricare o archiviare un grosso frammento di memoria. Quindi memorizzi tutte le modifiche che intendi apportare a un blocco di memoria in una cache, quindi crea una singola scrittura di quel pezzo memorizzato nella cache nella memoria effettiva ad un certo punto nel futuro.

Ma se si dispone di due dispositivi separati che utilizzano la stessa memoria, è necessario assicurarsi che la scrittura di un dispositivo sia visibile ad altri dispositivi. La maggior parte delle GPU non è in grado di leggere la cache della CPU. E la maggior parte dei linguaggi della CPU non ha il supporto a livello di linguaggio per dire "hey, quella roba che ho scritto alla memoria? Voglio davvero che tu la scriva ora nella memoria". Quindi di solito hai bisogno di qualcosa per garantire la visibilità dei cambiamenti.

In Vulkan, la memoria che viene etichettato come "HOST_COHERENT" significa che, se si scrive a che la memoria (tramite un puntatore mappato, dal momento che è l'unico modo Vulkan consente di scrivere direttamente nella memoria), si non lo fai necessità utilizzare funzioni speciali per assicurarsi che la GPU possa vedere tali modifiche. La visibilità della GPU di qualsiasi modifica è garantita. Se questo flag non è disponibile in memoria, è necessario utilizzare le API Vulkan per garantire la coerenza delle regioni specifiche di dati a cui si desidera accedere.

Con la memoria coerente, una delle due cose sta accadendo in termini di hardware. O l'accesso della CPU alla memoria non è memorizzato nella cache in nessuna delle cache della CPU, o la GPU ha accesso diretto alle cache della CPU (forse perché si trova sullo stesso dado delle CPU). Di solito si può dire che quest'ultimo sta accadendo, perché le implementazioni su GPU on-die di Vulkan non si preoccupano di offrire opzioni di memoria non coerenti.

4

Se la memoria è coerente, tutti i thread che accedono a tale memoria devono concordare sullo stato della memoria in ogni momento, ad es .: se il thread 0 legge la posizione di memoria A e il thread 1 legge la stessa posizione contemporaneamente, entrambi i thread dovrebbero leggi sempre lo stesso valore.

Ma se la memoria non è coerente, i thread A e B potrebbero leggere valori diversi.Thread 0 potrebbe pensare che la posizione A contenga un 1, mentre thread pensa che quella posizione contenga un 2. I diversi thread avrebbero una visione incoerente della memoria.

La coerenza è difficile da ottenere con un numero elevato di core. Spesso ogni core deve essere consapevole degli accessi alla memoria da tutti gli altri core. Quindi se hai 4 core in una CPU quad core, la coerenza non è così difficile da ottenere, dato che ogni core deve essere informato sulla memoria che accede agli indirizzi di altri 3 core, ma in una GPU con 16 core, ogni core deve essere reso consapevole di la memoria accede a 15 altri core. I core scambiano dati sul contenuto della loro cache usando i cosiddetti "protocolli di coerenza della cache".

Ecco perché le GPU supportano spesso solo forme di coerenza limitate. Se alcune posizioni di memoria sono di sola lettura o sono accessibili solo da un singolo thread, non è richiesta alcuna coerenza. Se le cache sono piccole e la coerenza non è sempre richiesta ma solo su istruzioni specifiche del programma, è possibile ottenere un comportamento corretto del programma utilizzando i flush della cache prima o dopo specifici accessi alla memoria.

Se il vostro hardware offre sia tipi di memoria coerenti che non coerenti, allora ci si può aspettare che la memoria non coerente sia più veloce, ma se si tenta di eseguire algoritmi paralleli usando questa memoria, falliranno in modi davvero strani.