C_and_CPP 板


LINE

※ 引述《goodzey (--)》之銘言: : 不知道有沒有高手可以解答以下問題? : 資料形式: 600列800行的隨機數 : 目的: 把每一行的數據加起來 : 初始化: : sum[600]={0.0} : data[600x800]= 上述資料 : CUDA程式1: 成功 : // dim3 gridsize(1, 1, 1); : // dim3 blocksize(600, 1, 1); : for (int j = 0; j < 800; j+= 1){ : sum[(blockDim.x*bdx + tdx)] = sum[(blockDim.x*bdx + tdx)] : + data[600*j + (blockDim.x*bdx +tdx)]; : } 這邊有一個簡單的最佳化,先把 tdx thread 負責的 row 之和放在 register 裡面,這樣可以減少一些不必要的 global memory write。 : CUDA程式2: 失敗 : // dim3 gridsize(40, 1, 1); : // dim3 blocksize(600, 1, 1); : for (int j = 0; j < 800; j+= 40){ : sum[0*(j + bdx) +tdx] = sum[0*(j + bdx) +tdx] : + data[600*(j + bdx) +tdx]; : } : 請問程式2失敗的原因是?可以怎麼寫呢? : 我自己猜測是: 例如, sum[1]無法同時處理40筆資料 : 請教大家, 謝謝 2 的話,每個 block 的 tdx thread 都會往 sum[tdx] 做加總,而 blocks 並沒有保證 結束的時間點,所以會需要用 atomicAdd 避免 race condition。但因為總是往 sum 做加 總,實際上在 kernel launch 前,還得把 sum 清零,因此在量測效能上,是需要計算 清零 + kernel 運行的時間。這邊提供修改過的 kernel 給你參考: __global__ void multipleBlockSum(float *sum, float *data, size_t m, size_t n) { const auto numBlocks = gridDim.x; const auto bdx = blockIdx.x; const auto tdx = threadIdx.x; float s{}; for (int j = 0; j < n; j += numBlocks) { s += data[m * (j + bdx) + tdx]; } float *dst = &sum[tdx]; atomicAdd(dst, s); } 不過這邊想拋磚引玉提供一點關於這種 reduction 問題 kernel 的做法: 1. 每個 block 劃分一塊區域(tiling)去做 reduction,以這個問題就是 row-wise sum 2. 先把 tile 讀進 shared memory 後,在 shared memory 做 reduction,如果 tile 無法覆蓋所有 columns,則用 tile 大小 loop 過所有 column。 reduction 結果要放 shared memory or register 都可以。 3. 寫出 reduction 結果。 kernel 大概會長這樣: 1 template<size_t TileM, size_t TileN> 2 __global__ void reductionSum(float* s, float* a, size_t m, size_t n) { 3 const auto blockReadOffset = blockIdx.x * TileM; 4 const auto row = threadIdx.x / TileN; 5 const auto col = threadIdx.x % TileN; 6 const auto blockWriteOffset = blockIdx.x * TileM + row; 7 const auto localWriteOffset = row * TileN + col; 8 const auto localReadOffset = row + col * m; 9 __shared__ float buf[TileM * TileN]; 10 __shared__ float sum[TileM]; 11 memset(sum, 0, sizeof(float) * TileM); 12 size_t nIter = 0; 13 14 while (nIter < n) { 15 buf[localWriteOffset] = a[blockReadOffset + nIter * m + 16 localReadOffset]; 17 __syncthreads(); 18 19 #pragma unroll 20 for (uint32_t s = (TileN >> 1); s >= 1; s >>= 1) { 21 if (nIter + col < n && ((nIter + col + s) < n) && col < s) { 22 buf[localWriteOffset] += buf[localWriteOffset + s]; 23 } 24 __syncthreads(); 25 } 26 27 if (col == 0) { 28 sum[row] += buf[localWriteOffset]; 29 } 30 __syncthreads(); 31 32 nIter += TileN; 33 } 34 35 if (col == 0) { 36 s[blockWriteOffset] = sum[row]; 37 } 38} 參數: - TileM, TileN, block 每次 loop 負責的區域,[TileM, TileN] - s: sum 結果,a: input matrix,m: # of rows,n: # of columns 程式碼的大致解說如下: L2~L8: global read/write,shared memory read/write 的位址計算。 L9~L11: shared memory 的配置與初始化,包含 reduction 與 sum 結果的 buffer。 L12~L13: 開始 N 方向的 iteration。 L15~L17: 讀取 global memory 的資料到 shared memory,用 __syncthreads() 來保證 block 所需要的資料都已讀進 shared memory。 L19~L32: shared memory 內的 reduction,只有 col == 0 的 thread 更新 sum buffer 的值。 reduction 的做法可以參考: https://developer.download.nvidia.com/assets/cuda/files/reduction.pdf 我這邊寫的 kernel 就簡單做而已,沒有最佳化到極致。 L35~L36: 將 sum 寫出至 global memory。 要 launch kernel 的話大概像這樣: block 數量是 m / TileM,不整除的話要 +1, e.g. m, n = 600, 800, TileM, TileN = 16, 16, # of blocks = 600 / 16 + 1 = 38 reductionSum<16, 16><<<38, 256>>>(...) --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.162.155.177 (臺灣)
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_and_CPP/M.1685340827.A.DAC.html
1F:推 goodzey: thx! 會花時間測試看看上述程式 05/30 22:16
2F:→ goodzey: 一個問題:用atomicAdd是否就不屬於平行計算了? 05/30 22:18
3F:→ goodzey: 用atomicAdd的程式計算速度大概快多少? 05/30 22:21
4F:推 goodzey: 實驗結果: 第一個程式(用atomicAdd)速度是原本1.5倍以上 06/02 23:16
5F:→ goodzey: 第二個程式(reduction kernal)有點難,再研究摟 06/02 23:19







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Tech_Job站內搜尋

TOP