GPU程式設計--CPU和GPU的設計區別

weixin_34054866發表於2018-05-07

本篇結構

  • 前言
  • 概論
  • CPU簡介
  • GPU簡介
  • 平行計算
  • CPU/GPU對比
  • 適於GPU計算的場景
  • GPU開發環境
  • 參考博文

一、前言

因為工作需要,需要從github上找一個CUDA的DBSCAN聚類實現,剛開始從github上獲取到的程式碼只支援二維資料,為了適配多維資料,要對程式碼簡單改造,這就需要了解CUDA程式設計模式。之前沒有接觸過GPU程式設計相關概念,甚至於沒有學過c語言,加上腦袋笨重,費了好些功夫,才讓CUDA DBSCAN執行起來。

為了方便自己後面回顧,所以將涉及到的知識點簡單串聯起來,並加以記錄。

如果可以,也希望給其他朋友一些參考(肯定是有很多不足,還望海涵)。

二、概論

由於其設計目標的不同,GPU和CPU分別針對了兩種不同的應用場景。

CPU需要很強的通用性來處理各種不同的資料型別,同時又要邏輯判斷又會引入大量的分支跳轉和中斷的處理。這些都使得CPU的內部結構異常複雜。

而GPU面對的則是型別高度統一的、相互無依賴的大規模資料和不需要被打斷的純淨的計算環境。

