0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

CUDA編程分布式共享內(nèi)存

冬至子 ? 來源:指北筆記 ? 作者:張北北 ? 2023-05-19 15:35 ? 次閱讀

Distributed Shared Memory

計(jì)算能力9.0中引入的線程塊集群為線程塊集群中的線程提供了訪問集群中所有參與線程塊的共享內(nèi)存的能力。這種分區(qū)共享內(nèi)存稱為 Distributed Shared Memory,對(duì)應(yīng)的地址空間稱為分布式共享內(nèi)存地址空間。屬于線程塊集群的線程可以在分布式地址空間中讀、寫或執(zhí)行原子操作,而不管該地址屬于本地線程塊還是遠(yuǎn)程線程塊。無論內(nèi)核是否使用分布式共享內(nèi)存,共享內(nèi)存大小規(guī)格(靜態(tài)的或動(dòng)態(tài)的)仍然是每個(gè)線程塊。分布式共享內(nèi)存的大小就是每個(gè)集群的線程塊數(shù)量乘以每個(gè)線程塊的共享內(nèi)存大小。

訪問分布式共享內(nèi)存中的數(shù)據(jù)需要所有線程塊存在 。用戶可以使用cluster .sync()從Cluster Group API中保證所有線程塊已經(jīng)開始執(zhí)行。用戶還需要確保在線程塊退出之前完成所有分布式共享內(nèi)存操作。

CUDA提供了一種訪問分布式共享內(nèi)存的機(jī)制,應(yīng)用程序可以從利用它的功能中獲益。讓我們看看一個(gè)簡(jiǎn)單的直方圖計(jì)算,以及如何使用線程塊集群在GPU上優(yōu)化它。 計(jì)算直方圖的標(biāo)準(zhǔn)方法是在每個(gè)線程塊的共享內(nèi)存中進(jìn)行計(jì)算,然后執(zhí)行全局內(nèi)存原子

這種方法的一個(gè)限制是共享內(nèi)存容量。一旦直方圖容器不再適合共享內(nèi)存,用戶就需要直接計(jì)算直方圖,從而計(jì)算全局內(nèi)存中的原子。對(duì)于分布式共享內(nèi)存,CUDA提供了一個(gè)中間步驟,根據(jù)直方圖桶的大小,直方圖可以直接在共享內(nèi)存、分布式共享內(nèi)存或全局內(nèi)存中計(jì)算。

下面的CUDA內(nèi)核示例展示了如何在共享內(nèi)存或分布式共享內(nèi)存中計(jì)算直方圖,具體取決于直方圖箱的數(shù)量。

#include 

// Distributed Shared memory histogram kernel
__global__ void clusterHist_kernel(int *bins, const int nbins, const int bins_per_block, const int *__restrict__ input,
                                   size_t array_size)
{
  extern __shared__ int smem[];
  namespace cg = cooperative_groups;
  int tid = cg::this_grid().thread_rank();

  // Cluster initialization, size and calculating local bin offsets.
  cg::cluster_group cluster = cg::this_cluster();
  unsigned int clusterBlockRank = cluster.block_rank();
  int cluster_size = cluster.dim_blocks().x;
 
  for (int i = threadIdx.x; i < bins_per_block; i += blockDim.x)
  {
    smem[i] = 0; //Initialize shared memory histogram to zeros
  }

  // cluster synchronization ensures that shared memory is initialized to zero in
  // all thread blocks in the cluster. It also ensures that all thread blocks
  // have started executing and they exist concurrently.
  cluster.sync();

  for (int i = tid; i < array_size; i += blockDim.x * gridDim.x)
  {
    int ldata = input[i];

    //Find the right histogram bin.
    int binid = ldata;
    if (ldata < 0)
      binid = 0;
    else if (ldata >= nbins)
      binid = nbins - 1;

    //Find destination block rank and offset for computing
    //distributed shared memory histogram
    int dst_block_rank = (int)(binid / bins_per_block);
    int dst_offset = binid % bins_per_block;

    //Pointer to target block shared memory
    int *dst_smem = cluster.map_shared_rank(smem, dst_block_rank);

    //Perform atomic update of the histogram bin
    atomicAdd(dst_smem + dst_offset, 1);
  }

  // cluster synchronization is required to ensure all distributed shared
  // memory operations are completed and no thread block exits while
  // other thread blocks are still accessing distributed shared memory
  cluster.sync();

  // Perform global memory histogram, using the local distributed memory histogram 
  int *lbins = bins + cluster.block_rank() * bins_per_block;
  for (int i = threadIdx.x; i < bins_per_block; i += blockDim.x)
  {
    atomicAdd(&lbins[i], smem[i]);
  }
}

上面的內(nèi)核可以在運(yùn)行時(shí)啟動(dòng),集群大小取決于所需的分布式共享內(nèi)存的數(shù)量。如果直方圖足夠小,可以容納一個(gè)塊的共享內(nèi)存,用戶可以啟動(dòng)集群大小為1的內(nèi)核。下面的代碼片段展示了如何根據(jù)共享內(nèi)存需求動(dòng)態(tài)啟動(dòng)集群內(nèi)核。

