2014-04-23 32 views
1

我有一個包含2D圖像的OpenCL緩衝區。 此圖像的寬度比寬度大。 我需要從此緩衝區製作OpenCL圖像。 問題是功能clEnqueueCopyImageToBuffer不包含作爲輸入參數的步幅。 是否有可能從OpenCL緩衝區製作OpenCL圖像(步幅大於寬度),只有一次複製或更快? 解決這個問題的一種方法是編寫自己的內核,但也許有更多的整潔解決方案?OpenCL clEnqueueCopyImageToBuffer with stride

+2

我不知道「開箱即用」的解決方案,但認爲可能值得考慮將'clEnqueueCopyBufferRect'的緩衝區的相關部分複製到新緩衝區中,並將* this * buffer複製到圖像中。儘管這涉及到* 2 *拷貝操作,但它可能比編寫自己的內核更簡單。考慮到複製操作完全留給了OpenCL實現,我認爲這不可能比自己的內核慢(*但可能甚至更快* ...) – Marco13

+1

I像CopyBufferRect然後CopyBufferToImage解決方案;它將比下面建議的逐行CopyImageToBuffer更快。但是,我會問:_將多餘的像素包含在圖像中有什麼問題?_您已經在處理它們作爲您的緩衝區,因此它們可能不是大量的額外數據,您仍然可以訪問圖像使用相同的座標,無論他們是否在那裏。您在圖像上運行的下一個操作可能是正確大小的。 – Dithermaster

+0

由於我使用圖像採樣器通過鏡像和雙線性插值處理邊界,因此我無法在圖像中包含額外的像素。計算資源非常有限,無法使用邊界鏡像自行執行雙線性插值。 – Yury

回答

5

不幸的是,OpenCL規範中沒有任何方法允許您在緩衝區數據的跨度不等於圖像寬度時直接從緩衝區創建圖像。最有效的解決方案可能是編寫自己的內核來執行此操作。

不涉及編寫自己的內核的最簡單的解決方案是每次複製一行clEnqueueCopyBufferToImage。如果你的圖像足夠大,可能這種技術的性能與手寫內核的性能相當,但你必須試試看。


我並沒有包括在我原來的答案clEnqueueCopyBufferRect的方法,因爲我的第一反應是,額外的拷貝會殺了性能。然而,上面的評論讓我進一步思考了這個問題,並且我有興趣實施所有三種方法來看看實際的性能。

performance results

正如我懷疑,最快的辦法是實現一個內核直接做到這一點。但是,逐行復制數據的速度明顯慢於我的預期。使用clEnqueueCopyBufferRect將緩衝區複製到中間緩衝區實際上是性能和簡單性的很好折中,儘管比內核實現要慢兩倍。

這個小實驗的源代碼可以在here找到。我用1024的步幅複製了1020x1020圖像,並且計時在8次運行中平均。

+0

優秀分析(+1)。除了Xeon案例之外,「rect」解決方案的時間似乎是「*粗略*內核時間的兩倍」,這是直觀有意義的,因爲這只是關於在設備內存中傳輸的數據 - 一次..或兩次。 – Marco13

+0

不錯,謝謝jprice! – Dithermaster