2011-11-17 24 views
1

我今天開始了我的CUDA冒險。我試圖在所有線程中共享一個無符號整數。所有的線程修改這個值。我通過使用cudaMemcpy將這一個值複製到設備。但是,在計算結束時,我收到這個值等於0.Cuda內存在每個線程中共享

也許有幾個線程正在同時寫入這個變量? 我不知道是否應該使用任何信號量或鎖定此變量時,線程開始寫或什麼。

編輯:

很難更詳細地說,因爲我的問題是,一般如何解決這個問題。其實我沒有寫任何算法,只測試CUDA。

但是,如果你願意...我創建了包含一些值(無符號整數)的向量。我試圖做一些事情,比如搜索比給定共享值更大的值,但是當來自向量的值更大時,我將向量元素加1並保存共享值。

它看起來像這樣:

__global__ void method(unsigned int *a, unsigned int *b, long long unsigned N) { 
    int idx = blockIdx.x* blockDim.x+ threadIdx.x; 
    if (a[idx]>*b && idx < N) 
     *b = a[idx]+1; 
} 

正如我說這是不是有用的代碼,僅用於測試,但我不知道該怎麼辦呢?

+0

有足夠的細節在這裏真正肯定地說,但併發寫入通常被認爲是一件壞事。 – Gian

+0

這看起來是錯誤的設計。你希望CUDA線程並行工作*,所以他們通常不需要訪問一個聯合內存。 –

+0

看起來更新後 – nosbor

回答

1

「我的問題一般是如何爲每個線程使用共享內存全局。」

閱讀你不需要任何特別的東西。你所做的工作在Fermi設備上更快,因爲它們有一個緩存,而其他緩存較慢。

如果您在其他線程更改後正在讀取該值,則無法等待所有線程完成其操作,然後再讀取所需的值,因此可能不符合您的預期。在所有正在運行的線程之間同步全局內存中的值的唯一方法是使用不同的內核。在您更改要在內核完成的所有線程之間共享的值後,啓動一個可與共享值一起工作的新值。

爲了讓每個線程都寫入相同的內存位置,您必須使用原子操作,但請記住您應該將原子操作保持在最低限度,因爲這可以有效地序列化執行。

要了解可用的原子功能,請閱讀CUDA C編程指南available here的B.11部分。

你問什麼是:

__global__ void method(unsigned int *a, unsigned int *b, long long unsigned N) { 
    int idx = blockIdx.x* blockDim.x+ threadIdx.x; 
    if (a[idx]>*b && idx < N) 
     //*b = a[idx]+1; 
     atomicAdd(b, a[idx]+1); 
} 
+0

的鏈接的答案,以便您的解決方案看起來沒問題。如果我想分配值,那麼我可以使用atomicExch(b,a [idx] +1)嗎?因爲我認爲它應該在那裏... – nosbor

+0

是的,它在那裏,編程指南中的項目B.11.1.3。 – jmsu

-1

編輯 - 刪除錯誤

雖然理想情況下您不想這樣做 - 除非您可以確定所有線程都需要大約相同時間參見Cuda thread tutorial

+1

__ syncthreads()不適用於塊間同步(由「每個線程」暗示)。他正在談論全局內存中的共享值,而不是__ shared __ memory。 – jmsu

+0

好的 - 將留下指向 –

1

如果值在sh只有在每一個在單個多處理器中運行的線程都是本地的(即,每個線程塊),而不是每個爲該內核運行的線程。如果您希望每個線程都寫入變量,您肯定需要執行原子操作(如atomicAdd等)。 請注意,這會將所有併發線程請求序列化爲寫入變量。