Buscar..


Introducción

Este tema destaca diferentes formas de colocar datos en algún lugar donde su dispositivo pueda acceder a ellos.

Leyendo una matriz

Para leer una matriz del dispositivo al host, se llama

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

La cola $ es el CommandQueue que se usó para asignar la memoria en el dispositivo. El $ memobj contiene la dirección a la memoria del dispositivo, $ desplazamiento y $ tamaño definen con más precisión de dónde y cuántos datos se copian. El $ target es un puntero a la memoria del host donde se almacenarán los datos. El $ target debe asignarse y tener un tamaño adecuado.

Leyendo una textura

Leer una imagen es casi como leer una matriz. La única diferencia es que el tamaño y la compensación deben ser tridimensionales.

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

El $ stride define cuántos bytes tiene una fila. Normalmente esto es solo ancho * (bytes por píxel), pero alguien podría querer cambiarlo para alinear los datos con los bancos de memoria. Lo mismo ocurre con $ slice_pitch, solo que este valor es para la tercera dimensión.

Escribiendo una textura 2D

Para copiar una textura al dispositivo hay dos pasos necesarios.

  1. Asignar la memoria en el dispositivo.
  2. Copia la imagen al dispositivo.
  _mem = clCreateImage2D($context, $mem_flags, $image_format, $width, $height, $stride, $source, &err);

Las $ mem_flags definen cómo se asigna la memoria. Puede ser de solo lectura, solo escritura o ambos. Además, puede definir dónde y cómo se asigna la memoria. $ width, $ height y $ stride son bastante explicativos.

Si su mem_flags copia los datos, ya está. Si desea hacerlo manualmente en un momento posterior, deberá llamar a otra función cuando esté listo.

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

El valor $ offset y $ size definen la región de la imagen que desea copiar en la memoria de destino. El $ stride define cuántos bytes tiene una fila. Normalmente esto es solo ancho * (bytes por píxel), pero alguien podría querer cambiarlo para alinear los datos con los bancos de memoria. Lo mismo ocurre con $ slice_pitch, solo que este valor es para la tercera dimensión. Tanto $ stride como $ slice_pitch tienen que coincidir con sus datos de entrada.

Banderas de memoria

Al asignar Memoria, tiene la opción de elegir entre diferentes modos:

  • Memoria de sólo lectura
  • Escribe solo memoria
  • Memoria de lectura / escritura

La memoria de solo lectura se asigna en la región de memoria constante, mientras que las otras dos se asignan en la región global global.

Además de la accesibilidad, puede definir dónde se asigna su memoria.

  • No especificado: su memoria está asignada en la memoria del dispositivo como cabría esperar. El puntero $ source se puede establecer en nulo.
  • CL_MEM_USE_HOST_PTR: Esto le dice al dispositivo que los datos están en la RAM del sistema y no deben ser movidos. En su lugar, los datos se manipulan directamente en el ram.
  • CL_MEM_COPY_HOST_PTR: Le dice al dispositivo que copie todos los valores de la dirección dada a la memoria del dispositivo o, usando CL_MEM_ALLOC_HOST_PTR, a una región de memoria separada en la memoria ram del sistema.
  • CL_MEM_ALLOC_HOST_PTR: Le dice al dispositivo que asigne espacio en el ram del sistema. Si se utiliza como único parámetro, el puntero $ source se puede establecer en nulo.

En cuanto a la velocidad, el acceso a la memoria global del dispositivo es el más rápido. Pero también necesitas llamarlo dos veces para copiar datos. Usar el puntero del Host es el más lento, mientras que Alloc_host_ptr ofrece una velocidad más alta.

Cuando se usa use_host_ptr, el dispositivo hace exactamente eso: usa sus datos en el ram del sistema, que por supuesto es paginado por el sistema operativo. Por lo tanto, cada llamada de memoria tiene que pasar por la CPU para manejar posibles resultados de página. Cuando los datos están disponibles, la CPU los copia en la memoria anclada y los pasa al controlador DMA utilizando preciados ciclos de reloj de CPU. Por el contrario, alloc_host_ptr asigna memoria anclada en el ram del sistema. Esta memoria se coloca fuera del mecanismo de intercambio de páginas y, por lo tanto, tiene una disponibilidad garantizada. Por lo tanto, el dispositivo puede omitir la CPU por completo al acceder al ram del sistema y utilizar DMA para copiar rápidamente los datos al dispositivo.

Escribiendo una matriz

Escribir una matriz consiste en dos pasos:

  1. Asignación de la memoria.
  2. Copiando los datos

Para asignar la memoria, una simple llamada a

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

es suficiente. Si decidió copiar el puntero del host a través de mem_flags, habrá terminado. De lo contrario, puede copiar los datos cuando lo desee con

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


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow