2014-06-11 3 views
15

Afin de réduire le temps de transfert entre l'hôte et l'appareil pour mon application, je souhaite utiliser la mémoire épinglée. NVIDIA's best practices guide propose des tampons de cartographie et de l'écriture des données en utilisant le code suivant:Comment utiliser la mémoire épinglée/la mémoire mappée dans 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 recommande d'utiliser des appels à clEnqueueMapBuffer et clEnqueueUnmapBuffer au lieu des appels à clEnqueueReadBuffer ou clEnqueueWriteBuffer.

Quelle est la bonne façon d'utiliser la mémoire épinglée/la mémoire mappée? Est-il nécessaire d'écrire les données en utilisant enqueueWriteBuffer ou est-ce que enqueueMapBuffer est suffisant?

De même, quelle est la différence entre CL_MEM_ALLOC_HOST_PTR et CL_MEM_USE_HOST_PTR?

Répondre

10

Ceci est un sujet intéressant que très peu de gens détaillent. Je vais essayer de définir exactement comment cela fonctionne.

La mémoire épinglée fait référence à une mémoire qui, tout en étant dans le périphérique, existe dans l'hôte, de sorte qu'une écriture DMA est possible entre ces 2 mémoires. Augmenter les performances de copie. C'est pourquoi il a besoin de CL_MEM_ALLOC_HOST_PTR dans les paramètres de création du tampon.

D'autre part, CL_MEM_USE_HOST_PTR prendra un pointeur d'hôte pour la création de tampon, il n'est pas clair par la spécification si cela peut ou ne peut pas être une mémoire épinglée. Mais d'une manière générale, il ne devrait PAS être créé de cette façon, car le pointeur de l'hôte n'a pas été réservé par l'API OpenCL et ne sait pas où il réside en mémoire.


En ce qui concerne la question Map/Read. Les deux sont ok. Et ils vont donner la même performance. La différence entre les deux techniques est que:

  • Pour Carte/Unmap: Vous devez mapper avant d'écrire/lecture et unmap après. De cette façon, vous assurez la cohérence des données. Ce sont des appels d'API, et prennent du temps à compléter tout en étant asynchrones. La bonne chose, c'est que vous n'avez pas besoin de tenir autre chose que l'objet tampon.
  • Pour Map + Lecture/écriture: Lors de la création de la zone mémoire, vous devez créer une carte et enregistrer la valeur du pointeur. Ensuite, lors de la destruction de la mémoire tampon, vous devez d'abord démapper et ensuite détruire. Vous devez maintenir buffer+Mapped_Buffer tout le long. La bonne chose est que vous pouvez maintenant juste clEnqueueRead/Write à ce pointeur mappé. L'API attendra que les données épinglées soient cohérentes, puis considérera que c'est fait. C'est plus facile à utiliser, car c'est comme faire une carte + unmap en une fois.

Le mode lecture/écriture est plus facile à utiliser, spécialement pour les lectures répétitives, mais pas aussi polyvalent que l'option manuelle de la carte, puisque vous ne pouvez pas écrire une carte read only, ni lire une carte write only. Mais pour une utilisation générale, les variables qui sont lues ne seront jamais écrites, et vice versa.


Ma compréhension est que la recommandation Intel, fait référence à « Utiliser la carte, et non simplement lecture/écriture », plutôt que « Lorsque vous utilisez la carte, ne pas utiliser de lecture/écriture sur des pointeurs cartographiées » .

Avez-vous vérifié cette recommandation de nVIDIA sur Intel HW? Je pense que cela devrait fonctionner, mais je ne sais pas si en effet l'opération serait optimale (comme dans AMD ou nVIDIA HW).

+0

Il est vraiment étrange que vous deviez utiliser clEnqueueWriteBuffer() avec Map/Unmap. Depuis que vous faites la carte, puis changez le pointeur d'hôte, vous changez réellement les données de processeur et de GPU. Lorsque vous effectuez l'unmap, les données seront synchronisées entre le CPU et le côté GPU. Je ne comprends pas la nécessité pour vous d'effectuer un clEnqueueWriteBuffer entre MAP + modifier cDataIn et UNMAP. Très étrange... –

Questions connexes