[Hotball's Hive]CUDA 教学-1

来源:互联网 发布:星际争霸1兵种数据 编辑:程序博客网 时间:2024/03/29 12:39
 

[Hotball's Hive]CUDA 簡介

現代的顯示晶片已經具有高度的可程式化能力,由於顯示晶片通常具有相當高的記憶體頻寬,以及大量的執行單元,因此開始有利用顯示晶片來幫助進行一些計算工作的想法,即 GPGPU。CUDA 即是 NVIDIA 的 GPGPU 模型。

NVIDIA 的新一代顯示晶片,包括 GeForce 8 系列及更新的顯示晶片都支援 CUDA。NVIDIA 免費提供 CUDA 的開發工具(包括 Windows 版本和 Linux 版本)、程式範例、文件等等,可以在 CUDA Zone 下載。

GPGPU 的優缺點

使用顯示晶片來進行運算工作,和使用 CPU 相比,主要有幾個好處:

  1. 顯示晶片通常具有更大的記憶體頻寬。例如,NVIDIA 的 GeForce 8800GTX 具有超過 50GB/s 的記憶體頻寬,而目前高階 CPU 的記憶體頻寬則在 10GB/s 左右。
  2. 顯示晶片具有更大量的執行單元。例如 GeForce 8800GTX 具有 128 個 "stream processors",時脈為 1.35GHz。CPU 時脈通常較高,但是執行單元的數目則要少得多。
  3. 和高階 CPU 相比,顯示卡的價格較為低廉。例如目前一張 GeForce 8800GT 包括 512MB 記憶體的價格,和一顆 2.4GHz 四核心 CPU 的價格相若。

當然,使用顯示晶片也有它的一些缺點:

  1. 顯示晶片的運算單元數量很多,因此對於不能高度平行化的工作,所能帶來的幫助就不大。
  2. 顯示晶片目前通常只支援 32 bits 浮點數,且多半不能完全支援 IEEE 754 規格, 有些運算的精確度可能較低。目前許多顯示晶片並沒有分開的整數運算單元,因此整數運算的效率較差。
  3. 顯示晶片通常不具有分支預測等複雜的流程控制單元,因此對於具有高度分支的程式,效率會比較差。
  4. 目前 GPGPU 的程式模型仍不成熟,也還沒有公認的標準。例如 NVIDIA 和 AMD/ATI 就有各自不同的程式模型。

整體來說,顯示晶片的性質類似 stream processor,適合一次進行大量相同的工作。CPU 則比較有彈性,能同時進行變化較多的工作。

CUDA 架構

CUDA 是 NVIDIA 的 GPGPU 模型,它使用 C 語言為基礎,可以直接以大多數人熟悉的 C 語言,寫出在顯示晶片上執行的程式,而不需要去學習特定的顯示晶片的指令或是特殊的結構。

在 CUDA 的架構下,一個程式分為兩個部份:host 端和 device 端。Host 端是指在 CPU 上執行的部份,而 device 端則是在顯示晶片上執行的部份。Device 端的程式又稱為 "kernel"。通常 host 端程式會將資料準備好後,複製到顯示卡的記憶體中,再由顯示晶片執行 device 端程式,完成後再由 host 端程式將結果從顯示卡的記憶體中取回。

arch1-medium 

由於 CPU 存取顯示記憶體時只能透過 PCI Express 介面,因此速度較慢(PCI Express x16 的理論頻寬是雙向各 4GB/s),因此不能太常進行這類動作,以免降低效率。

在 CUDA 架構下,顯示晶片執行時的最小單位是 thread。數個 thread 可以組成一個 block。一個 block 中的 thread 能存取同一塊共用的記憶體,而且可以快速進行同步的動作。

每一個 block 所能包含的 thread 數目是有限的。不過,執行相同程式的 block,可以組成 grid。不同 block 中的 thread 無法存取同一個共用的記憶體,因此無法直接互通或進行同步。因此,不同 block 中的 thread 能合作的程度是比較低的。不過,利用這個模式,可以讓程式不用擔心顯示晶片實際上能同時執行的 thread 數目限制。例如,一個具有很少量執行單元的顯示晶片,可能會把各個 block 中的 thread 循序執行,而非同時執行。不同的 grid 則可以執行不同的程式(即 kernel)。

Grid、block 和 thread 的關係,如下圖所示:

arch2-large 

每個 thread 都有自己的一份 register 和 local memory 的空間。同一個 block 中的每個 thread 則有共用的一份 share memory。此外,所有的 thread(包括不同 block 的 thread)都共用一份 global memory、constant memory、和 texture memory。不同的 grid 則有各自的 global memory、constant memory 和 texture memory。這些不同的記憶體的差別,會在之後討論。

執行模式

由於顯示晶片大量平行計算的特性,它處理一些問題的方式,和一般 CPU 是不同的。主要的特點包括:

  1. 記憶體存取 latency 的問題:CPU 通常使用 cache 來減少存取主記憶體的次數,以避免記憶體 latency 影響到執行效率。顯示晶片則多半沒有 cache(或很小),而利用平行化執行的方式來隱藏記憶體的 latency(即,當第一個 thread 需要等待記憶體讀取結果時,則開始執行第二個 thread,依此類推)。
  2. 分支指令的問題:CPU 通常利用分支預測等方式來減少分支指令造成的 pipeline bubble。顯示晶片則多半使用類似處理記憶體 latency 的方式。不過,通常顯示晶片處理分支的效率會比較差。

因此,最適合利用 CUDA 處理的問題,是可以大量平行化的問題,才能有效隱藏記憶體的 latency,並有效利用顯示晶片上的大量執行單元。使用 CUDA 時,同時有上千個 thread 在執行是很正常的。因此,如果不能大量平行化的問題,使用 CUDA 就沒辦法達到最好的效率了。