2014-01-25 31 views
6

我正在研究需要大量OpenCL代碼的項目。我正在使用OpenCV的ocl模塊來更快地開發我的項目,但有一些功能沒有實現,我將不得不編寫自己的OpenCL代碼。將數據從Mat/oclMat傳輸到cl_mem(OpenCV + OpenCL)

我的問題是:什麼是從Mat和/或oclMat傳輸數據到cl_mem數組的最快和最便宜的方法。重新措辭這是否有一個很好的方法來傳輸或入隊(clEnqueueWriteBuffer)從oclMat或Mat數據?

目前,我正在使用for-loop從Mat讀取數據(或從oclMat下載,然後使用for-loops),然後將它排入隊列。這是昂貴的,因此我的問題。

感謝任何看到此問題的人:)

+0

嗨,這是對我有用的東西。假定x是用「1」初始化的oclMat。 oclMat x(100,100,CV_32FC1,Scalar(1)); clossKernelArg(kernel,0,sizeof(cl_mem),(void *)&x.data); 這對我有用,我通過挖掘OpenCV中給出的ocl代碼得到了這個想法。請讓我知道你是否認爲這裏可能出現問題。謝謝!! – ponderingfish

+0

這就是使用它的正確方法。你甚至沒有使用另一個緩衝區,而是直接使用原始的oclMat緩衝區。當您將其緩衝區用於其他目的時,請小心不要使用原始的oclMat。 – DarkZeros

+0

謝謝@DarkZeros! – ponderingfish

回答

1

計算主機 - 設備互連中實現的內存帶寬。

如果您獲得最大帶寬的60%和更多,那麼您無需執行任何操作,但內存傳輸速度會盡可能快。但是,如果您的帶寬結果低於理論最大值的55% - 60%,請嘗試使用具有解鎖操作的多個命令隊列(不要忘記在最後同步)。另外,請注意平均圖像大小。小數據傳輸通常具有大的開銷率。

如果您的設備使用共享內存,請使用內存映射而不是讀/寫,這可以大大節省時間。如果設備擁有自己的內存,則應用固定內存技術,這在NVIDIA OpenCL最佳實踐指南中有詳細描述。

+0

謝謝你的回答和時間!還有其他工作對我來說 - 請檢查我對原始問題的評論。 – ponderingfish

+0

使用適當的構造函數意味着複製將在後臺進行。我假設CL_MEM_COPY_HOST_PTR標誌用於內存對象創建階段。雖然如果你對解決方案感到滿意,那很好:) –

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); 

注:請注意與鑄造,也許你要投另一個指針。

+0

謝謝你的回答和時間!還有其他工作對我來說 - 請檢查我對原始問題的評論。 – ponderingfish

2

我已經爲Boost.Compute庫編寫了一套互操作函數,它可以簡化OpenCL和OpenCV的使用。看看opencv_copy_mat_to_buffer()函數。

還有從OpenCL緩衝區複製回主機cv::Mat以及將cv::Mat複製到OpenCL image2d對象的功能。

0

爲了您的評論,它是正確的。 oclMat可以用作設備的cl_mem(void *),因爲它是由OpenCL設備分配的。

此外,您可以先創建svm內存(例如void * svmdata),然後分配Mat:Mat A(行,列,CV_32FC1,svmdata)。 現在您可以在主機和設備之間處理墊子而無需複製內存。 (PS。svm內存是OCL的新特性,它可以由clSVMAlloc創建)。