OpenCL clEnqueueCopyImageToBuffer带步幅

OpenCL clEnqueueCopyImageToBuffer带步幅,opencl,gpgpu,Opencl,Gpgpu,我有一个包含2D图像的OpenCL缓冲区。 此图像的跨距大于其宽度。 我需要从这个缓冲区生成OpenCL图像。 问题是函数clEnqueueCopyImageToBuffer不包含作为输入参数的步幅。 从OpenCL缓冲区复制OpenCL图像的步幅是否可能大于宽度,只需一次复制还是更快? 解决此问题的一种方法是编写自己的内核,但可能还有更简洁的解决方案?不幸的是,OpenCL规范中没有允许您在缓冲区数据的跨距不等于图像宽度时直接从缓冲区创建图像的方法。最有效的解决方案可能是编写自己的内核来实现这

我有一个包含2D图像的OpenCL缓冲区。 此图像的跨距大于其宽度。 我需要从这个缓冲区生成OpenCL图像。 问题是函数clEnqueueCopyImageToBuffer不包含作为输入参数的步幅。 从OpenCL缓冲区复制OpenCL图像的步幅是否可能大于宽度,只需一次复制还是更快?
解决此问题的一种方法是编写自己的内核,但可能还有更简洁的解决方案?

不幸的是,OpenCL规范中没有允许您在缓冲区数据的跨距不等于图像宽度时直接从缓冲区创建图像的方法。最有效的解决方案可能是编写自己的内核来实现这一点

不需要编写自己的内核的最简单解决方案是使用clEnqueueCopyBufferToImage一次复制一行。如果您的映像足够大,那么这项技术的性能可能相当于手工编写的内核,但您必须尝试一下才能看到

我在最初的回答中没有包括clEnqueueCopyBufferRect方法,因为我的第一直觉是,额外的副本会破坏性能。然而,上面的评论让我进一步思考,我很有兴趣实现这三种方法,看看性能到底是什么样子

正如我所怀疑的,最快的方法是实现一个内核来直接完成这项工作。然而,逐行复制数据的速度比我预期的要慢得多。使用clenqueucopybufferrect将缓冲区复制到中间缓冲区实际上是性能和简单性的一个很好的折衷,尽管仍然比内核实现慢两倍


可以找到这个小实验的源代码。我正在复制一个跨距为1024的1020x1020图像,并且计时是8次运行的平均值。

不幸的是,OpenCL规范中没有允许您在缓冲区数据的跨距不等于图像宽度时直接从缓冲区创建图像的方法。最有效的解决方案可能是编写自己的内核来实现这一点

不需要编写自己的内核的最简单解决方案是使用clEnqueueCopyBufferToImage一次复制一行。如果您的映像足够大,那么这项技术的性能可能相当于手工编写的内核,但您必须尝试一下才能看到

我在最初的回答中没有包括clEnqueueCopyBufferRect方法,因为我的第一直觉是,额外的副本会破坏性能。然而,上面的评论让我进一步思考,我很有兴趣实现这三种方法,看看性能到底是什么样子

正如我所怀疑的,最快的方法是实现一个内核来直接完成这项工作。然而,逐行复制数据的速度比我预期的要慢得多。使用clenqueucopybufferrect将缓冲区复制到中间缓冲区实际上是性能和简单性的一个很好的折衷,尽管仍然比内核实现慢两倍


可以找到这个小实验的源代码。我正在以1024的步幅复制一个1020x1020图像,时间平均为8次运行。

我不知道一个现成的解决方案,但我认为可能值得考虑使用clEnqueueCopyBufferRect将缓冲区的相关部分复制到一个新的缓冲区中,并将该缓冲区复制到一个图像中。尽管这涉及两个复制操作,但它可能比编写自己的内核更简单。考虑到复制操作完全由OpenCL实现,我认为它不太可能比自己的内核慢很多,但可能更快…我喜欢CopyBufferRect然后CopyBufferToImage解决方案;这将比下面建议的逐行复制ImageToBuffer更快。但是,我会问:在图像中包含额外像素有什么不对?您已经在为缓冲区处理它们,因此它们可能不是大量的额外数据,并且无论它们是否存在,您仍然可以使用相同的坐标访问图像。在图像上运行的下一个操作可以是正确大小的操作。我不能在图像中包含额外的像素,因为我使用图像采样器通过镜像和双线性插值处理边界。计算资源非常有限,无法运行自己的带有边界镜像的双线性插值实现。@Dithermaster@Marco13我也想到了clEnqueueCopyBufferRect方法,但我的第一个想法是额外的拷贝会降低性能。然而,我大错特错了,我用三种不同ap的一些性能结果更新了我的答案
我不知道一个现成的解决方案,但是我认为应该考虑使用clEnqueueCopyBufferRect将缓冲区的相关部分复制到一个新的缓冲区中,然后将这个缓冲区复制到一个图像中。尽管这涉及两个复制操作,但它可能比编写自己的内核更简单。考虑到复制操作完全由OpenCL实现,我认为它不太可能比自己的内核慢很多,但可能更快…我喜欢CopyBufferRect然后CopyBufferToImage解决方案;这将比下面建议的逐行复制ImageToBuffer更快。但是,我会问:在图像中包含额外像素有什么不对?您已经在为缓冲区处理它们,因此它们可能不是大量的额外数据,并且无论它们是否存在,您仍然可以使用相同的坐标访问图像。在图像上运行的下一个操作可以是正确大小的操作。我不能在图像中包含额外的像素,因为我使用图像采样器通过镜像和双线性插值处理边界。计算资源非常有限,无法运行自己的带有边界镜像的双线性插值实现。@Dithermaster@Marco13我也想到了clEnqueueCopyBufferRect方法,但我的第一个想法是额外的拷贝会降低性能。然而,我大错特错了,我用三种不同方法的一些性能结果更新了我的答案。优秀的分析+1。除了Xeon的情况外,rect解决方案的时间似乎大约是内核时间的两倍,这从直觉上讲是有意义的,因为这只是关于在设备内存中传输的数据——或者一次。。。或者两次。出色的分析能力+1。除了Xeon的情况外,rect解决方案的时间似乎大约是内核时间的两倍,这从直觉上讲是有意义的,因为这只是关于在设备内存中传输的数据——或者一次。。。一两次。