2012-07-08 54 views
0

的GPU,我試圖瞭解究竟是如何CL_MEM_USE_HOST_PTR和CL_MEM_COPY_HOST_PTR工作指向的緩衝區的副本。 基本上都採用CL_MEM_USE_HOST_PTR時,說創建2D圖像,這將沒有複製到設備,而不是GPU將把映射的內存(clEnqueueMapBuffer把它映射)主機上,做加工,我們可以把結果寫入到其他位置。另一方面,如果我使用CL_MEM_COPY_HOST_PTR,它將在設備上創建主機ptr指向的數據的副本(我猜它會創建一個單獨的副本,而不僅僅是緩存)。現在處理將在複製到設備的數據上完成,然後再將結果複製到主機。我希望我能正確理解它。創建由主機PTR的GPU內核的OpenCL

所以我的查詢是... 它只是出於我的好奇心,我想這樣做這樣。我將使用CL_MEM_USE_HOST_PTR,現在即使設備可以訪問主機內存,我也希望GPU內核在設備本身上創建一個單獨的副本(不使用COPY_HOST_PTR,因爲它再次在主機中完成),然後執行處理這些數據。如何才能做到這一點??

回答

1

創建緩衝區複製到使用CL_MEM_READ_WRITE,但不要將其初始化你的主機上。 我最近不得不初始化一個新的緩衝區,以連續整數

cl_mem _offsetBuffer; 
_offsetBuffer = clCreateBuffer(_context, CL_MEM_READ_WRITE, (size_t)(count * sizeof(cl_int)), NULL, &errorCode); 

clCreateBuffer上面並沒有做任何事情,除了給你一個句柄內存對象主機的內存。然後我使用內核來分配順序值,因爲圖形卡上的內存速度證明比分配cpu上的值要快得多。

__kernel void initOffsetBuffer(__global int* offsetBuffer, const int offsetBufferLength, const int startValue){ 
    int gid = get_global_id(0); 
    int gs = get_global_size(0); 
    int i; 
    for(i=gid;i<offsetBufferLength;i+=gs){ 
     offsetBuffer[i] = i+startValue; 
    } 
} 

此時在主機內存中仍然沒有緩衝區副本。我需要使用clEnqueueReadBuffer將其複製到主機。

您可以很容易地將此​​代碼修改爲複製內核,而不僅僅是直接分配。

__kernel void copyBuffer(__global const int* srcBuffer, __global int* dstBuffer, const int bufferLength){ 
    int gid = get_global_id(0); 
    int gs = get_global_size(0); 
    int i; 
    for(i=gid;i<bufferLength;i+=gs){ 
     dstBuffer[i] = srcBuffer[i]; 
    } 
} 
1

OpenCL的緩衝區通常在主機內存中的「位」的副本(這是怎樣的緩衝區的內容中的OpenCL規範的稱呼)。這是必要的,因爲設備內存是有限的,而且這些位通常只在被內核使用時傳輸到設備。

當你創建一個USE_HOST_PTR緩衝區,你讓OpenCL運行使用host_ptr位置該主機的內存拷貝。當內核將使用緩衝區時,這些位將被複制到設備。執行後,您需要確保這些位被同步回主機內存。這通過調用clEnqueueMapBuffer來完成,並且由此函數返回的指針將位於主機內存區域內。

當你創建一個COPY_HOST_PTR緩存,運行時分配的緩衝區的新主機內存拷貝,並複製你的點點進去。通常,此時沒有任何內容被髮送到設備。

0

CL_MEM_HOST_PTR - 實際上,cl_mem對象會在設備上分配內存並複製主機指針指定的數據。主機端不可見設備端緩衝區對象的任何修改。

CL_MEM_USE_HOST_PTR - cl_mem對象由host_ptr使用的內存refferd,所以該設備可以directrly修改分配以這種方式,我們不涉及任何數據傳輸主機數據。