c++ - OpenCL:从主机到设备缓冲区的并行写入?

标签 c++ buffer opencl

我有一个相当大的 cl_mem 缓冲区(1 亿个 float )。我正在尝试减少用来自主机的数据填充它所需的时间(我必须多次将数据从主机传递到设备,目前我每次都重新初始化缓冲区)。

与其一遍又一遍地使用 clCreateBuffer/CL_MEM_COPY_HOST_PTR 进行初始化,似乎更有效的方法是初始化一次缓冲区,然后每次都使用多线程方法更新其数据(因此多个 CPU 线程各自更新缓冲区的子集)数据同步)。

这样的方法可行吗?我查看了 clEnqueueWriteBuffer,虽然它允许更新缓冲区的子集,但似乎对它的多次调用仍将由命令队列按顺序执行。我需要多个命令队列吗?这种方法甚至可能吗?

最佳答案

您的问题并不完全清楚您的初始化/更新是否每次都相同,或者整个缓冲区是否需要在运行之间更新。显然,加快速度的最简单方法是消除任何重复工作,并且不要多次复制相同的数据。

您的测量是否表明您不受 CPU 和设备之间的接口(interface)限制?因为如果您每次都需要复制 N MB,您的设备通过 B MB/s 接口(interface)连接到 CPU/系统内存,并且您的复制时间不会超过 N/B 秒,再多的多线程也无济于事你。

如果您受限于某些 CPU 计算的顺序性质以及随后复制到缓冲区,您可以使用 clEnqueueWriteBuffer() 的异步变体开始复制第一个数据 block ,同时计算下一个等。请注意,clEnqueueWriteBuffer()/CL_MEM_COPY_HOST_PTR 通常使用设备的 DMA 引擎,这通常不需要主机 CPU 的太多干预,并且所以可以完全与计算并行运行。 (主机内存带宽当然一如既往地共享。)

如果这对您的目的来说太麻烦,使用 clEnqueueMapBuffer 可能会有用。将缓冲区映射到主机应用程序的地址空间。这允许任意数量的线程同时访问它的任意区域。但是请注意,这不是 Elixir ,除非您的 OpenCL 实现明确指定了它在实践中的实现方式,否则您实际上可能会使事情变得更糟,因为它最终可能会复制更多 比以前好。

如果你的设备内核实际上并没有最终读取所有的缓冲区(而且你只是事先不知道它需要哪些部分),或者如果它们只精确地读取所有缓冲区一次,那么在一个很好的和可预测的模式,但您的主机代码需要读取和写入大量内容或写入随机位置,您可以尝试使用 CL_MEM_USE_HOST_PTR 创建的缓冲区。这并不是所有实现中的零拷贝,但其想法是让设备直接访问主机内存。您再次受到设备上行链路接口(interface)带宽的限制,并且延迟通常比设备内存差得多,但如果您的设备实际上不需要读取所有内容,这可能会更快,因为您不必推送整个缓冲区在管道中。

最后,如果您的 CPU 以某种方式预处理/解压缩数据,您可以尝试将其卸载到设备。

关于c++ - OpenCL:从主机到设备缓冲区的并行写入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53600898/

相关文章:

c++ - 如何使用C++中另一个命名空间中定义的操作

c++ - 持有多个 Eigen MatrixXd 的最有效方法

c++ - 在图像顶部模拟天体(星星)

c++ - 为什么 mpd_connection_clear_error () 在 mpd_recv_idle () 的 MPD_ERROR_TIMEOUT 之后失败?

java - JNI 方法帮助。带有目标偏移量的 Memcpy

node.js - 为什么同一个字符串有两个不同的缓冲区?

java - 为什么在我的 BufferedReader 中使用*更大*的缓冲区时性能会*差*?

c++ - 基于 GPU 的 N^2 比较

caching - 是什么导致 CPU 中的 L3 缓存未命中?

c++ - 使用 Optimus 技术让 OpenCL 在 Linux 笔记本电脑上运行