這是回答 PTT 上的一篇 CUDA 問題 [問題] CUDA 程式 - 看板 C_and_CPP - 批踢踢實業坊
下面簡略地敘述
// dim3 gridsize(1, 1, 1); // dim3 blocksize(600, 1, 1); for (int j = 0; j < 800; j+= 1){ sum[(blockDim.x*bdx + tdx)] += data[600*j + (blockDim.x*bdx +tdx)]; }
// dim3 gridsize(40, 1, 1); // dim3 blocksize(600, 1, 1); for (int j = 0; j < 800; j+= 40){ sum[tdx] += data[600*(j + bdx) +tdx]; }
第二個就會執行錯誤
猜測是: 例如, sum[1]無法同時處理40筆資料
答案會錯的原因是 race condition
現在有 40 threads 可能會同時處理 sum += data
→ (讀 sum, 算 sum+data 並把他寫回去)
但這個並非 atomic ,也就是同一條讀和寫中間有可能會被其他插入
例如: sum 一開始是 0,A: sum += 10
, B: sum += 3
有可能是
- A 讀 sum = 0
- B 讀 sum = 0
- B 寫入 sum = 0 + 3 = 3
- A 寫入 sum = 0 (因為一開始讀到是 0) + 10 = 10
最後答案就變成 10 而非 13
根據執行順序也有可能是 3 或 13
可以用 atomicAdd (但可能因為衝突太多導致很慢)
或者不同切法,例如用 (記得處理邊界) sum[threadIdx.x + blockIdx.x * blockDim.x]
然後平行後面加總 data ,記得可以先放入 register 最後再放入 global memory 會比較好。