2014-06-11 24 views
15

Per ridurre il tempo di trasferimento da host a dispositivo per la mia applicazione, desidero utilizzare la memoria bloccata. NVIDIA's best practices guide propone buffer di mappatura e di scrittura dei dati utilizzando il seguente codice:Come utilizzare la memoria bloccata/memoria mappata in OpenCL

cDataIn = (unsigned char*)clEnqueueMapBuffer(cqCommandQue, cmPinnedBufIn, CL_TRUE,CL_MAP_WRITE, 0, memSize, 0, NULL, NULL, NULL); 

for(unsigned int i = 0; i < memSize; i++) 
{ 
    cDataIn[i] = (unsigned char)(i & 0xff); 
} 

clEnqueueWriteBuffer(cqCommandQue, cmDevBufIn, CL_FALSE, 0, 
szBuffBytes, cDataIn, 0, NULL, NULL); 

Intel's optimization guide raccomanda di utilizzare le chiamate a clEnqueueMapBuffer e clEnqueueUnmapBuffer invece di chiamate verso clEnqueueReadBuffer o clEnqueueWriteBuffer.

Qual è il modo corretto di utilizzare la memoria bloccata/la memoria mappata? È necessario scrivere i dati usando enqueueWriteBuffer o è sufficiente enqueueMapBuffer?

Inoltre, qual è la differenza tra CL_MEM_ALLOC_HOST_PTR e CL_MEM_USE_HOST_PTR?

risposta

10

Questo è un argomento interessante che i dettagli delle persone molto poco. Proverò a definire esattamente come funziona.

La memoria bloccata si riferisce a una memoria che, oltre ad essere nel dispositivo, esiste nell'host, quindi è possibile una scrittura DMA tra queste 2 memorie. Aumentare le prestazioni di copia. Ecco perché ha bisogno di CL_MEM_ALLOC_HOST_PTR nei parametri di creazione del buffer.

D'altra parte, CL_MEM_USE_HOST_PTR prenderà un puntatore host per la creazione del buffer, non è chiaro dalla specifica se questa può o non può essere una memoria bloccata. Ma in generale, NON dovrebbe essere la memoria bloccata creata in questo modo, dal momento che il puntatore dell'host non è stato prenotato dall'API OpenCL e non è chiaro dove risiede in memoria.


Informazioni sulla mappa/Leggi domanda. Entrambi sono ok. E daranno la stessa performance. La differenza tra le due tecniche è che:

  • per la mappa/Unmap: È necessario mappare prima di scrivere/leggere e unmap dopo. In questo modo garantisci la coerenza dei dati. Queste sono chiamate API e richiedono tempo per essere completate e asincrone. La cosa buona è che non è necessario tenere altre cose piuttosto che l'oggetto buffer.
  • Per mappa + lettura/scrittura: Al momento della creazione della zona di memoria è necessario eseguire una mappa e salvare il valore del puntatore. Quindi, alla distruzione del buffer, è necessario prima rimuovere Unmap e quindi distruggerlo. È necessario tenere premuto buffer+Mapped_Buffer per tutto il tempo. La cosa buona è che ora puoi solo aggiungere clEnqueueRead/Write a quel puntatore mappato. L'API attenderà che i dati aggiunti siano coerenti e quindi considerino fatto. È più facile da usare, dato che è come fare una mappa + unmap in un colpo solo.

La modalità di lettura/scrittura è più facile da usare, specialmente per ripetitivo legge, ma non è così versatile come l'opzione di carta manuale, dal momento che non può scrivere una mappa read only, né leggere una mappa write only. Ma per uso generale le variabili che vengono lette non verranno mai scritte e viceversa.


mia comprensione è che la raccomandazione di Intel, si riferisce a "Usa Mappa, non semplice lettura/scrittura", piuttosto che "Quando si utilizza Mappe, non utilizzare lettura/scrittura su puntatori mappate" .

Hai controllato questa raccomandazione di NVIDIA su Intel HW? Penso che dovrebbe funzionare, tuttavia non so se effettivamente l'operazione sarebbe ottimale (come in AMD o NVIDIA HW).

+0

è davvero strano che sia necessario utilizzare clEnqueueWriteBuffer() insieme a Map/Unmap. Da quando si esegue la mappatura e quindi si modifica il puntatore dell'host, si stanno effettivamente modificando i dati della CPU e della GPU. Quando si esegue l'unmap, i dati verranno sincronizzati tra CPU e GPU. Non capisco la necessità per voi di eseguire un clEnqueueWriteBuffer tra MAP + modificare cDataIn e UNMAP. Molto strano... –

Problemi correlati