OpenCL中的内存管理

5
当我开始使用OpenCL编程时,我使用以下方法向我的内核提供数据:
cl_mem buff = clCreateBuffer(cl_ctx, CL_MEM_READ_WRITE, object_size, NULL, NULL);
clEnqueueWriteBuffer(cl_queue, buff, CL_TRUE, 0, object_size, (void *) object, NULL, NULL, NULL);

显然,这要求我将我的数据分成块,确保每个块都能适应设备内存。在执行计算后,我会使用clEnqueueReadBuffer()读出数据。然而,有一段时间我意识到我可以只使用以下行:

cl_mem buff = clCreateBuffer(cl_ctx, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, object_size, (void*) object, NULL);

当执行此操作时,数据的分区变得过时了。令我惊讶的是,性能得到了极大的提升。这是我不理解的事情。据我所知,使用主机指针时,设备内存作为缓存工作,但所有数据仍然需要被复制到其中进行处理,一旦完成后再复制回主内存。当使用显式复制(clEnqueRead/WriteBuffer)时,为什么会慢一个数量级,而在我看来,它应该基本相同?我有什么遗漏吗?
谢谢。
2个回答

3

是的,你忘记在clEnqueueWriteBuffer调用中加入CL_TRUE。这会使写操作变成阻塞式的,也就是说在复制过程中CPU会被暂停一段时间。如果使用主机指针,OpenCL实现可以通过异步方式进行"优化",这样整体性能会更好。

需要注意的是,这取决于CL实现,不能保证其速度更快/相等/更慢。


我知道clEnqueueRead/WriteBuffer上的阻塞标志。然而,当我进行测量时,我使用了clFinish(至少我非常确定我使用了),这应该具有与阻塞标志相同的效果,对吗?也就是说,当然,只有在处理相同数量的数据时才会产生这种效果。嗯,也许CL实现足够聪明,可以省略未被访问的对象部分(约70%)...无论如何,谢谢! - VHristov

2
在某些情况下,CPU 和 GPU 可以共享同一物理 DRAM 存储器。例如,如果内存块满足 CPU 和 GPU 的对齐规则,则 Intel 将 CL_MEM_USE_HOST_PTR 解释为允许 CPU 和 GPU 共享物理 DRAM,因此不需要实际复制数据。显然,这非常快速!以下是一个解释它的链接:

https://software.intel.com/en-us/articles/getting-the-most-from-opencl-12-how-to-increase-performance-by-minimizing-buffer-copies-on-intel-processor-graphics

PS我知道我的回复对于OP来说太迟了,但其他读者可能会感兴趣。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接