91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

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

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

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

CUDA并行計(jì)算平臺(tái)的C/C++接口的簡(jiǎn)單介紹

星星科技指導(dǎo)員 ? 來源:NVIDIA ? 作者:Mark Harris ? 2022-04-11 10:13 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

本文是 CUDA C 和 C ++的一個(gè)系列,它是 CUDA 并行計(jì)算平臺(tái)的 C / C ++接口。本系列文章假定您熟悉 C 語(yǔ)言編程。我們將針對(duì) Fortran 程序員運(yùn)行一系列關(guān)于 CUDA Fortran 的文章。這兩個(gè)系列將介紹 CUDA 平臺(tái)上并行計(jì)算的基本概念。從這里起,除非我另有說明,我將用“ CUDA C ”作為“ CUDA C 和 C ++”的速記。 CUDA C 本質(zhì)上是 C / C ++,具有幾個(gè)擴(kuò)展,允許使用并行的多個(gè)線程在 GPU 上執(zhí)行函數(shù)。

CUDA 編程模型基礎(chǔ)

在我們跳轉(zhuǎn)到 CUDA C 代碼之前, CUDA 新手將從 CUDA 編程模型的基本描述和使用的一些術(shù)語(yǔ)中受益。

CUDA 編程模型是一個(gè)異構(gòu)模型,其中使用了 CPU 和 GPU 。在 CUDA 中, host 指的是 CPU 及其存儲(chǔ)器, device 是指 GPU 及其存儲(chǔ)器。在主機(jī)上運(yùn)行的代碼可以管理主機(jī)和設(shè)備上的內(nèi)存,還可以啟動(dòng)在設(shè)備上執(zhí)行的函數(shù) kernels 。這些內(nèi)核由許多 GPU 線程并行執(zhí)行。

鑒于 CUDA 編程模型的異構(gòu)性, CUDA C 程序的典型操作序列是:

聲明并分配主機(jī)和設(shè)備內(nèi)存。

初始化主機(jī)數(shù)據(jù)。

將數(shù)據(jù)從主機(jī)傳輸?shù)皆O(shè)備。

執(zhí)行一個(gè)或多個(gè)內(nèi)核。

將結(jié)果從設(shè)備傳輸?shù)街鳈C(jī)。

記住這個(gè)操作序列,讓我們看一個(gè) CUDA C 示例。

第一個(gè) CUDA C 程序

在最近的一篇文章中,我演示了 薩克斯比的六種方法 ,其中包括一個(gè) CUDA C 版本。 SAXPY 代表“單精度 A * X + Y ”,是并行計(jì)算的一個(gè)很好的“ hello world ”示例。在這篇文章中,我將剖析 CUDA C SAXPY 的一個(gè)更完整的版本,詳細(xì)解釋它的作用和原因。完整的 SAXPY 代碼是:

#include 

__global__
void saxpy(int n, float a, float *x, float *y)
{
 int i = blockIdx.x*blockDim.x + threadIdx.x;
 if (i < n) y[i] = a*x[i] + y[i];
}

int main(void)
{
  int N = 1<<20;
  float *x, *y, *d_x, *d_y;
  x = (float*)malloc(N*sizeof(float));
  y = (float*)malloc(N*sizeof(float));

  cudaMalloc(&d_x, N*sizeof(float));?
  cudaMalloc(&d_y, N*sizeof(float));

  for (int i = 0; i < N; i++) {
    x[i] = 1.0f;
    y[i] = 2.0f;
  }

  cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);
  cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);

  // Perform SAXPY on 1M elements
  saxpy<<<(N+255)/256, 256>>>(N, 2.0f, d_x, d_y);

  cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);

  float maxError = 0.0f;
  for (int i = 0; i < N; i++)
    maxError = max(maxError, abs(y[i]-4.0f));
  printf("Max error: %f
", maxError);

  cudaFree(d_x);
  cudaFree(d_y);
  free(x);
  free(y);
}

函數(shù)saxpy是在 GPU 上并行運(yùn)行的內(nèi)核,main函數(shù)是宿主代碼。讓我們從宿主代碼開始討論這個(gè)程序。

主機(jī)代碼

main 函數(shù)聲明兩對(duì)數(shù)組。

  float *x, *y, *d_x, *d_y;
  x = (float*)malloc(N*sizeof(float));
  y = (float*)malloc(N*sizeof(float));

  cudaMalloc(&d_x, N*sizeof(float));
  cudaMalloc(&d_y, N*sizeof(float));

