1. 程式人生 > >【CUDA並行程式設計系列(2)】CUDA簡介及CUDA初步程式設計

【CUDA並行程式設計系列(2)】CUDA簡介及CUDA初步程式設計

前言

CUDA並行程式設計系列是本人在學習CUDA時整理的資料,內容大都來源於對《CUDA並行程式設計:GPU程式設計指南》、《GPU高效能程式設計CUDA實戰》和CUDA Toolkit Documentation的整理。通過本系列整體介紹CUDA並行程式設計。內容包括GPU簡介、CUDA簡介、環境搭建、執行緒模型、記憶體、原子操作、同步、流和多GPU架構等。

本系列目錄:

本文對CUDA進行簡單介紹,並通過例項程式碼演示怎麼編寫在GPU上執行的程式碼,最後寫一段程式碼來查詢本機GPU的裝置引數。

CUDA C簡介

CUDA C是NVIDIA公司設計的一種程式語言,用於在GPU上得編寫通用計算程式,目前也叫“ CUDA C and C++”,或者“CUDA C/C++”。CUDA C是C語言的擴充套件,所以使用起來和C語言類似。當然,CUDA現在已經不侷限於C語言了,在NVIDIA ZONE的

LANGUAGE SOLUTIONS就明確支援多種語言和開發環境,如:C++、Python、Java、.Net、OpenACC、OpenCL等,作業系統也支援Linux、Mac OS、Windows。當然,前提是電腦至少配備一個支援CUDA的GPU,在NVIDIA官方可以檢視自己電腦的顯示卡是否支援CUDA。

GPU計算能力

在檢視某個顯示卡是否支援CUDA時,還會看到一個計算能力(Compute Capability)的引數。正如不同的CPU有著不同的功能和指令集,對於支援CUDA的GPU也同樣如此。NVIDIA將GPU支援的各種功能統稱為計算能力。硬體的計算能力是固定的。不同計算能力具有一定差別,如,在計算能力1.0版本不支援全域性記憶體上的原子操作。更高計算能力的GPU是低計算能力的超級,所以計算能力2.0支援的功能在3.0也全部支援。可以看到,目前GPU最高的計算能力已經達到5.3(Tegra X1)。

環境搭建

Hello,World!

新建一個檔案“hello_world.cu”

int main( void )
{
    printf( "Hello, World!\n" );
    return 0;
}

除了字尾”.cu”表示CUDA檔案,這段程式碼甚至不需要任何解釋,下面編譯並執行:

nvcc hello_world.cu
./a.out

輸出:

Hello, World!

我們使用nvcc命令編譯,這將使用CUDA C編譯器來編譯這段程式碼。

修改一下這段程式碼:

__global__  void kernel( void )
 {
}

int
main( void ) { kernel<<<1,1>>>(); printf( "Hello, World!\n" ); return 0; }

編譯執行結果還是一樣的,可以看到CUDA C為標準C增加了__global__修飾符,這個修飾符告訴編譯器,函式應該編譯為在裝置(Device)而不是主機(Host)上執行,CUDA把GPU稱為裝置(Device),把CPU稱為主機(Host),而在GPU裝置上執行的函式稱為核函式(Kernel),在裝置上執行的函式需要增加__global____device__修飾符。

呼叫核函式增加了<<<1,1>>>修飾符,其它沒有任何變化。當然,這段程式碼GPU並沒有做什麼實際的工作,下面讓GPU實際做點事情。

GPU上的加法

修改上面的程式碼:

__global__  void add( int a, int b, int *c )
{
    *c = a + b;
}

int main( void )
{
    int c;
    int *dev_c;
    cudaMalloc( &dev_c, sizeof(int) ) ;

    add<<<1,1>>>( 2, 7, dev_c );

    cudaMemcpy( &c, dev_c, sizeof(int),cudaMemcpyDeviceToHost );
    printf( "2 + 7 = %d\n", c );
    cudaFree( dev_c );

    return 0;
}

主機呼叫核函式add做加法運算,函式add將在GPU上執行。需要注意的是,主機和裝置在物理上處於不同的位置,使用了不同的記憶體,核函式不能直接使用主機上儲存的資料,同樣主機也不能直接使用裝置上儲存的資料,資料需要在主機和裝置之間傳輸。

在裝置上分配記憶體使用cudaMalloc(),該函式類似malloc()。在執行完add函式後,計算結果儲存在裝置的記憶體上,還需要使用cudaMemcpy()傳輸到主機記憶體上,引數cudaMemcpyDeviceToHost表示從裝置傳輸到主機。顯然,cudaMemcpyHostToDevice表示從主機傳輸到裝置,cudaMemcpyDeviceToDevice表示從裝置傳輸到另一個裝置。

至此,一個完整地CUDA C程式碼已經實現,下面來寫一段程式碼查詢顯示卡的裝置引數。

