Recherche…


Introduction

Cette rubrique met en évidence différentes manières de placer des données quelque part où votre appareil peut y accéder.

Lecture d'un tableau

Pour lire un tableau de l’appareil vers l’hôte, on appelle

clEnqueueReadBuffer($queue, $memobj, $blocking, $offset, $size, $target, 0, null, null);

La file d'attente $ est la CommandQueue utilisée pour allouer la mémoire sur le périphérique. $ Memobj contient l'adresse de la mémoire de l'appareil, $ offset et $ size définissent davantage d'où et combien de données sont copiées. $ Target est un pointeur sur la mémoire hôte dans laquelle les données seront stockées. La cible $ doit être allouée et avoir la taille appropriée.

Lire une texture

Lire une image est presque comme lire un tableau. La seule différence étant que la taille et le décalage doivent être tridimensionnels.

clEnqueueReadImage($queue, $memobj, $blocking, $offset, $size, $stride, $slice_pitch, $target, 0, null, null);

Le stride $ définit le nombre d'octets d'une ligne. Normalement, il ne s'agit que de largeur * (octets par pixel), mais quelqu'un pourrait vouloir changer cela pour aligner les données avec les banques de mémoire. La même chose vaut pour $ slice_pitch, mais seulement que cette valeur est pour la troisième dimension.

Écrire une texture 2D

Pour copier une texture sur le périphérique, deux étapes sont nécessaires.

  1. Allouer la mémoire sur l'appareil
  2. Copier l'image sur le périphérique
  _mem = clCreateImage2D($context, $mem_flags, $image_format, $width, $height, $stride, $source, &err);

Les $ mem_flags définissent comment la mémoire est allouée. Il peut être en lecture seule, écriture seule ou les deux. De plus, vous pouvez définir où et comment la mémoire est allouée. $ width, $ height et $ stride sont assez explicites.

Si vos mem_flags copient les données, vous avez terminé. Si vous souhaitez le faire manuellement ultérieurement, vous devez appeler une autre fonction lorsque vous êtes prêt.

err = clEnqueueWriteImage($queue, _mem, $blocking, $offset, $size, $stride, $slice_pitch, $source, 0, null, null);

Les valeurs $ offset et $ size définissent la région d'image à copier dans la mémoire cible. Le stride $ définit le nombre d'octets d'une ligne. Normalement, il ne s'agit que de largeur * (octets par pixel), mais quelqu'un pourrait vouloir changer cela pour aligner les données avec les banques de mémoire. La même chose vaut pour $ slice_pitch, mais seulement que cette valeur est pour la troisième dimension. $ Stride et $ slice_pitch doivent correspondre à vos données d'entrée.

Drapeaux de mémoire

Lorsque vous allouez de la mémoire, vous avez le choix entre différents modes:

  • Mémoire en lecture seule
  • Ecrire uniquement de la mémoire
  • Lecture / écriture de mémoire

La mémoire en lecture seule est allouée dans la région de mémoire __constant, tandis que les deux autres sont allouées dans la région __global normale.

En plus de l'accessibilité, vous pouvez définir où votre mémoire est allouée.

  • Non spécifié: votre mémoire est allouée sur la mémoire de l'appareil comme prévu. Le pointeur $ source peut être défini sur null.
  • CL_MEM_USE_HOST_PTR: Ceci indique au périphérique que les données se trouvent dans la mémoire vive du système et ne doivent pas être déplacées. Au lieu de cela, les données sont manipulées directement dans le ram.
  • CL_MEM_COPY_HOST_PTR: Indique à l'appareil de copier toutes les valeurs à l'adresse donnée dans la mémoire de l'appareil ou, à l'aide de CL_MEM_ALLOC_HOST_PTR, dans une région de mémoire distincte dans ram ram du système.
  • CL_MEM_ALLOC_HOST_PTR: Indique à l'appareil d'allouer de l'espace au ram du système. S'il est utilisé comme paramètre unique, le pointeur $ source peut être défini sur null.

En termes de vitesse, l'accès à la mémoire globale de l'appareil est le plus rapide. Mais vous devez également l'appeler deux fois pour copier des données. L'utilisation du pointeur hôte est la plus lente, tandis que Alloc_host_ptr offre une vitesse plus élevée.

Lorsque vous utilisez use_host_ptr, le périphérique fait exactement cela: il utilise vos données dans le ram du système, qui est bien sûr paginé par l’OS. Donc, chaque appel de mémoire doit passer par le processeur pour gérer les erreurs de page potentielles. Lorsque les données sont disponibles, le processeur les copie dans la mémoire épinglée et les transmet au contrôleur DMA en utilisant de précieux cycles d'horloge CPU. Au contraire, alloc_host_ptr alloue de la mémoire épinglée dans le ram du système. Cette mémoire est placée en dehors du mécanisme de pages d'échange et sa disponibilité est donc garantie. Par conséquent, le périphérique peut ignorer entièrement le processeur lorsqu’il accède à ram système et utiliser DMA pour copier rapidement les données sur le périphérique.

Ecrire un tableau

L'écriture d'un tableau se fait en deux étapes:

  1. Allouer la mémoire
  2. Copier les données

Pour allouer la mémoire, un simple appel à

_mem = clCreateBuffer($queue, $mem_flags, $size, $host_ptr, &err);

est assez. Si vous avez décidé de copier le pointeur hôte via les mem_flags, vous avez terminé. Sinon, vous pouvez copier les données à tout moment avec

err = clEnqueueWriteBuffer($queue, _mem, $blocking, $offset, $size, $source, 0, null, null);


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow