2012-03-13 38 views
0
 

    __kernel 
    void example(__global int *a, __global int *dependency, uint cols) 
    { 
     int j = genter code hereet_global_id(0); 
     int i = get_global_id(1); 
     if(i > 0 && j > 0) 
     { 
      while(1) 
     { 
      test = 1;     
      } 
      //Wait for the dependents 

     ----------------------------- 

     -------------------------- 
     } 
    } 

在一定條件下等待其它線程在上面的內核代碼爲什麼while循環只是在所有的線程跳過與出無限循環的任何方式。對此有任何想法。 我正在研究一些有趣的問題,它需要一個線程根據某些條件等待其他線程完成,但每當上面或while(wait_condition)在GPU上運行時都會被跳過。有沒有做一個特定的線程中的OpenCL內核

是否有任何其他方式讓特定線程等待GPU上的OpenCL內核中的其他線程?

在此先感謝!

+1

值得指出的是,並非每個在內核啓動中排隊的工作項都在設備上同時運行是很正常的。這意味着任何採用自旋鎖方案的代碼(即使是正確設計的代碼)仍然可能會失敗併產生無法恢復的死鎖,因爲旋轉工作項目可能正在等待來自尚未安排的工作項目的操作。在GPU計算中,整個設備級別同步的整體思路通常很糟糕,如果您需要,您可能會更好地使用不同的算法或不同的體系結構。 – talonmies 2012-03-14 07:05:47

回答

3

在高層次上,GPU是數據並行計算設備。他們喜歡在不同的數據上運行相同的任務。當他們的任務完成不同的事情時,他們做得不好。

您的代碼說明了任務並行問題。所以我的高層次問題是你解決什麼類型的問題。如果這是一個任務並行問題,那麼GPU可能不是最好的解決方案。多核CPU是否可以替代?

您的代碼是「自旋鎖」的典型代碼。代碼循環直到值發生變化。它通常用於數據庫中的短期輕量級鎖定。即使在CPU上,這也是危險的代碼,因爲錯誤或錯誤會鎖定CPU或GPU。對於CPU代碼,通常使用中斷計時器來保護自旋鎖。 用法是

1)設置一個計時器 2)自旋直到一個值改變 3)繼續或超時

所以MS的必要數量之後的代碼被中斷並且錯誤被拋出。因此,如果您使用自旋鎖模式,爲了安全起見,在完成適當數量的循環後,在while語句中添加一個循環退出。

在OpenCL簡化算法中,其典型爲零線程(get_global_id(0)== 0) 返回最終的單例結果。在此之前,所有線程將通過屏障呼叫進行同步

__kernel 
void mytask(... , global float * result) 
{ 
    int thread = get_global_id(0); 

    ... your code 

    barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE) // flush global and local variables or enqueue a memory fence see OpenCL spec for details 


    if (thread == 0) // Zero thread 
     result[0] = value; // set the singleton result as the zeroth array element 

} 
+0

重要的是要指出,「障礙」不會成爲整個設備(GPU)的障礙,但僅限於工作組。有效的全球障礙仍然是正在進行的研究的主題。 – KLee1 2012-03-21 06:38:55