查詢裝置

在進行CUDA並行程式設計之前,對自己PC機的GPU裝置效能及相關資訊的瞭解是很有必要的,下面寫一段程式碼來查詢裝置引數資訊。

查詢裝置時會用的幾個函式:

  1. cudaGetDeviceCount(),獲得CUDA裝置的數量,一臺PC可能會有多個CUDA裝置,可以通過這個函式查詢。
  2. cudaGetDeviceProperties(),通過裝置編號查詢裝置屬性,裝置編號從0開始。裝置屬性儲存在cudaDeviceProp結構體中,具體結構可檢視cudaDeviceProp Struct Reference

完整程式碼如下:

int main(void)
{
      cudaDeviceProp prop;
      int count;

      cudaGetDeviceCount(&count);
      printf("cuda device count: %d\n", count);

      for (int i = 0; i < count; ++i)
      {
            cudaGetDeviceProperties(&prop, i);

            printf ("    ---  General Information for device %d ------\n", i);
            printf ("Name: %s\n", prop.name);
            printf ( "Compute capability: %d.%d\n", prop.major, prop.minor );
            printf ( "Clock rate: %d \n", prop.clockRate );
            printf( "Device copy overlap: ");
            if (prop.deviceOverlap)
            {
                  printf ( "Enabled\n");
            }
            else
            {
                  printf ( "Disabled\n" );
            }
            printf ( "Kernel execiton timeout: " );
            if (prop.kernelExecTimeoutEnabled )
            {
                  printf ( "Enabled\n" );
            }
            else
            {
                  printf ( "Disabled\n" );
            }
            printf ("integrated:");
            if (prop.integrated)
            {
                  printf("true\n");
            }
            else
            {
                  printf("false\n");
            }
            printf ( "--- Memory Information for device %d ----\n", i);
            printf ( "Total global mem: %ld\n", prop.totalGlobalMem );
            printf ( "Total constant Mem: %ld\n", prop.totalConstMem );
            printf ("Max mem pitch: %ld\n", prop.memPitch );
            printf ( "Texture Alignment: %ld\n", prop.textureAlignment );
            printf ( "  --- MP Information for device %d ---\n", i );
            printf ( "Multiprocessor count: %d\n", prop.multiProcessorCount );
            printf ( "Shared mem per mp: %ld\n", prop.sharedMemPerBlock );
            printf ("Registers per mp: %d\n", prop.regsPerBlock );
            printf ("Threads in warp: %d\n", prop.warpSize );
            printf ("Max threads per block: %d\n", prop.maxThreadsPerBlock );
            printf ("Max thread dimensions: ( %d %d %d )\n", prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2] );
            printf ("Max grid dimensions: ( %d %d %d )", prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2] );
            printf ("\n");
      }

      return 0;
}

執行這段程式碼,就可以知道自己PC機配備GPU的具體資訊,這對以後寫程式碼是很重要的。

參考文獻

相關推薦

CUDA並行程式設計系列2CUDA簡介CUDA初步程式設計

前言 CUDA並行程式設計系列是本人在學習CUDA時整理的資料,內容大都來源於對《CUDA並行程式設計:GPU程式設計指南》、《GPU高效能程式設計CUDA實戰》和CUDA Toolkit Documentation的整理。通過本系列整體介紹CUDA並行程式設

CUDA並行程式設計系列4CUDA記憶體

前言 CUDA並行程式設計系列是本人在學習CUDA時整理的資料,內容大都來源於對《CUDA並行程式設計:GPU程式設計指南》、《GPU高效能程式設計CUDA實戰》和CUDA Toolkit Documentation的整理。通過本系列整體介紹CUDA並行程

CUDA並行程式設計系列1GPU技術簡介

前言 CUDA並行程式設計系列是本人在學習CUDA時整理的資料,內容大都來源於對《CUDA並行程式設計:GPU程式設計指南》、《GPU高效能程式設計CUDA實戰》和CUDA Toolkit Documentation的整理。通過本系列整體介紹CUDA並行程式設

不容錯過,最全的安卓架構合集從零開始搭建android框架系列2

安卓架構文章合集(a collection of android Architecture) 部落格原地址: 簡書部落格 github地址: 這是從各大平臺上參考的android架構文章,文章資料,主要參考自Info,推薦關注: infoQ 1 Android

C++11併發/多執行緒程式設計系列2

std::thread詳解 std::thread在標頭檔案<thread>中宣告,因此使用 std::thread 時需要包含 <thread>標頭檔案。 default(1) thread() noexcept;

vtk.js學習筆記2繪製紋理深度圖

在vtk.js學習筆記(1)中搭建好了vtk.js的開發環境,並繪製了一個圓錐,這篇筆記將通過繪製一個帶深度資訊的紋理圖繼續學習vtk.js,實際效果如下圖所示。1、通過vtkElevationReader實現帶深度資訊的紋理對映import vtkTexture from

