使用OpenCL,如何最快地对GPU缓冲区执行memset()操作?

6

我正在使用OpenCL,并且需要在全局设备内存中对某些数组执行memset()操作。CUDA有一个类似于memset()的API函数,但是OpenCL没有。我阅读了这篇文章,找到了两种可能的替代方法:

  1. using memset() on the host with some scratch buffer, then clEnqueueWriteBuffer() to copy that to the buffer on the device.
  2. Enqueueing the following kernel:

    __kernel void memset_uint4(
        __global  uint4* mem,
        __private uint4  val) 
    {
        mem[get_global_id(0)] = val; 
    }
    
哪个更好?或者说,在哪种情况/平台下,一个比另一个更好?
请注意:如果将内存清零的特殊情况需要特别处理,那么也请告知。
2个回答

9
你可以使用来自OpenCL v1.2的 clEnqueueFillBuffer()。这正是你所需要的,而且非常灵活,可以用不同的模式填充缓冲区。
如果你的版本是1.1或更低,则必须采用其他方法。

1
由于OP提到了CUDA,很可能他们正在使用来自NVidia的显卡,目前仅支持OpenCL 1.1。此外,您的答案并未回答给定的两种方法中哪种更好的问题。 - xperroni
2
自2015年以来,具有Kepler或更高架构的NVIDIA显卡支持OpenCL 1.2。驱动程序发布说明 - einpoklum

6

如果您有额外的内存可用,一种非常快速的方法(如果您有额外的内存可用)是使用预先大小初始化的数组(例如填充所有零的数组),然后在需要清空缓冲区时进行设备上的复制。根据我的经验,这比在OpenCL或CUDA中调用填充函数要快得多。显然,这是一个特殊情况,但在我最后一次测试时更快。


它特别比clEnqueueFillBuffer快吗? - einpoklum
@einpoklum 我做了一个测试,enqueueCopyBuffer比enqueueFillBuffer更快,只是在10k次尝试中:fillBuffer的时间为00.000059,copyBuffer的时间为00.000048。 - Jonno_FTW
1
@Jonno_FTW:这是以秒为单位吗?另外,对于什么内存大小?如果您已经准备好了测试(我现在不在OpenCL上工作),或许可以每次运行时使用1 GB;这将使您在比较中获得更长的执行时间。此外,零值情况可能与其他值的情况不同。 - einpoklum
3
好的,我使用了64百万个无符号整数在我的AMD R9 380上再次尝试,这是代码:https://gist.github.com/JonnoFTW/2aa358e7b7e57eecf140ce7beae3fa85 结果表明,使用enqueue填充缓冲区的速度大约快了两倍。 - Jonno_FTW

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