指針x和y指向以典型方式使用malloc分配的主機(jī)陣列,d_x和d_y數(shù)組指向從CUDA運(yùn)行時(shí)API使用cudaMalloc函數(shù)分配的設(shè)備數(shù)組。CUDA中的主機(jī)和設(shè)備有獨(dú)立的內(nèi)存空間,這兩個(gè)空間都可以從主機(jī)代碼進(jìn)行管理(CUDAC內(nèi)核也可以在支持它的設(shè)備上分配設(shè)備內(nèi)存)。

然后,主機(jī)代碼初始化主機(jī)數(shù)組。在這里,我們?cè)O(shè)置了一個(gè) 1 數(shù)組,以及一個(gè) 2 數(shù)組。

  for (int i = 0; i < N; i++) {
    x[i] = 1.0f;
    y[i] = 2.0f;
  }

為了初始化設(shè)備數(shù)組,我們只需使用cudaMemcpy將數(shù)據(jù)從xy復(fù)制到相應(yīng)的設(shè)備數(shù)組d_xd_y,它的工作方式與標(biāo)準(zhǔn)的 Cmemcpy函數(shù)一樣,只是它采用了第四個(gè)參數(shù),指定了復(fù)制的方向。在本例中,我們使用cudaMemcpyHostToDevice指定第一個(gè)(目標(biāo))參數(shù)是設(shè)備指針,第二個(gè)(源)參數(shù)是主機(jī)指針。

  cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);
  cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);

在運(yùn)行內(nèi)核之后,為了將結(jié)果返回到主機(jī),我們使用cudaMemcpycudaMemcpyDeviceToHost,從d_y指向的設(shè)備數(shù)組復(fù)制到y指向的主機(jī)數(shù)組。

cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);

啟動(dòng)內(nèi)核

cord [EZX13 內(nèi)核由以下語(yǔ)句啟動(dòng):

saxpy<<<(N+255)/256, 256>>>(N, 2.0, d_x, d_y);

三個(gè) V 形符號(hào)之間的信息是 執(zhí)行配置 ,它指示有多少設(shè)備線程并行執(zhí)行內(nèi)核。在 CUDA 中,軟件中有一個(gè)線程層次結(jié)構(gòu),它模仿線程處理器在 GPU 上的分組方式。在 CUDA 編程模型中,我們談到啟動(dòng)一個(gè) grid 為 螺紋塊 的內(nèi)核。執(zhí)行配置中的第一個(gè)參數(shù)指定網(wǎng)格中線程塊的數(shù)量,第二個(gè)參數(shù)指定線程塊中的線程數(shù)。

線程塊和網(wǎng)格可以通過為這些參數(shù)傳遞 dim3 (一個(gè)由 CUDA 用 x 、 y 和 z 成員定義的簡(jiǎn)單結(jié)構(gòu))值來生成一維、二維或三維的線程塊和網(wǎng)格,但是對(duì)于這個(gè)簡(jiǎn)單的示例,我們只需要一維,所以我們只傳遞整數(shù)。在本例中,我們使用包含 256 個(gè)線程的線程塊啟動(dòng)內(nèi)核,并使用整數(shù)算術(shù)來確定處理數(shù)組( (N+255)/256 )的所有 N 元素所需的線程塊數(shù)。

對(duì)于數(shù)組中的元素?cái)?shù)不能被線程塊大小平均整除的情況,內(nèi)核代碼必須檢查內(nèi)存訪問是否越界。

清理

完成后,我們應(yīng)該釋放所有分配的內(nèi)存。對(duì)于使用 cudaMalloc() 分配的設(shè)備內(nèi)存,只需調(diào)用 cudaFree() 。對(duì)于主機(jī)內(nèi)存,請(qǐng)像往常一樣使用 free() 。

cudaFree(d_x);
  cudaFree(d_y);
  free(x);
  free(y);

設(shè)備代碼

現(xiàn)在我們繼續(xù)討論內(nèi)核代碼。

__global__
void saxpy(int n, float a, float *x, float *y)
{
 int i = blockIdx.x*blockDim.x + threadIdx.x;
 if (i < n) y[i] = a*x[i] + y[i];
}

