2013-06-13 16 views
7

Sto progettando un set di funzioni matematiche e le implemento in entrambe le versioni CPU e GPU (con CUDA).Memoria CUDA per tabelle di ricerca

Alcune di queste funzioni sono basate su tabelle di ricerca. La maggior parte dei tavoli prende 4KB, alcuni di loro un po 'di più. Le funzioni basate sulle tabelle di ricerca prendono un input, selezionano una o due voci della tabella di ricerca e quindi calcolano il risultato interpolando o applicando tecniche simili.

La mia domanda è ora: dove devo salvare queste tabelle di ricerca? Un dispositivo CUDA ha molte posizioni per la memorizzazione dei valori (memoria globale, memoria costante, memoria texture, ...). Ammesso che ogni tabella possa essere letta contemporaneamente da più thread e che i valori di input, e quindi gli indici di ricerca, possano essere completamente non correlati tra i thread di ogni warp (con conseguente accesso non correlato alla memoria), quale memoria fornisce l'accesso più veloce?

Aggiungo che il contenuto di queste tabelle è precalcolato e completamente costante.

EDIT

Giusto per chiarire: ho bisogno di memorizzare circa 10 diverse tabelle 4KB di ricerca. In ogni caso sarebbe bello sapere se la soluzione come per questo caso sarebbe la stessa per il caso con, ad es. 100 tabelle 4KB o con ad es. 10 tabelle di ricerca 16KB.

+4

La cache costante è intesa per il caso di trasmissione, cioè l'accesso attraverso un ordito è uniforme. Funzionerà se tutti i thread nel warp accedono a posizioni diverse ma le prestazioni ne risentono. La memoria condivisa è veloce ed è 48KB, quindi è una buona misura, ma potrebbe essere necessario per altri scopi, o il tuo codice fa parte di una libreria dove non funziona bene. Se non è possibile utilizzare la memoria condivisa, suggerirei trame. Potrebbe essere preferibile non utilizzare alcuna tabella sulla GPU (vedi anche la libreria matematica CUDA), poiché i FLOPS aumentano più rapidamente della larghezza di banda della memoria tra le generazioni di GPU. – njuffa

+0

Grazie, njuffa, per la chiara spiegazione. La mia unica domanda riguarda la memoria condivisa. Se ricordo bene, questa memoria è condivisa tra thread nello stesso ordito. Quindi, dovrei replicare i miei tavoli su tutti gli orditi? E le tabelle saranno persistenti dopo la fine del kernel? – Spiros

+2

La memoria condivisa è condivisa tra tutti i thread in un blocco thread. Quindi temo che con un totale di 40 KB di memoria della tabella il tuo codice sarebbe limitato a un singolo blocco di thread per SM.Nella maggior parte dei casi è meglio avere almeno due blocchi di thread in esecuzione, quindi è consigliabile prendere in considerazione l'utilizzo di uno schema misto in cui alcune tabelle sono memorizzate nella memoria condivisa (quelle con il maggior numero di accessi) e altre nella memoria texture. La memoria texture ha anche il vantaggio di poter ottenere un'interpolazione lineare (a bassa precisione) gratuitamente. Che tipo di funzioni matematiche stai implementando che richiedono tabelle grandi? – njuffa

risposta

2

La memoria di trama (ora denominata cache di sola lettura) sarebbe probabilmente una scelta da esplorare, anche se non per i benefici dell'interpolazione. Supporta letture a 32 bit senza leggere oltre questa quantità. Tuttavia, sei limitato a 48K in totale. Per Kepler (calcolo 3.x) questo è abbastanza semplice da programmare ora.

La memoria globale, a meno che non la si configuri in modalità a 32 bit, trascinerà spesso 128 byte per ogni thread, moltiplicando enormemente i dati effettivamente necessari dalla memoria man mano che (apparentemente) non si riesce a convogliare gli accessi alla memoria. Quindi la modalità a 32 bit è probabilmente quella che ti serve se vuoi usare più di 48K (hai menzionato 40K).

Pensando a coalescenza, se si dovesse accedere a un insieme di valori in serie da queste tabelle, si potrebbe essere in grado di interlacciare le tabelle in modo tale che tali combinazioni possano essere raggruppate e lette come una lettura di 64 o 128 bit per thread. Ciò significherebbe che le letture a 128 byte dalla memoria globale potrebbero essere utili.

Il problema che si ha è che si sta limitando la larghezza di banda della memoria della soluzione utilizzando le tabelle di ricerca. Cambiare la dimensione della cache L1 (su Fermi/calcolo 2.x) a 48K probabilmente farà una differenza significativa, specialmente se non stai utilizzando gli altri 32K di memoria condivisa. Prova la memoria texture e poi la memoria globale in modalità a 32 bit e vedi quale funziona meglio per il tuo algoritmo. Infine, scegli una scheda con una buona larghezza di banda di memoria se hai una scelta sull'hardware.

Problemi correlati