如何在 OpenCL 中使用固定内存/映射内存

Posted

技术标签:

【中文标题】如何在 OpenCL 中使用固定内存/映射内存【英文标题】:How to use pinned memory / mapped memory in OpenCL 【发布时间】:2014-08-01 06:34:04 【问题描述】:

为了减少我的应用程序从主机到设备的传输时间,我想使用固定内存。 NVIDIA's best practices guide 建议使用以下代码映射缓冲区并写入数据:

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 建议使用对 clEnqueueMapBuffer 和 clEnqueueUnmapBuffer 的调用,而不是对 clEnqueueReadBuffer 或 clEnqueueWriteBuffer 的调用。

使用固定内存/映射内存的正确方法是什么?是否需要使用 enqueueWriteBuffer 写入数据或 enqueueMapBuffer 是否足够?

另外,CL_MEM_ALLOC_HOST_PTR 和 CL_MEM_USE_HOST_PTR 有什么区别?

【问题讨论】:

【参考方案1】:

这是一个有趣的话题,很少有人详细介绍。 我将尝试准确定义它的工作原理。

固定内存是指在主机中存在于设备中的内存,因此可以在这两个内存之间进行 DMA 写入。提高复印性能。 这就是为什么它在缓冲区创建参数中需要CL_MEM_ALLOC_HOST_PTR

另一方面,CL_MEM_USE_HOST_PTR 将使用主机指针来创建缓冲区,规范不清楚这是否可以是固定内存。但一般来说,不应该以这种方式创建固定内存,因为主机指针没有被 OpenCL API 保留,并且不清楚它在内存中的位置。


关于地图/阅读问题。 两个都可以。他们会给出同样的表现。 这两种技术的区别在于:

对于 Map/Unmap:您需要在写入/读取之前进行映射,然后再取消映射。这样可以确保数据的一致性。这些是 API 调用,需要时间来完成并且是异步的。好处是,除了缓冲区对象之外,您不需要持有任何其他东西。 For Map+Read/Write:在创建内存区域时,您需要做一个 Map 并保存指针值。然后,在销毁缓冲区时,您需要先 Unmap 然后销毁它。你需要一直持有buffer+Mapped_Buffer。好消息是您现在可以将clEnqueueRead/Write 指向该映射指针。 API 将等待固定数据保持一致,然后认为已完成。它更易于使用,因为它就像一次完成地图+取消地图。

读/写模式更易于使用,特别适用于重复读取,但不如手动映射选项那样通用,因为您无法编写read only 映射,也无法读取write only 映射。但对于一般用途,读取的变量永远不会被写入,反之亦然。


我的理解是Intel的推荐,是指“使用Map,不是普通的Read/Write”,而不是“在使用Map的时候,不要使用Read/Write over Mapped指针”

您是否通过英特尔硬件检查过此 nVIDIA 建议?我认为它应该可以工作,但是我不知道该操作是否确实是最佳的(如在 AMD 或 nVIDIA HW 中)。

【讨论】:

您需要将 clEnqueueWriteBuffer() 与 Map/Unmap 一起使用,这真的很奇怪。因为当您执行 Map,然后更改主机指针时,您实际上是在更改 CPU 和 GPU 数据。当您进行取消映射时,数据将在 CPU 和 GPU 端之间同步。我不明白您需要在 MAP+change cDataIn 和 UNMAP 之间执行 clEnqueueWriteBuffer。很奇怪……

以上是关于如何在 OpenCL 中使用固定内存/映射内存的主要内容,如果未能解决你的问题,请参考以下文章

如何在 OpenCL 中使用本地内存?

OpenCL 在内存和性能方面,在内核代码中使用用户定义函数的效率如何

内存映射 IO - 它是如何完成的?

openCL缓存对象的传输与映射

openCL缓存对象的传输与映射

OpenCL 本地内存大小和计算单元数量