2016-11-19 32 views
0

我有一個簡單的內核是這樣的:寫作數組索引只適用於最後一個任務隊列

__kernel void cycle(__global int * grid, int idx) { 
    grid[idx] = idx; 
} 

,我跑clEnqueueTask()一個循環裏面,像這樣:

for (int i = 0; i < size; i++) { 
    int arg = i; 
    clSetKernelArg(kernel_id, 1, &arg); 
    clEnqueueTask(command_queue, kernel_id, 0, NULL, NULL); 
} 

預期的結果是一個[0 ...size - 1]的數組,但它僅將最後一個索引設置爲適當的值。其他人保持默認(在我的情況下爲0)。

我試圖積累在陣列(grid[0] += idx)的第一個單元格的idx參數的值,它給了我整數的預期總和從1size - 1,因此參數被正確地傳遞和任務正確執行。

任何幫助表示讚賞!

+0

我結束了使用'clEnqueueNDRangeKernel',它運作良好。仍然不確定爲什麼任務並行性在這種情況下不起作用。 'clEnqueueTask'在英特爾實施的OpenCL上被標記爲不推薦使用,但我不確定這與問題有任何關係 – Lev

回答

1

一個可能的建議,您的問題的原因:

arg整數有充分的循環中相同的內存地址;當將它傳遞給CL內核時,您傳遞的是地址(而不是該值的副本),因此每次更改所有實例的值。

雖然這表示所有的網格數組值都等於相同的最後一個值,除了最後一個值以外,不是零。

爲什麼在計算總和時會工作? 我的猜測是你不會在grid數組內存儲單個值(在內核完成並讀回數據後需要保留它);相反,該值將被添加並分配給grid[0],並且grid[0]中的值不會再依賴於idx

誠然,這是有些含糊,並涉及一些猜測,但這裏的東西,你可以嘗試:

for (int i = 0; i < size; i++) { 
    int *arg = malloc(sizeof(*arg)); 
    *arg = i; 
    clSetKernelArg(kernel_id, 1, arg, sizeof(*arg)); 
    clEnqueueTask(command_queue, kernel_id, 0, NULL, NULL); 
} 

(出於某種原因,你的例子不具有size參數clSetKernelArg,不知道爲什麼。) 顯然,通常你會將arg作爲一個大小爲size的數組來分配,而不是每次迭代都分配一次,但讓我們繼續這個例子。

如果這個工作,你可以玩弄看看你可以在什麼點freearg,因爲上面是相當多的內存泄漏。我懷疑你可以在循環內免費arg

相關問題