所以我現在一直在玩OpenCL,測試主機和設備之間的內存傳輸速度。 我正在使用英特爾OpenCL SDK,並在集成圖形的Intel i5 Processor上運行。 我發現然後clEnqueueMapBuffer
代替clEnqueueWriteBuffer
這原來是近10倍的速度利用固定內存時,像這樣:CL_MEM_ALLOC_HOST_PTR比CL_MEM_USE_HOST_PTR更慢
int amt = 16*1024*1024;
...
k_a = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, a, NULL);
k_b = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, b, NULL);
k_c = clCreateBuffer(context,CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, sizeof(int)*amt, ret, NULL);
int* map_a = (int*) clEnqueueMapBuffer(c_q, k_a, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_b = (int*) clEnqueueMapBuffer(c_q, k_b, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_c = (int*) clEnqueueMapBuffer(c_q, k_c, CL_TRUE, CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
clFinish(c_q);
凡a
b
和ret
是128個對齊INT陣列。 時間出來約22.026186毫秒,相對於使用clEnqueueWriteBuffer
然而,當我改變了我的代碼
k_a = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
k_b = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
k_c = clCreateBuffer(context,CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR, sizeof(int)*amt, NULL, NULL);
int* map_a = (int*)clEnqueueMapBuffer(c_q, k_a, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_b = (int*)clEnqueueMapBuffer(c_q, k_b, CL_TRUE, CL_MAP_READ, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
int* map_c = (int*)clEnqueueMapBuffer(c_q, k_c, CL_TRUE, CL_MAP_WRITE, 0, sizeof(int)*amt, 0, NULL, NULL, &error);
/** initiate map_a and map_b **/
時間增加到91.350065毫秒
什麼能198.604528毫秒是問題嗎?或者它是一個問題呢?
編輯: 這是我如何初始化第二碼數組:
for (int i = 0; i < amt; i++)
{
map_a[i] = i;
map_b[i] = i;
}
而現在,我檢查,map_a和map_b 做包含在節目結束的權利元素,但map_c包含全部0。我這樣做:
clEnqueueUnmapMemObject(c_q, k_a, map_a, 0, NULL, NULL);
clEnqueueUnmapMemObject(c_q, k_b, map_b, 0, NULL, NULL);
clEnqueueUnmapMemObject(c_q, k_c, map_c, 0, NULL, NULL);
和我的內核就是
__kernel void test(__global int* a, __global int* b, __global int* c)
{
int i = get_global_id(0);
c[i] = a[i] + b[i];
}
在第二個代碼中,您可以展示如何用a,b和ret數據初始化k_a,k_b和k_c,以及clFinish在哪裏。如果這兩個代碼做了不同的事情,它將很難幫助你 –
對不起,代碼是相同的,我只是沒有意外複製一切。在第二個代碼中,我不用ret初始化k_c,因爲我認爲我只能從map_c讀取數據。 – selena731
映射和使用之後,您必須取消映射,或者從映射對象執行clWrite/Read以確保內存一致性。 – DarkZeros