在 CUDA 中,我們使用 __global__ de __global__ 說明符定義諸如 Clara 這樣的內(nèi)核。設(shè)備代碼中定義的變量不需要指定為設(shè)備變量,因?yàn)榧俣ㄋ鼈凂v留在設(shè)備上。在這種情況下, n 、 a 和 i 變量將由每個(gè)線程存儲(chǔ)在寄存器中,指針 x 和 y 必須是指向設(shè)備內(nèi)存地址空間的指針。這確實(shí)是真的,因?yàn)楫?dāng)我們從宿主代碼啟動(dòng)內(nèi)核時(shí),我們將 d_x 和 d_y 傳遞給了內(nèi)核。但是,前兩個(gè)參數(shù) n 和 a 沒有在主機(jī)代碼中顯式傳輸?shù)皆O(shè)備。因?yàn)楹瘮?shù)參數(shù)在 C / C ++中是默認(rèn)通過值傳遞的,所以 CUDA 運(yùn)行時(shí)可以自動(dòng)處理這些值到設(shè)備的傳輸。 CUDA 運(yùn)行時(shí) API 的這一特性使得在 GPU 上啟動(dòng)內(nèi)核變得非常自然和簡(jiǎn)單——這幾乎與調(diào)用 C 函數(shù)一樣。

在我們的 saxpy 內(nèi)核中只有兩行。如前所述,內(nèi)核由多個(gè)線程并行執(zhí)行。如果我們希望每個(gè)線程處理結(jié)果數(shù)組的一個(gè)元素,那么我們需要一種區(qū)分和標(biāo)識(shí)每個(gè)線程的方法。 CUDA 定義變量 blockDim 、 blockIdx 和 threadIdx 。這些預(yù)定義變量的類型為 dim3 ,類似于主機(jī)代碼中的執(zhí)行配置參數(shù)。預(yù)定義變量 blockDim 包含在內(nèi)核啟動(dòng)的第二個(gè)執(zhí)行配置參數(shù)中指定的每個(gè)線程塊的維度。預(yù)定義變量 threadIdx 和 blockIdx 分別包含線程塊中線程的索引和網(wǎng)格中的線程塊的索引。表達(dá)式:

    int i = blockDim.x * blockIdx.x + threadIdx.x

生成用于訪問數(shù)組元素的全局索引。我們?cè)谶@個(gè)例子中沒有使用它,但是還有一個(gè) gridDim ,它包含在啟動(dòng)的第一個(gè)執(zhí)行配置參數(shù)中指定的網(wǎng)格維度。

在使用該索引訪問數(shù)組元素之前,將根據(jù)元素的數(shù)量 n 檢查其值,以確保沒有越界內(nèi)存訪問。如果一個(gè)數(shù)組中的元素?cái)?shù)不能被線程塊大小平均整除,并且結(jié)果內(nèi)核啟動(dòng)的線程數(shù)大于數(shù)組大小,則需要進(jìn)行此檢查。內(nèi)核的第二行執(zhí)行 SAXPY 的元素級(jí)工作,除了邊界檢查之外,它與 SAXPY 主機(jī)實(shí)現(xiàn)的內(nèi)部循環(huán)相同。

if (i < n) y[i] = a*x[i] + y[i];

編譯和運(yùn)行代碼

CUDA C 編譯器 nvcc 是 NVIDIA CUDA 工具箱 的一部分。為了編譯我們的 SAXPY 示例,我們將代碼保存在一個(gè)擴(kuò)展名為。 cu 的文件中,比如說 saxpy.cu 。然后我們可以用 nvcc 編譯它。

nvcc -o saxpy saxpy.cu

然后我們可以運(yùn)行代碼:

% ./saxpy
Max error: 0.000000

總結(jié)與結(jié)論

通過對(duì) SAXPY 的一個(gè)簡(jiǎn)單的 CUDA C 實(shí)現(xiàn)的演練,您現(xiàn)在了解了編程 CUDA C 的基本知識(shí)。將 C 代碼“移植”到 CUDA C 只需要幾個(gè) C 擴(kuò)展:設(shè)備內(nèi)核函數(shù)的 __global__ de Clara 說明符;啟動(dòng)內(nèi)核時(shí)使用的執(zhí)行配置;內(nèi)置的設(shè)備變量 blockDim 、 blockIdx 和 threadIdx 用來識(shí)別和區(qū)分并行執(zhí)行內(nèi)核的 GPU 線程。

異類 CUDA 編程模型的一個(gè)優(yōu)點(diǎn)是,將現(xiàn)有代碼從 C 移植到 CUDA C 可以逐步完成,一次只能移植一個(gè)內(nèi)核。

在本系列的下一篇文章中,我們將研究一些性能度量和度量。

關(guān)于作者

Mark Harris 是 NVIDIA 杰出的工程師,致力于 RAPIDS 。 Mark 擁有超過 20 年的 GPUs 軟件開發(fā)經(jīng)驗(yàn),從圖形和游戲到基于物理的模擬,到并行算法和高性能計(jì)算。當(dāng)他還是北卡羅來納大學(xué)的博士生時(shí),他意識(shí)到了一種新生的趨勢(shì),并為此創(chuàng)造了一個(gè)名字: GPGPU (圖形處理單元上的通用計(jì)算)。