於是CPU和GPU就呈現出非常不同的架構(圖可以從CUDA官網找到https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#axzz4YFZTibzg):

7017386-4478ca059da72c36.png
CPU/GPU架構圖

三、CPU簡介

CPU (Central Processing Unit) 即中央處理器,是機器的“大腦”,也是佈局謀略、發號施令、控制行動的“總司令官”。

CPU的結構主要包括運算器(ALU, Arithmetic and Logic Unit)、控制單元(CU, Control Unit)、暫存器(Register)、快取記憶體器(Cache)和它們之間通訊的資料、控制及狀態的匯流排。

CPU是基於低延時的設計,簡單來說包括:計算單元、控制單元和儲存單元,架構可參考下圖:

7017386-d0f9b854b2ba83c5.png

CPU的特點是:

(1)CPU有強大的ALU(算術運算單元),它可以在很少的時鐘週期內完成算術計算

當今的CPU可以達到64bit 雙精度。執行雙精度浮點源算的加法和乘法只需要1~3個時鐘週期(CPU的時鐘週期的頻率是非常高的,達到1.532~3gigahertz(千兆HZ, 10的9次方))。

(2)大的快取可以降低延時

儲存很多的資料放在快取裡面,當需要訪問的這些資料,只要在之前訪問過的,如今直接在快取裡面取即可。

(3)複雜的邏輯控制單元

當程式含有多個分支的時候,它通過提供分支預測的能力來降低延時。
資料轉發。當一些指令依賴前面的指令結果時,資料轉發的邏輯控制單元決定這些指令在pipeline中的位置並且儘可能快的轉發一個指令的結果給後續的指令。這些動作需要很多的對比電路單元和轉發電路單元。

四、GPU簡介

GPU全稱為Graphics Processing Unit,中文為圖形處理器,就如它的名字一樣,GPU最初是用在個人電腦、工作站、遊戲機和一些移動裝置(如平板電腦、智慧手機等)上執行繪圖運算工作的微處理器。

GPU是基於大的吞吐量設計,GPU簡單架構參考下圖:

7017386-24fc192bb35bc045.png

GPU的特點是:

(1)有很多的ALU和很少的cache

快取的目的不是儲存後面需要訪問的資料的,這點和CPU不同,而是為thread提高服務的。如果有很多執行緒需要訪問同一個相同的資料,快取會合並這些訪問,然後再去訪問dram(因為需要訪問的資料儲存在dram中而不是cache裡面),獲取資料後cache會轉發這個資料給對應的執行緒,這個時候是資料轉發的角色。但是由於需要訪問dram,自然會帶來延時的問題。

(2)GPU的控制單元(左邊黃色區域塊)可以把多個的訪問合併成少的訪問。

(3)GPU的雖然有dram延時,卻有非常多的ALU和非常多的thread

為了平衡記憶體延時的問題,GPU可以充分利用多的ALU的特性達到一個非常大的吞吐量的效果。儘可能多的分配Threads。

五、平行計算

在對比CPU/GPU前,先了解下並行平行計算。

平行計算(Parallel Computing)是指同時使用多種計算資源解決計算問題的過程,是提高計算機系統計算速度和處理能力的一種有效手段。它的基本思想是用多個處理器來共同求解同一問題,即將被求解的問題分解成若干個部分,各部分均由一個獨立的處理機來平行計算。

平行計算可分為時間上的並行空間上的並行

時間上的並行是指流水線技術,比如說工廠生產食品的時候分為四步:清洗-消毒-切割-包裝。

如果不採用流水線,一個食品完成上述四個步驟後,下一個食品才進行處理,耗時且影響效率。但是採用流水線技術,就可以同時處理四個食品。這就是並行演算法中的時間並行,在同一時間啟動兩個或兩個以上的操作,大大提高計算效能。

空間上的並行是指多個處理機併發的執行計算,即通過網路將兩個以上的處理機連線起來,達到同時計算同一個任務的不同部分,或者單個處理機無法解決的大型問題。

比如小李準備在植樹節種三棵樹,如果小李1個人需要6個小時才能完成任務,植樹節當天他叫來了好朋友小紅、小王,三個人同時開始挖坑植樹,2個小時後每個人都完成了一顆植樹任務,這就是並行演算法中的空間並行,將一個大任務分割成多個相同的子任務,來加快問題解決速度。

六、CPU/GPU對比

CPU:

CPU的架構中需要大量的空間去放置儲存單元(橙色部分)和控制單元(黃色部分),相比之下計算單元(綠色部分)只佔據了很小的一部分,所以它在大規模平行計算能力上極受限制,而更擅長於邏輯控制。

CPU遵循的是馮諾依曼架構,其核心就是:儲存程式,順序執行。這使得CPU就像是個一板一眼的管家,人們吩咐的事情它總是一步一步來做。但是隨著人們對更大規模與更快處理速度的需求的增加,這位管家漸漸變得有些力不從心。

GPU:

GPU的構成相對簡單,有數量眾多的計算單元和超長的流水線,特別適合處理大量的型別統一的資料。

GPU的工作大部分都計算量大,但沒什麼技術含量,而且要重複很多很多次。GPU就是用很多簡單的計算單元去完成大量的計算任務,純粹的人海戰術。這種策略基於一個前提,就是平行計算的執行緒之間沒有什麼依賴性,是互相獨立的。

GPU在處理能力和儲存器頻寬上相對於CPU有明顯優勢,在成本和功耗上也不需要付出太大代價。由於圖形渲染的高度並行性,使得GPU可以通過增加並行處理單元和儲存器控制單元的方式提高處理能力和儲存器頻寬。GPU設計者將更多的電晶體用作執行單元,而不是像CPU那樣用作複雜的控制單元和快取並以此來提高少量執行單元的執行效率。

但GPU無法單獨工作,必須由CPU進行控制呼叫才能工作。CPU可單獨作用,處理複雜的邏輯運算和不同的資料型別,但當需要大量的處理型別統一的資料時,則可呼叫GPU進行平行計算。

另外:CPU的整數計算、分支、邏輯判斷和浮點運算分別由不同的運算單元執行,此外還有一個浮點加速器。因此,CPU面對不同型別的計算任務會有不同的效能表現。而GPU是由同一個運算單元執行整數和浮點計算,因此,GPU的整型計算能力與其浮點能力相似。

關於GPU和CPU,知乎上有個不是很雅觀的例子:

就像有個工作需要算幾億次一百以內加減乘除一樣,因為這些計算沒有太大的難度,一個辦法是僱上幾十個小學生一起算,一人算一部分,算是個體力活。

GPU就是這樣,用很多簡單的計算單元去完成大量的計算任務,純粹的人海戰術。但是這種策略基於一個前提,就是小學生A和小學生B的工作沒有什麼依賴性,是互相獨立的。很多涉及到大量計算的問題基本都有這種特性,比如你說的破解密碼,挖礦和很多圖形學的計算。這些計算可以分解為多個相同的簡單小任務,每個任務就可以分給一個小學生去做。

CPU就像老教授,積分微分都會算,就是工資高,一個老教授資頂二十個小學生。有一些任務並不是簡單的計算,二是涉及到“流”的問題。比如你去相親,雙方看著順眼才能繼續發展。總不能你這邊還沒見面呢,那邊找人把證都給領了。這種比較複雜的問題都是CPU來做的。

總而言之,因為最初用來處理的任務就不同,所以CPU和GPU設計上有不小的區別。GPU的運算速度取決於僱了多少小學生,CPU的運算速度取決於請了多麼厲害的教授。教授處理複雜任務的能力是碾壓小學生的,但是對於沒那麼複雜的任務,還是頂不住人多。當然現在的GPU也能做一些稍微複雜的工作了,相當於升級成初中生高中生的水平。但還需要CPU來把資料喂到嘴邊才能開始幹活,究竟還是靠CPU來管的。

七、適於GPU計算的場景

儘管GPU計算已經開始嶄露頭角,但GPU並不能完全替代X86解決方案。很多作業系統、軟體以及部分程式碼現在還不能執行在GPU上,所謂的GPU+CPU異構超級計算機也並不是完全基於GPU進行計算。一般而言適合GPU運算的應用有如下特徵:

  • 運算密集
  • 高度並行
  • 控制簡單
  • 分多個階段執行

GPU計算的優勢是大量核心的平行計算,瓶頸往往是I/O頻寬,因此適用於計算密集型的計算任務。

PS:所謂計算密集型(Compute-intensive)的程式,就是其大部分執行時間花在了暫存器運算上,暫存器的速度和處理器的速度相當,從暫存器讀寫資料幾乎沒有延時。可以做一下對比,讀記憶體的延遲大概是幾百個時鐘週期;讀硬碟的速度就不說了,即便是SSD,也實在是太慢了。

八、GPU開發環境

CG(C for Graphics)是為GPU程式設計設計的高階繪製語言,由NVIDIA和微軟聯合開發,微軟版本叫HLSL,CG是NVIDIA版本。Cg極力保留C語言的大部分語義,並讓開發者從硬體細節中解脫出來,Cg同時也有一個高階語言的其他好處,如程式碼的易重用性,可讀性得到提高,編譯器程式碼優化。

CUDA(ComputeUnified DeviceArchitecture,統一計算架構)是由NVIDIA所推出的一種整合技術,是該公司對於GPGPU的正式名稱。通過這個技術,使用者可利用NVIDIA的GeForce8以後的GPU和較新的QuadroGPU進行計算。亦是首次可以利用GPU作為C-編譯器的開發環境。NVIDIA營銷的時候,往往將編譯器與架構混合推廣,造成混亂。實際上,CUDA架構可以相容OpenCL或者自家的C-編譯器。無論是CUDAC-語言或是OpenCL,指令最終都會被驅動程式轉換成PTX程式碼,交由顯示核心計算。

ATIStream是AMD針對旗下圖形處理器(GPU)所推出的通用平行計算技術。利用這種技術可以充分發揮AMDGPU的並行運算能力,用於對軟體進行加速或進行大型的科學運算,同時用以對抗競爭對手的NVIDIA CUDA技術。與CUDA技術是基於自身的私有標準不同,ATIStream技術基於開放性的OpenCL標準。

OpenCL(Open Computing Language,開放計算語言)是一個為異構平臺編寫程式的框架,此異構平臺可由CPU,GPU或其他型別的處理器組成。OpenCL由一門用於編寫kernels(在OpenCL裝置上執行的函式)的語言(基於C99)和一組用於定義並控制平臺的API組成。OpenCL提供了基於任務分割槽和資料分割槽的平行計算機制。

OpenCL類似於另外兩個開放的工業標準OpenGL和OpenAL,這兩個標準分別用於三維圖形和計算機音訊方面。OpenCL擴充套件了GPU用於圖形生成之外的能力。OpenCL由非盈利性技術組織KhronosGroup掌管。

下面是對幾種GPU開發環境的簡單評價:

CG:優秀的圖形學學開發環境,但不適於GPU通用計算開發。

ATIStream:硬體上已經有了基礎,但只有低層次彙編才能使用所有的硬體資源。高層次的brook是基於上一代GPU的,缺乏良好的程式設計模型。

OpenCL:開放標準,抽象層次較低,較多對硬體的直接操作,程式碼需要根據不同硬體優化。

CUDA:僅能用於NVIDIA的產品,發展相對成熟,效率高,擁有豐富的文件資源。

九、參考博文

想更好理解CPU和GPU的區別,可以參考下面的博文:

通俗易懂告訴你CPU/GPU是什麼?
CPU和GPU的設計區別
GPU及相關技術簡介

相關文章