金陽光測試基於控件核心技術探討---Android自己主動化系列2---2013年5月

進程 實用 版本 信號 監聽 dialog otto 設計 核心技術 第一講分享了下安卓自己主動化一些概況和一些自己主動化框架現狀和技術可以解決什麽樣的問題。這次課就深入到android世界裏面。遨遊、翺翔。深入了解自己主動化測試核心技術。

CUDA程式設計2其實寫個矩陣相乘並不是那麼難

程式程式碼及圖解析:123456789101112131415161718#include <iostream>#include "book.h"__global__ void add( int a, int b, int *c ) {    *c = a + b

ABAP自學系列

發的 img api .cn ima code pat 查看 屏幕 一、查看補丁包級別 然後看Patch Level即可。 常用T-code: SE38(寫程序) SE80(屏幕開發) Smartform(開發smartform打印) SE37(可以查看function

開源OSharp框架學習系列1:總體設計系列導航

正是 html 組織 內聚性 權限 是什麽 enc 3-0 分發 OSharp是什麽?   OSharp是個快速開發框架,但不是一個大而全的包羅萬象的框架,嚴格的說,OSharp中什麽都沒有實現。與其他大而全的框架最大的不同點,就是OSharp只做抽象封裝,不做實現。依賴註

SQL從零到迅速精通實用函數2

表的操作 deny 獲取 拒絕 分享 子字符串 evo sci ever 1.對查詢結果進行排序 查詢stu_info表中所有學生信息,並按照成績由高到底進行排序,輸入語句如下。 SELECT * FROM stu_info ORDER BY s_score DESC;

C++14系列2:C/C++的時間函數

復習 -a 執行時間 htm 結果 down pro addclass data- C++筆記開始 為了好好研究下C++14。順便復習下曾經的C++知識。搞了個git(不斷完好中): https://github.com/rododo/cpp14ex

[轉]微信小程序之加載更多分頁加載實例 —— 微信小程序實戰系列2

是否 底部 watermark water ongl 小程序教程 所有 空數組 osi 本文轉自;http://blog.csdn.net/michael_ouyang/article/details/56846185 loadmore 加載更多(分頁加載) 當

編程思考系列2字段與屬性

面向對象 都是 實時 valid class ria body 之間 系列 字段(fields)與屬性(properties)的定義 字段與屬性都是OOP(面向對象編程)中的概念。 字段是指封裝在類或對象中的數據,因此也被叫做數據成員(data member)或成員變量(

領域驅動設計系列2淺析VO、DTO、DO、PO的概念、區別和用處

服務 完全 session 並且 main 解決 業務 導致 teacher   上一篇文章作為一個引子,說明了領域驅動設計的優勢,從本篇文章開始,筆者將會結合自己的實際經驗,談及領域驅動設計的應用。本篇文章主要討論一下我們經常會用到的一些對象:VO、DTO、DO和PO。

信息安全系列2--信息安全基礎

適應性 而不是 信息 進一步 理論 威脅 大數據 關鍵詞 www. 我們分析一個事物的時候,都是希望能全面的了解事物,而不是片面的看到局部;都是希望能從根本上掌握事務的本質和規律,而不是只是停留在表面現象;都是希望能有一些行動上的指導,而不是停留在理論與概念上。這裏,堂主借

爬蟲系列2-----python爬取CSDN博客首頁所有文章

成功 -name 保存 eas attr eve lan url att 對於Python初學者來說,爬蟲技能是應該是最好入門,也是最能夠有讓自己有成就感的,今天在整理代碼時,整理了一下之前自己學習爬蟲的一些代碼,今天上第2個簡單的例子,python爬取CSDN博客首頁所有

區塊鏈技術系列2 - 環形簽名

情況 rsa ima 創建 語音 基於 密碼 div tps 前言 在密碼學中,環簽名是一種數字簽名,其可以由每個具有密鑰的一組用戶的任何成員完成。因此,使用環簽名簽名的消息由特定人群中的某一人簽署。環簽名的一個安全屬性是若要確定哪個組成員的密鑰用於產生簽名在計算上是不可行

部署Django到雲伺服器centos+nginx+mysql+uwsgi+python3操作篇2

接上篇操作篇(1):https://blog.csdn.net/jacky_zhuyuanlu/article/details/82880612 (七)建立Django專案 (1)建立資料夾,存放網站 mkdir -p /data/wwwroot

Python菜鳥快樂遊戲程式設計_pygame2

Python菜鳥快樂遊戲程式設計_pygame(博主錄製,2K解析度,超高清) https://study.163.com/course/courseMain.htm?courseId=1006188025&share=2&shareId=400000000398149