2016-11-19 65 views
1

我編寫了模擬簡單熱流的C++應用程序。它使用OpenCL進行計算。 OpenCL內核採用二維(n x n)溫度值及其大小(n)的陣列。它在每個循環之後返回與溫度新的數組:如何避免在OpenCL中持續存儲複製

僞代碼:

int t_id = get_global_id(0); 
if(t_id < n * n) 
{ 
    m_new[t_id/n][t_id % n] = average of its and its neighbors (top, bottom, left, right) temperatures 
} 

正如可以看到,每一個線程被計算在矩陣的單細胞。當主機應用程序需要執行X計算週期看起來這

  • 爲1 ... X
    1. 複製內存OpenCL設備
    2. 調用內核
    3. 複製存儲備份

我想重寫內核代碼來執行所有X週期沒有常量內存co去往/來自OpenCL設備。

  1. 複製內存OpenCL設備
  2. 調用內核X倍,或致電內核一次,並使其計算X週期。
  3. 複製存儲備份

我知道,當其他所有線程都在做他們的工作在內核的每個線程應該鎖定和後 - M [] []和m_new [] []應該被交換。我不知道如何實現這兩個功能中的任何一個。

或者也許有另一種方式來做到這一點最佳?

回答

1
Copy memory to OpenCL device 
Call kernel X times 
Copy memory back 

這個工程。確保call kernel未被阻塞(因此每個週期保存1-2毫秒),並且沒有任何主機可訪問的緩衝區屬性,例如USE_HOST_PTR或ALLOC_HOST_PTR。

如果調用內核X次不能獲得令人滿意的性能,可以嘗試使用單個工作組(例如只有256個線程)循環X次,每個循環在最後有一個barrier(),以便所有256個線程同步開始下一個週期。通過這種方式,您可以同時計算M個不同的熱流問題,其中M是計算單元(或工作組)的數量,如果這是一臺服務器,它可以用於這麼多的計算。

全局同步是不可能的,因爲當最新線程啓動時,第一個線程已經不存在了。它適用於(計算單元的數量)(每個工作組的線程數)(每個工作組的波前數)線程併發。例如,具有5個計算單元和本地範圍= 256的R7-240 gpu,它可以一次運行5 * 256 * 20 = 25k線程。

然後,爲了獲得進一步的性能,可以應用本地內存優化。

+0

你能說出更多的事情嗎? 當內存實際上被複制到OpenCL設備? 1)創建緩衝區時:緩衝區A(上下文,CL_MEM_COPY_HOST_PTR,size,mem); 2)設置內核arg時:kernel-> setArg(0,A); 3)運行內核時:enqueueNDRangeKernel(...); 我已經在我的代碼中測量了一些時間,它對我仍然不清楚。 – Klepak

+0

沒有一個。它在刷新隊列之後被複制,並且在它開始由gpu發出並且在enqueuewritebuffer命令完成之前被複制。假設所有命令都是非阻塞類型。如果enqueuewritebuffer被設置爲阻塞,那麼在退出該enqueuewritbuffer函數之前,緩衝區將完成複製。 clFinish()爲隊列創建一個啓動信號,這樣就開始了。 clFinish()是同步主機和設備以確保隊列是否完成的最簡單方法。但是,實現可能會讓命令立即開始,並且您可能需要將用戶事件處理程序置於頂部 –