我正在开发一个需要大量OpenCL代码的项目。我正在使用OpenCV的ocl模块来更快地开发我的项目,但有些功能没有实现,我将不得不编写自己的OpenCL代码。
我的问题是:将数据从Mat和/或oclMat传输到cl_mem数组的最快最便宜的方法是什么。重写这个,是否有一种从oclMat或Mat传输或排队(clEnqueueWriteBuffer)数据的好方法?
目前,我正在使用for循环从Mat读取数据(或从oclMat下载然后使用for循环),然后将其排队。结果证明这是昂贵的,因此我的问题。
感谢所有看到此问题的人:)
答案 0 :(得分:2)
我为Boost.Compute库编写了一组互操作函数,可以方便地使用OpenCL和OpenCV。看一下opencv_copy_mat_to_buffer()
函数。
还有从OpenCL缓冲区复制回主机cv::Mat
以及将cv::Mat
复制到OpenCL image2d
对象的功能。
答案 1 :(得分:1)
计算主机 - 设备互连中实现的内存带宽。
如果你获得大约60%甚至更多的最大带宽,你就无所事事,内存传输速度尽可能快。但是,如果您的带宽结果低于理论最大值的55% - 60%,请尝试使用具有解除阻塞操作的多个命令队列(不要忘记在最后同步)。另外,要注意平均图像大小。小数据传输通常具有很大的开销率。
如果您的设备使用共享内存,请使用内存映射而不是读/写,这可能会大大节省时间。如果Device拥有自己的内存,请应用固定内存技术,这在NVIDIA OpenCL最佳实践指南中有详细描述。
答案 2 :(得分:1)
oclMat的文档声明底层ocl缓冲区数据有某种功能:
//! pointer to the data(OCL memory object)
uchar *data;
如果设备中已有clMat,则只需执行从clMat.data
到clBuffer
的复制缓冲区即可。但你必须破解一点内存,访问oclMat的一些私人成员
类似的东西:
clEnqueueCopyBuffer(command_queue, (clBuffer *)oclMat.data, dst_buffer, 0, 0, size);
注意:注意投射,也许你必须再投射一个指针。
答案 3 :(得分:0)
对于你的评论,这是对的。 oclMat可以用作设备的cl_mem(void *),因为它是由OpenCL设备分配的。
此外,您可以首先创建svm内存(例如void * svmdata),然后分配Mat:Mat A(rows,cols,CV_32FC1,svmdata)。 现在,您可以在没有内存复制的情况下处理主机和设备之间的Mat A. (PS .svm内存是OCL的新字符,它可以由clSVMAlloc创建)。