我正在用openCL 1.2創建應用程序,這是對更大應用程序的測試。該測試將1與每個內核執行的4x4矩陣的每個值相加。這個想法是獲得雙緩衝工作。我創建了兩個實際上做同樣事情的內核,他們共享相同的READ_WRITE緩衝區,因此每個內核執行都可以在最後一個內核執行的地方繼續執行,但它們有所不同,因爲它們具有不同的輸出緩衝區,允許使用輸出緩衝區之一內核在閱讀其他的數據,就像這樣:我認爲OpenCL,爲單個設備使用兩個命令隊列進行雙緩衝
的代碼片段是相關或可能是有問題的有以下幾種,我包括隊列,緩衝區和事件以防萬一,但我試圖改變這一切:
隊列
compute_queue = clCreateCommandQueueWithProperties(context, device_id, 0, &err);
data_queue = clCreateCommandQueueWithProperties(context, device_id, 0, &err);
緩衝
input_Parametros = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(double) * 5, Parametros, NULL);
input_matA = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(double) * 4, matA_1, NULL); // The 4x4 matrix
output_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY , sizeof(double) * 4 * iteraciones_por_kernel, NULL, NULL);
output_buffer_2 = clCreateBuffer(context, CL_MEM_WRITE_ONLY , sizeof(double) * 4 * iteraciones_por_kernel, NULL, NULL);
參數爲每個內核設置
clSetKernelArg(kernel_1, 0, sizeof(cl_mem), &input_matA);
clSetKernelArg(kernel_1, 1, sizeof(cl_mem), &input_Parametros);
clSetKernelArg(kernel_1, 3, sizeof(cl_mem), &output_buffer);
clSetKernelArg(kernel_2, 0, sizeof(cl_mem), &input_matA);
clSetKernelArg(kernel_2, 1, sizeof(cl_mem), &input_Parametros);
clSetKernelArg(kernel_2, 3, sizeof(cl_mem), &output_buffer_2);
活動
cl_event event_1, event_2, event_3, event_4;
內核和讀入隊
////////////////////////////////////////////////////////////////
// START
////////////////////////////////////////////////////////////////
clEnqueueNDRangeKernel(compute_queue, kernel_1, 1, NULL, global, local, 0, 0, &event_1);
clEnqueueNDRangeKernel(compute_queue, kernel_2, 1, NULL, global, local, 0, 0, &event_2);
clEnqueueReadBuffer(data_queue, output_buffer, CL_FALSE, 0, sizeof(double)*4*iteraciones_por_kernel, datos_salida, 1 , &event_1, &event_3);
////////////////////////////////////////////////////////////////
// ENQUEUE LOOP
////////////////////////////////////////////////////////////////
for (int i = 1; i <= (n_iteraciones_int - 2); i++){
////////////////////////////////////////////////////////////////
// LOOP PART 1
////////////////////////////////////////////////////////////////
if (i % 2 != 0){
clEnqueueNDRangeKernel(compute_queue, kernel_1, 1, NULL, global, local, 1, &event_3, &event_1);
clEnqueueReadBuffer(data_queue, output_buffer_2, CL_FALSE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[i*iteraciones_por_kernel_int*4], 1, &event_2, &event_4);
}
////////////////////////////////////////////////////////////////
// LOOP PART 2
////////////////////////////////////////////////////////////////
if (i % 2 == 0){
clEnqueueNDRangeKernel(compute_queue, kernel_2, 1, NULL, global, local, 1, &event_4, &event_2);
clEnqueueReadBuffer(data_queue, output_buffer, CL_FALSE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[i*iteraciones_por_kernel_int * 4], 1, &event_1, &event_3);
}
}
////////////////////////////////////////////////////////////////
// END
////////////////////////////////////////////////////////////////
clEnqueueReadBuffer(data_queue, output_buffer_2, CL_TRUE, 0, sizeof(double) * 4 * iteraciones_por_kernel, &datos_salida[(n_iteraciones_int - 1) * 4], 1, &event_2, 0);
我不能得到這個即使一切似乎完全正常工作。第一次讀取給出了期望的值,但從那時開始就像內核不再執行一樣,因爲我從output_buffer_2中得到0,並且與第一次讀取時相同的值形成第一個output_buffer。
這對於相同的內核和只有一個隊列來說完全正常,它只需一次數據傳輸就可以完成,但我不想那麼做。
我修改了所有內容並儘可能多地調查,嘗試了所有我能想到的變化。這應該很容易,我認爲可能...問題在哪裏?
如果有任何幫助,我將使用AMD HD7970作爲設備,Windows 10和Visual Studio社區2013。
兩個模量的檢查是對零。一個應該是1 –
最新的阻塞閱讀需要一個事件。確保它在返回該事件的上次迭代中有適當的步驟。奇數編號的最後迭代,你忘了比較1 –
最後,你可能需要clflush兩個隊列循環啓動兩個隊列,而最後讀取只啓動自己的隊列iirc –