// Launch via extensible launch
{
  cudaLaunchConfig_t config = {0};
  config.gridDim = array_size / threads_per_block;
  config.blockDim = threads_per_block;

  // cluster_size depends on the histogram size.
  // ( cluster_size == 1 ) implies no distributed shared memory, just thread block local shared memory
  int cluster_size = 2; // size 2 is an example here
  int nbins_per_block = nbins / cluster_size;

  //dynamic shared memory size is per block. 
  //Distributed shared memory size =  cluster_size * nbins_per_block * sizeof(int)
  config.dynamicSmemBytes = nbins_per_block * sizeof(int);

  CUDA_CHECK(::cudaFuncSetAttribute((void *)clusterHist_kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, config.dynamicSmemBytes));

  cudaLaunchAttribute attribute[1];
  attribute[0].id = cudaLaunchAttributeClusterDimension;
  attribute[0].val.clusterDim.x = cluster_size; 
  attribute[0].val.clusterDim.y = 1;
  attribute[0].val.clusterDim.z = 1;

  config.numAttrs = 1;
  config.attrs = attribute;

  cudaLaunchKernelEx(&config, clusterHist_kernel, bins, nbins, nbins_per_block, input, array_size);
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • gpu
    gpu
    +關(guān)注

    關(guān)注

    28

    文章

    4761

    瀏覽量

    129144
  • CUDA
    +關(guān)注

    關(guān)注

    0

    文章

    121

    瀏覽量

    13648
  • API接口
    +關(guān)注

    關(guān)注

    1

    文章

    84

    瀏覽量

    10473
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    分布式軟件系統(tǒng)

    。更重要的是,NI LabVIEW 8的分布式智能提供的解決方案不僅令這些挑戰(zhàn)迎刃而解,且易于實(shí)施。LabVIEW 8的分布式智能具體包括: 可對(duì)分布式系統(tǒng)中的所有結(jié)點(diǎn)編程——包括主機(jī)
    發(fā)表于 07-22 14:53

    使用分布式I/O進(jìn)行實(shí)時(shí)部署系統(tǒng)的設(shè)計(jì)

    這篇文章討論了使用分布式I/O進(jìn)行實(shí)時(shí)部署系統(tǒng)的設(shè)計(jì)。美國(guó)國(guó)家儀器公司推出了NI 9144擴(kuò)展機(jī)箱,用于確定性以太網(wǎng)中的NI CompactRIO和可編程自動(dòng)化控制器(PAC)系統(tǒng)。用于C系列模塊
    發(fā)表于 03-12 17:47

    在NI分布式管理器創(chuàng)建共享變量失敗,想請(qǐng)教各位原因

    在NI分布式管理器創(chuàng)建共享變量失?。涸谶@里創(chuàng)建了一個(gè)變量爐批次號(hào)但現(xiàn)實(shí)質(zhì)量是進(jìn)程失敗 并且關(guān)閉了NI分布式管理器后就沒有這個(gè)變量了,請(qǐng)問這是什么情況?
    發(fā)表于 11-06 13:27

    利用NI VeriStand 2010特性創(chuàng)建分布式系統(tǒng)

    要素。通??梢允褂梅瓷?b class='flag-5'>內(nèi)存接口實(shí)現(xiàn)。  反射內(nèi)存網(wǎng)絡(luò)是實(shí)時(shí)本地局域網(wǎng)(LAN),每個(gè)計(jì)算機(jī)總是擁有共享內(nèi)存集合的最新本地復(fù)本。這些專用網(wǎng)絡(luò)是為了提供高確定性的數(shù)據(jù)通信而專門設(shè)計(jì)的??梢?/div>
    發(fā)表于 04-08 09:42

    分布式系統(tǒng)的優(yōu)勢(shì)是什么?

    當(dāng)討論分布式系統(tǒng)時(shí),我們面臨許多以下這些形容詞所描述的 同類型: 分布式的、刪絡(luò)的、并行的、并發(fā)的和分散的。分布式處理是一個(gè)相對(duì)較新的領(lǐng)域,所以還沒有‘致的定義。與順序計(jì)算相比、并行的、并發(fā)的和
    發(fā)表于 03-31 09:01

    HarmonyOS應(yīng)用開發(fā)-分布式設(shè)計(jì)

    不同終端設(shè)備之間的極速連接、硬件協(xié)同、資源共享,為用戶提供最佳的場(chǎng)景體驗(yàn)。分布式設(shè)計(jì)指南可以幫助應(yīng)用開發(fā)者了解如何充分發(fā)揮“One Super Device”的能力,提供獨(dú)特的跨設(shè)備交互體驗(yàn)。說明:本設(shè)計(jì)指南后續(xù)舉例中將包括手機(jī)、智慧屏、手表等多種設(shè)備,其中手機(jī)均指 EM
    發(fā)表于 09-22 17:11

    分布式軟總線實(shí)現(xiàn)近場(chǎng)設(shè)備間統(tǒng)一的分布式通信管理能力如何?

    現(xiàn)實(shí)中多設(shè)備間通信方式多種多樣(WIFI、藍(lán)牙等),不同的通信方式使用差異大,導(dǎo)致通信問題多;同時(shí)還面臨設(shè)備間通信鏈路的融合共享和沖突無法處理等挑戰(zhàn)。那么分布式軟總線實(shí)現(xiàn)近場(chǎng)設(shè)備間統(tǒng)一的分布式通信管理能力如何呢?
    發(fā)表于 03-16 11:03

    vxworks驅(qū)動(dòng)及分布式編程

    本書在內(nèi)容上分為兩部分:驅(qū)動(dòng)篇和分布式編程篇。驅(qū)動(dòng)篇主要介紹了字符設(shè)備驅(qū)動(dòng)、增強(qiáng)型網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)(ENI)以及WindML中文字庫(kù)的設(shè)計(jì)和MicroWindows向VxWorks平臺(tái)上的移植過程;分布式
    發(fā)表于 08-26 14:20 ?0次下載
    vxworks驅(qū)動(dòng)及<b class='flag-5'>分布式</b><b class='flag-5'>編程</b>

    CUDA 6中的統(tǒng)一內(nèi)存模型

    的,并通過PCI-Express總線相連。在CUDA6之前, 這是程序員最需要注意的地方。CPU和GPU之間共享的數(shù)據(jù)必須在兩個(gè)內(nèi)存中都分配,并由程序直接地在兩個(gè)內(nèi)存之間來回復(fù)制。這給
    的頭像 發(fā)表于 07-02 14:08 ?2838次閱讀

    歐拉(openEuler)Summit2021:基于分布式內(nèi)存池的分布式應(yīng)用數(shù)據(jù)交換與共享

    歐拉(openEuler)Summit 2021分布式&多樣性計(jì)算分論壇上,介紹了基于分布式內(nèi)存池的分布式應(yīng)用數(shù)據(jù)交換與共享,能使全棧性能倍
    的頭像 發(fā)表于 11-10 15:48 ?2389次閱讀
    歐拉(openEuler)Summit2021:基于<b class='flag-5'>分布式</b><b class='flag-5'>內(nèi)存</b>池的<b class='flag-5'>分布式</b>應(yīng)用數(shù)據(jù)交換與<b class='flag-5'>共享</b>

    通過使用CUDA GPU共享內(nèi)存

    共享內(nèi)存是編寫優(yōu)化良好的 CUDA 代碼的一個(gè)強(qiáng)大功能。共享內(nèi)存的訪問比全局內(nèi)存訪問快得多,因?yàn)?/div>
    的頭像 發(fā)表于 04-11 10:03 ?7452次閱讀

    CUDA簡(jiǎn)介: CUDA編程模型概述

    CUDA 編程模型中,線程是進(jìn)行計(jì)算或內(nèi)存操作的最低抽象級(jí)別。 從基于 NVIDIA Ampere GPU 架構(gòu)的設(shè)備開始,CUDA 編程
    的頭像 發(fā)表于 04-20 17:16 ?3025次閱讀
    <b class='flag-5'>CUDA</b>簡(jiǎn)介: <b class='flag-5'>CUDA</b><b class='flag-5'>編程</b>模型概述

    介紹CUDA編程模型及CUDA線程體系

    CUDA 編程模型主要有三個(gè)關(guān)鍵抽象:層級(jí)的線程組,共享內(nèi)存和柵同步(barrier synchronization)。
    的頭像 發(fā)表于 05-19 11:32 ?1935次閱讀
    介紹<b class='flag-5'>CUDA</b><b class='flag-5'>編程</b>模型及<b class='flag-5'>CUDA</b>線程體系

    CUDA編程共享內(nèi)存

    共享內(nèi)存是使用__shared__內(nèi)存空間說明符分配的。
    的頭像 發(fā)表于 05-19 15:32 ?1170次閱讀
    <b class='flag-5'>CUDA</b><b class='flag-5'>編程</b><b class='flag-5'>共享</b><b class='flag-5'>內(nèi)存</b>

    如何實(shí)現(xiàn)Redis分布式

    Redis是一個(gè)開源的內(nèi)存數(shù)據(jù)存儲(chǔ)系統(tǒng),可用于高速讀寫操作。在分布式系統(tǒng)中,為了保證數(shù)據(jù)的一致性和避免競(jìng)態(tài)條件,常常需要使用分布式鎖來對(duì)共享資源進(jìn)行加鎖操作。Redis提供了一種簡(jiǎn)單而
    的頭像 發(fā)表于 12-04 11:24 ?731次閱讀