審核編輯:郭婷

聲明:本文內(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)投訴
  • 存儲(chǔ)器
    +關(guān)注

    關(guān)注

    39

    文章

    7739

    瀏覽量

    171679
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11279

    瀏覽量

    225016
  • gpu
    gpu
    +關(guān)注

    關(guān)注

    28

    文章

    5194

    瀏覽量

    135470
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    C語(yǔ)言與C++的區(qū)別及聯(lián)系

    C語(yǔ)言和C++到底是什么關(guān)系? 首先C++C語(yǔ)言本來就是兩種不同的編程語(yǔ)言,但C++確實(shí)是對(duì)C
    發(fā)表于 12-24 07:23

    CC++之間的聯(lián)系

    1、語(yǔ)法兼容性: C++完全兼容C語(yǔ)言的語(yǔ)法,這意味著任何有效的C語(yǔ)言程序都可以直接在C++編譯器下編譯通過。 2、底層控制: C++
    發(fā)表于 12-11 06:51

    C語(yǔ)言和C++之間的區(qū)別是什么

    區(qū)別 1、面向?qū)ο缶幊?(OOP): C語(yǔ)言是一種面向過程的語(yǔ)言,它強(qiáng)調(diào)的是通過函數(shù)將任務(wù)分解為一系列步驟進(jìn)行執(zhí)行。 C++C語(yǔ)言的基礎(chǔ)上擴(kuò)展了面向?qū)ο蟮奶匦?,支持?class)、封裝、繼承
    發(fā)表于 12-11 06:23

    為啥 AI 計(jì)算速度這么驚人?—— 聊聊 GPU、內(nèi)存與并行計(jì)算

    提到AI,大家常說它“算得快”,其實(shí)是指AI能在眨眼間處理海量數(shù)據(jù)??伤鼮樯队羞@本事?答案就藏在“GPU+高速內(nèi)存+并行計(jì)算”這trio(組合)里。咱們可以把AI要處理的數(shù)據(jù),想象成一大堆“小任務(wù)
    的頭像 發(fā)表于 12-05 14:35 ?870次閱讀
    為啥 AI <b class='flag-5'>計(jì)算</b>速度這么驚人?—— 聊聊 GPU、內(nèi)存與<b class='flag-5'>并行計(jì)算</b>

    一文看懂AI大模型的并行訓(xùn)練方式(DP、PP、TP、EP)

    大家都知道,AI計(jì)算(尤其是模型訓(xùn)練和推理),主要以并行計(jì)算為主。AI計(jì)算中涉及到的很多具體算法(例如矩陣相乘、卷積、循環(huán)層、梯度運(yùn)算等),都需要基于成千上萬的GPU,以并行任務(wù)的方式
    的頭像 發(fā)表于 11-28 08:33 ?1858次閱讀
    一文看懂AI大模型的<b class='flag-5'>并行</b>訓(xùn)練方式(DP、PP、TP、EP)

    C/C++代碼靜態(tài)測(cè)試工具Perforce QAC 2025.3的新特性

    ?Perforce Validate?中?QAC?項(xiàng)目的相對(duì)/根路徑的支持。C++?分析也得到了增強(qiáng),增加了用于檢測(cè) C++?并發(fā)問題的新檢查,并改進(jìn)了實(shí)體名稱和實(shí)
    的頭像 發(fā)表于 10-13 18:11 ?573次閱讀
    <b class='flag-5'>C</b>/<b class='flag-5'>C++</b>代碼靜態(tài)測(cè)試工具Perforce QAC 2025.3的新特性

    神經(jīng)網(wǎng)絡(luò)的并行計(jì)算與加速技術(shù)

    問題。因此,并行計(jì)算與加速技術(shù)在神經(jīng)網(wǎng)絡(luò)研究和應(yīng)用中變得至關(guān)重要,它們能夠顯著提升神經(jīng)網(wǎng)絡(luò)的性能和效率,滿足實(shí)際應(yīng)用中對(duì)快速響應(yīng)和大規(guī)模數(shù)據(jù)處理的需求。神經(jīng)網(wǎng)絡(luò)并行
    的頭像 發(fā)表于 09-17 13:31 ?1130次閱讀
    神經(jīng)網(wǎng)絡(luò)的<b class='flag-5'>并行計(jì)算</b>與加速技術(shù)

    從自然仿真到智能調(diào)度——GPU并行計(jì)算的多場(chǎng)景突破

    的體系結(jié)構(gòu),成為科學(xué)仿真與智能調(diào)度的核心計(jì)算平臺(tái)。在自然現(xiàn)象模擬中,風(fēng)沙流、流體力學(xué)等問題往往涉及海量粒子間的相互作用,計(jì)算負(fù)擔(dān)極為沉重,而GPU的并行鄰居搜索與空間
    的頭像 發(fā)表于 09-03 10:32 ?831次閱讀
    從自然仿真到智能調(diào)度——GPU<b class='flag-5'>并行計(jì)算</b>的多場(chǎng)景突破

    Kintex UltraScale 純 FPGA 開發(fā)平臺(tái),釋放高速并行計(jì)算潛能,高性價(jià)比的 FPGA 解決方案

    璞致電子PZ-KU060-KFB開發(fā)板采用Xilinx Kintex UltraScale KU060芯片,提供高密度并行計(jì)算能力,配備4GB DDR4內(nèi)存、20對(duì)GTH高速收發(fā)器和多種擴(kuò)展接口
    的頭像 發(fā)表于 08-18 13:28 ?725次閱讀
    Kintex UltraScale 純 FPGA 開發(fā)<b class='flag-5'>平臺(tái)</b>,釋放高速<b class='flag-5'>并行計(jì)算</b>潛能,高性價(jià)比的 FPGA 解決方案

    技能+1!如何在樹莓派上使用C++控制GPIO?

    在使用樹莓派時(shí),你會(huì)發(fā)現(xiàn)Python和Scratch是許多任務(wù)(包括GPIO編程)中最常用的編程語(yǔ)言。但你知道嗎,你也可以使用C++進(jìn)行GPIO編程,而且這樣做還有不少好處。借助WiringPi
    的頭像 發(fā)表于 08-06 15:33 ?4156次閱讀
    技能+1!如何在樹莓派上使用<b class='flag-5'>C++</b>控制GPIO?

    請(qǐng)問是否可以在通用Windows平臺(tái)中構(gòu)建OpenVINO? GenAI C++ 應(yīng)用程序?

    無法在通用 Windows 平臺(tái)中構(gòu)建OpenVINO? GenAI C++ 應(yīng)用程序
    發(fā)表于 06-24 07:35

    邊緣AI廣泛應(yīng)用推動(dòng)并行計(jì)算崛起及創(chuàng)新GPU滲透率快速提升

    是時(shí)候重新教育整個(gè)生態(tài)了。邊緣AI的未來不屬于那些高度優(yōu)化但功能狹窄的芯片,而是屬于可編程的、可適配的并行計(jì)算平臺(tái),它們能與智能軟件共同成長(zhǎng)并擴(kuò)展。
    的頭像 發(fā)表于 06-11 14:57 ?679次閱讀

    主流的 MCU 開發(fā)語(yǔ)言為什么是 C 而不是 C++

    在單片機(jī)的地界兒里,C語(yǔ)言穩(wěn)坐中軍帳,C++想分杯羹?難嘍。咱電子工程師天天跟那針尖大的內(nèi)存空間較勁,C++那些花里胡哨的玩意兒,在這兒真玩不轉(zhuǎn)。先說內(nèi)存這道坎兒。您當(dāng)stm32f4的256kRAM
    的頭像 發(fā)表于 05-21 10:33 ?1051次閱讀
    主流的 MCU 開發(fā)語(yǔ)言為什么是 <b class='flag-5'>C</b> 而不是 <b class='flag-5'>C++</b>?

    簡(jiǎn)單了解I2C接口

    在電子電路的復(fù)雜世界里,各種電路模塊設(shè)備需要相互通信才能協(xié)同工作 ,I2C接口就像是電路模塊設(shè)備間的溝通橋梁,今天就帶大家深入了解它。
    的頭像 發(fā)表于 05-08 14:15 ?2535次閱讀
    <b class='flag-5'>簡(jiǎn)單</b>了解I2<b class='flag-5'>C</b><b class='flag-5'>接口</b>

    讀懂極易并行計(jì)算:定義、挑戰(zhàn)與解決方案

    GPU經(jīng)常與人工智能同時(shí)提及,其中一個(gè)重要原因在于AI與3D圖形處理本質(zhì)上屬于同一類問題——它們都適用極易并行計(jì)算。什么是極易并行計(jì)算?極易并行計(jì)算指的是符合以下特征的計(jì)算任務(wù):任務(wù)獨(dú)
    的頭像 發(fā)表于 04-17 09:11 ?821次閱讀
    讀懂極易<b class='flag-5'>并行計(jì)算</b>:定義、挑戰(zhàn)與解決方案