2011-05-10 97 views
15

我有幾個塊,每個塊都有一個大小爲512的共享內存數組中的一些整數。如何檢查每個塊中的數組是否包含零作爲元素?並行寫入同一全局內存位置

我正在做的是創建一個駐留在全局內存中的數組。這個數組的大小取決於塊的數量,並且它被初始化爲0.因此,如果共享存儲器數組包含零,則每個塊寫入a[blockid] = 1

我的問題是當我在同一時間寫一個塊的幾個線程。也就是說,如果共享內存中的數組包含多個零,則多個線程將寫入a[blockid] = 1。這會產生任何問題嗎?

換句話說,如果2個線程將完全相同的值寫入全局內存中完全相同的數組元素,會是一個問題嗎?

回答

12

synchronizing進入全球數據在CUDA執行模型,有沒有保證從同一塊相同的全局內存位置的線程每同時寫入會成功。至少有一個寫操作可以工作,但編程模型無法保證有多少寫操作會發生,或者如果執行多個事務時它們將以什麼順序發生。

如果這是一個問題,那麼更好的方法(從正確性的角度來看)將是每個塊只有一個線程進行全局寫入。您可以使用原子集共享內存標誌或減少操作來確定是否應設置該值。你選擇的可能取決於可能有​​多少個零。零點越多,減少的效果越好。 CUDA包括經編級別__any()__all()運算符,它們可以構建成幾行代碼中非常有效的布爾運算。

+0

我的+1從CUDA的角度回答它是OP所尋找的,而不是C/C++開發環境的觀點。 – 2011-05-11 03:34:47

+6

請參閱我的回答瞭解更多詳情(不能在評論中發佈鏈接和引用!)。 CUDA確保如果一個warp中的多個線程寫入相同的位置,那麼至少有一個線程將成功寫入該位置,但是哪個線程(或哪個線程最後一個線程)未定義。 – Tom 2012-03-06 16:31:52

1

是的,這將是一個問題,被稱爲Race Condition
你應該考慮通過process Semaphores

+0

MMM I C 會是更好的,如果我用原子操作或使用減少算法,以檢查是否該數組包含一個零? – lina 2011-05-10 17:35:20

+0

@lina:這要看你能不能讓這些操作atomic..Synchronization可以很容易,如果你讀一點基礎知識... HTTP://www.academictutorials.com/ipc/ipc-process-synchronization.asp心連心 – 2011-05-10 17:38:00

+0

但在cuda中沒有這樣的東西...... – lina 2011-05-10 17:39:47

1

雖然不是互斥鎖或信號量,但CUDA確實包含一個同步基本元素,您可以使用它來序列化對給定代碼段或內存位置的訪問。通過__syncthreads()函數,您可以創建一個屏障,以便在命令指向的任何給定線程塊進行調用,直到給定塊中的所有線程都執行了__syncthreads()命令。這樣,您可以希望序列化訪問您的內存位置,並避免兩個線程需要同時寫入同一內​​存位置的情況。唯一的警告是所有的線程都必須在某個時候執行__syncthreads(),否則最終會出現死鎖情況。因此,不要將調用放在某些有條件的if語句中,其中一些線程可能永遠不會執行該命令。如果確實如此處理您的問題,則需要爲線程創建一些預配置,以避免死鎖,這些線程最初不會調用__syncthreads()以稍後調用該函數。

17

對於CUDA程序,如果在經寫入到同一位置的多個線程,則位置被更新,但它是發生不確定位置是多少次更新(即有多少實際寫入),它是undefined其中線程將寫最後(即哪個線程將贏得比賽)。

對於計算能力2.x的設備,如果一個warp中的多個線程寫入相同的地址,那麼只有一個線程將實際執行寫入,其中線程未定義。

CUDA C Programming Guide部F.4.2:

如果由經線執行的非原子指令寫入到全局存儲器的同一位置爲經線的螺紋的一個以上的,只有一個線程執行寫操作,以及哪個線程未定義。

參見本指南的4.1節以獲得更多信息。

換句話說,如果寫入給定位置的所有線程寫入相同的值,那麼它是安全的。