2011-07-31 208 views
41

在OpenCL中,我的理解是,您可以使用barrier()函數來同步工作組中的線程。我確實(通常)瞭解他們的用途以及何時使用它們。我也意識到工作組中的所有線程都必須碰到障礙,否則就會出現問題。但是,每次我嘗試使用屏障到目前爲止,它似乎導致我的視​​頻驅動程序崩潰,或有關訪問某種類型的無效內存的錯誤消息。到目前爲止,我已經在2種不同的視頻卡上看到了這一點(1個ATI,1個NVIDIA)。OpenCL中的障礙

所以,我的問題是:

  1. 任何想法,爲什麼會發生這種情況?
  2. barrier(CLK_LOCAL_MEM_FENCE)barrier(CLK_GLOBAL_MEM_FENCE)有什麼區別?我閱讀了文檔,但我不清楚。
  3. 是否有關於何時使用barrier(CLK_LOCAL_MEM_FENCE)barrier(CLK_GLOBAL_MEM_FENCE)的一般規則?
  4. 是否曾經有過使用錯誤的參數類型調用barrier()可能導致錯誤的時間?

回答

30

正如您所說的,屏障只能同步相同工作組中的線程。沒有辦法在內核中同步不同的工作組。

現在回答你的問題,該規範並沒有明確給我。但在我看來,這部分6.11.9包含了答案:

CLK_LOCAL_MEM_FENCE - 屏障功能要麼沖洗任何 變量存儲在本地內存中或隊列內存欄以確保 將內存操作正確排序到本地內存。

CLK_GLOBAL_MEM_FENCE - 屏障功能將排隊內存欄 以確保將內存操作正確排序到全局內存。 當工作項目,例如,寫入緩衝區或圖像內存對象然後想要讀取更新的數據時,這可能很有用。

所以,我的理解,你應該寫的時候,讀給__local內存空間,並CLK_GLOBAL_MEM_FENCE寫作和看書到__global內存空間時使用CLK_LOCAL_MEM_FENCE。

我還沒有測試這是否是任何比較慢,但是大部分時間,當我需要一個屏障,我有哪些存儲器空間被影響一個疑問,我簡單地使用兩者的組合,即:

barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE); 

這樣你就不應該有任何內存讀取\寫入順序問題(只要你確信組中的每個線程穿過障礙,但你知道這一點)。

希望它有幫助。

+3

顯然CLK_GLOBAL_MEM_FENCE往往比CLK_LOCAL_MEM_FENCE慢。原因是塊內的所有線程都必須等待內存訪問才能完成。等待全局內存訪問完成比本地內存訪問要昂貴得多。當然,這並不總是正確的,它取決於訪問模式(Fermi現在擁有緩存,意味着全局訪問可以緩存在L1上,與共享內存具有類似的延遲),內核中全局/本地內存訪問的數量,入住率,銀行衝突,合併等。 – Zk1001

31

在這裏恢復一個古老的線程。我自己也有一點障礙()。

關於你的碰撞問題,一個潛在的原因可能是如果你的障礙是在一個條件。我讀到,當你使用barrier時,組中的所有工作項必須能夠達到該指令,否則將掛起你的內核 - 通常會導致崩潰。

if(someCondition){ 
    //do stuff 
    barrier(CLK_LOCAL_MEM_FENCE); 
    //more stuff 
}else{ 
    //other stuff 
} 

我的理解是,如果一個或多個工作項目滿足someCondition,所有工作項目必須滿足條件,否則會有一些將跳過障礙。障礙等待所有工作項目達到這一點。要解決上面的代碼,我需要重新調整它一下:

if(someCondition){ 
    //do stuff 
} 
barrier(CLK_LOCAL_MEM_FENCE); 
if(someCondition){ 
    //more stuff 
}else{ 
    //other stuff 
} 

現在所有的工作項目將達到屏障。

我不知道這適用於循環的程度如何;如果工作項目從for循環中斷,它是否會遇到障礙?我不確定。

更新:我成功地崩潰了一些for-loop中的障礙ocl程序。確保所有工作項目同時退出for循環 - 或者更好的是,將屏障放在循環之外。

(來源:異構計算與OpenCL的第5章,p90-91)

+2

感謝您的評論。我也不確定,但我懷疑工作組中的所有線程必須遇到障礙,如果來自該工作組的任何線程都行。所以,循環的情況下,如果一個工作組中的所有線程在達到屏障之前都會中斷,那麼沒問題。但是,如果來自工作組的至少一個線程在循環的特定迭代中碰到障礙,則所有線程(來自該工作組)都必須如此。 –

+0

文檔似乎跳過的另一種情況是在兩種情況下都有if/else並調用障礙。這似乎並沒有使程序崩潰,但它似乎也沒有任何影響。 我發現,AMD的示例代碼可以讓所有線程都在for循環中運行,即使有些人沒有任何目的,只能觸及屏障。 –