CUDA 的塊間同步方法

      網友投稿 1021 2025-03-31

      cuda 塊間同步方法有以下三種

      ① Lock-Based Synchronization

      ② Lock-Free Synchronization

      ③ __threadfence()

      基于鎖的塊間同步

      cuda 基于鎖的同步的基本思想是使用一個全局互斥量變量來計算到達同步點的線程塊的數量。如下代碼所示,在 barrier 函數 __gpu_sync() 中,在一個塊完成它的計算之后,它的一個線程 (這里人為設置為?0 號線程,我們稱之為主導線程) 將自動地向 g_mutex 添加 1 (原子操作)。然后,主導線程將重復將?g_mutex 和一個目標值 goalVal 進行比較。如果 g_mutex 等于 goalVal,那么就意味著同步完成,即每個線程塊都可以進行下一階段的計算。在該設計中,當第一次調用 barrier 函數時,將 goalVal 設置為內核中的塊數 N 。然后,當連續調用 barrier 函數時,goalVal的值每次遞增 N 。這種設計比保持 goalVal 常量并在每個 barrier 之后重新設置 g_mutex 更有效,因為前者節省了指令的數量并避免了條件分支 。

      // lock-based

      __device__ volatile int g_mutex;

      // GPU lock-based synchronization function

      __device__ void __gpu_sync(int goalVal)

      {

      // thread ID in a block

      int tid_in_block = threadIdx.x * blockDim.y + threadIdx.y;

      // only thread 0 is used for synchronization

      if (tid_in_block == 0)

      {

      atomicAdd((int*) &g_mutex, 1);

      // only when all blocks add 1 go g_mutex

      // will g_mutex equal to goalVal

      while (g_mutex != goalVal)

      {

      // Do nothing here

      }

      }

      __syncthreads();

      }

      無鎖的塊間同步

      在 CUDA 基于鎖的同步中,互斥量變量 g_mutex 是通過原子函數 atomicAdd() 添加的。這意味著 g_mutex 的添加只能按順序執行,即使這些操作是在不同的塊中執行的。因此,提出一種完全避免使用原子操作的無鎖同步方法。這種方法的基本思想是為每個線程塊分配一個同步變量,這樣每個塊就可以獨立地記錄其同步狀態,而不必爭用單個全局互斥鎖變量。如下代碼所示,我們的無鎖同步方法使用兩個數組 Arrayin 和 Arrayout 來協調來自不同塊的同步請求。在這兩個數組中,每個元素都映射到內核中的一個線程塊,即,將元素 i 映射到線程塊 i ,算法大致分為三個步驟:

      一開始,當 block i 準備好通信時,它的主導線程 (線程 0) 將 Arrayin 中的元素 i 設置為目標值 goalVal。block i 中的主導線程然后忙等 Arrayout 的元素 i 被設置為 goalVal 。

      然后人為的讓 block 1中的前 N 個(N 等于塊數)線程重復檢查 Arrayin 中的所有元素是否等于 goalVal ,線程 i 負責檢查 Arrayin 中的第 i 個元素(一對一檢查)。將 Arrayin 中的所有元素設置為 goalVal 后,每個檢查線程將 Arrayout 中的相應元素設置為 goalVal 。注意,在更新 Arrayout的元素之前,block 1 的每個檢查線程都會調用塊內 barrier 函數? __syncthreads()。

      最后,當 block i 的主導線程看到 Arrayout 中的對應元素被設置為 goalVal 時,該 block 將繼續執行。

      // lock-free

      __device__ void __gpu_sync(int goalVal, volatile int *Arrayin, volatile int *Arrayout)

      {

      // thread ID in a block

      int tid_in_blk = threadIdx.x * blockDim.y + threadIdx.y;

      int nBlockNum = gridDim.x * gridDim.y;

      int bid = blockIdx.x * gridDim.y + blockIdx.y;

      // only thread 0 is used for synchonization

      if (tid_in_blk == 0)

      {

      Arrayin[bid] = goalVal;

      }

      if (bid == 1)

      {

      if (tid_in_blk < nBlockNum)

      {

      while (Arrayin[tid_in_blk] != goalVal)

      {

      // Do nothing here

      }

      }

      __syncthreads();

      if (tid_in_blk < nBlockNum)

      {

      Arrayout[tid_in_blk] = goalVal;

      }

      }

      if (tid_in_blk = 0)

      {

      while (Arrayout[bid] != goalVal)

      {

      CUDA 的塊間同步方法

      // Do nothing here

      }

      }

      __syncthreads();

      }

      從以上代碼可以看出,CUDA 無鎖同步中沒有原子操作。所有的操作都可以并行執行。不同線程塊的同步由單個塊 (block?1) 中的 N 個線程來控制,可以通過調用塊內 barrier 函數 __syncthreads() 來有效地同步。

      __threadfence()

      最后,值得注意的是,另外一種保證?CUDA 塊間同步通信的正確性的辦法是使用?__threadfence() (CUDA 2.2中引入了一個新的函數 )。這個函數將阻塞調用線程,直到之前對 全局內存 或 共享內存 的寫入對其他線程可見為止。但是使用 __threadfence() 也會引起一定的額外開銷,所以需要進行實際測試和權衡。

      任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:做成在線文檔庫(做成在線文檔庫怎么弄)
      下一篇:在WPS表中 如何在整個數字前加上減號?(在wps表中把一列數變成畝)
      相關文章
      中文字幕亚洲男人的天堂网络 | 亚洲一线产品二线产品| 国产亚洲精品无码专区| 亚洲av无码av在线播放| 亚洲午夜无码毛片av久久京东热| www.亚洲成在线| 激情亚洲一区国产精品| 亚洲三级在线免费观看| 亚洲最大在线观看| 亚洲人成在线播放| 亚洲日韩国产精品乱-久| 久久精品国产亚洲AV蜜臀色欲| 亚洲免费中文字幕| 色婷五月综激情亚洲综合| 中中文字幕亚洲无线码| 亚洲欧美国产欧美色欲| 亚洲精品无码专区| 久久精品国产亚洲AV| 美国毛片亚洲社区在线观看| 国产精品亚洲二区在线| 亚洲国产91精品无码专区| 亚洲精品国自产拍在线观看| 亚洲综合区小说区激情区 | 亚洲综合av一区二区三区| 亚洲欧美日韩国产精品一区| 亚洲精品V天堂中文字幕| 色窝窝亚洲av网| 亚洲精品国产电影| 亚洲色成人中文字幕网站| 亚洲成AV人在线播放无码| 亚洲免费在线视频| 亚洲综合久久成人69| ww亚洲ww在线观看国产| 亚洲va中文字幕无码久久不卡| 亚洲av永久无码精品网站 | 亚洲视频在线观看免费| 久久久久亚洲av无码专区| 91亚洲国产成人久久精品网址| 精品日韩99亚洲的在线发布| 鲁死你资源站亚洲av| 亚洲免费在线观看|