memory opencl gpu gpgpu data-transfer

memory - Cómo usar la memoria anclada/asignada en OpenCL



gpu gpgpu (1)

Para reducir el tiempo de transferencia de host a dispositivo para mi aplicación, quiero usar la memoria anclada. La guía de mejores prácticas de NVIDIA propone mapear buffers y escribir los datos utilizando el siguiente código:

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);

La guía de optimización de Intel recomienda usar las llamadas a clEnqueueMapBuffer y clEnqueueUnmapBuffer en lugar de las llamadas a clEnqueueReadBuffer o clEnqueueWriteBuffer.

¿Cuál es la forma correcta de usar la memoria anclada / asignada? ¿Es necesario escribir los datos utilizando enqueueWriteBuffer o es enqueueMapBuffer suficiente?

Además, ¿cuál es la diferencia entre CL_MEM_ALLOC_HOST_PTR y CL_MEM_USE_HOST_PTR?


Este es un tema interesante que muy poca gente detalla. Intentaré definir exactamente cómo funciona.

La memoria anclada se refiere a una memoria que, además de estar en el dispositivo, existe en el host, por lo que es posible una escritura DMA entre estas 2 memorias. Aumentar el rendimiento de la copia. Es por eso que necesita CL_MEM_ALLOC_HOST_PTR en los parámetros de creación de búfer.

Por otro lado, CL_MEM_USE_HOST_PTR tomará un puntero de host para la creación del búfer, no está claro por la especificación si esto puede o no puede ser una memoria anclada. Pero, en términos generales, NO se debe fijar la memoria de esta manera, ya que la API de OpenCL no ha reservado el puntero del host y no está claro dónde reside en la memoria.

Respecto a la pregunta Mapa / Leer. Ambos estan bien Y darán el mismo rendimiento. La diferencia entre ambas técnicas es que:

  • Para Map / Unmap : Necesita mapear antes de escribir / leer y des-mapear después. De esa forma se asegura la consistencia de los datos. Estas son llamadas a la API, y toman tiempo para completarse, además de ser asíncronas. Lo bueno es que no es necesario retener ninguna otra cosa en lugar del objeto de búfer.
  • Para Mapa + Lectura / Escritura : en la creación de la zona de memoria, debe hacer un Mapa y guardar el valor del puntero. Luego, en la destrucción del búfer, primero debes desasignar y luego destruirlo. Necesitas mantener buffer+Mapped_Buffer todo el tiempo. Lo bueno es que ahora solo puede hacer clEnqueueRead/Write en la clEnqueueRead/Write en ese puntero asignado. La API esperará a que los datos anclados sean consistentes y luego los considerará finalizados. Es más fácil de usar, ya que es como hacer un mapa + desasignar en una sola toma.

El modo Lectura / Escritura es más fácil de usar, especialmente para lecturas repetitivas, pero no es tan versátil como la opción de mapa manual, ya que NO PUEDE escribir un mapa de read only , ni leer un mapa de write only . Pero para uso general, las variables que se leen nunca se escribirán, y viceversa.

Entiendo que la recomendación de Intel se refiere a "Usar Mapa, no Lectura / Escritura simple" , en lugar de "Cuando se usa Mapa, no use Lectura / Escritura sobre los punteros asignados" .

¿Revisó esta recomendación de nVIDIA sobre Intel HW? Creo que debería funcionar, sin embargo, no sé si realmente la operación sería óptima (como en AMD o nVIDIA HW).