CUDA

**CUDA**（**C**ompute **U**nified **D**evice **A**rchitecture，**統一計算架構**）是由輝達 NVIDIA 所推出的一種整合技術，是該公司對於 GPGPU 的正式名稱。透過這個技術，使用者可利用 NVIDIA 的 GPU 進行圖像處理之外的運算，亦是首次可以利用 GPU 作為 C - 編譯器的開發環境。CUDA 開發套件（CUDA Toolkit ）只能將自家的 CUDA C - 語言（對 OpenCL 只有連結的功能），也就是執行於 GPU 的部分編譯成 PTX 中間語言或是特定 NVIDIA GPU 架構的機器碼（NVIDIA 官方稱為 "device code"）；而執行於中央處理器部分的 C / C++ 程式碼（NVIDIA 官方稱為 "host code"）仍依賴於外部的編譯器，如 Microsoft Windows 下需要 Microsoft Visual Studio；Linux 下則主要依賴於 GCC。

## 簡介

GPU 不僅用於進行圖形彩現，而且用於物理運算（物理效果如碎片、煙、火、流體）如 PhysX 和 Bullet。進一步的，GPU 可以用在計算生物學與密碼學等領域的非圖形應用上。在 NVIDIA 收購 AGEIA 後，NVIDIA 取得相關的物理加速技術，即是 PhysX 物理引擎。配合 CUDA 技術，顯示卡可以類比成一顆 PhysX 物理加速晶片。目前，全系列的 GeForce 8 顯示核心都支援 CUDA。而 NVIDIA 亦不會再推出任何的物理加速卡，顯示卡將會取代相關產品。

而使用 CUDA 技術，GPU 可以用來進行通用處理（不僅僅是圖形）；這種方法被稱為 GPGPU。與 CPU 不同的是，GPU 以較慢速度並行大量執行緒，而非快速執行單一執行緒。以 GeForce 8800 GTX 為例，其核心擁有 128 個內處理器。利用 CUDA 技術，就可以將那些內處理器做為執行緒處理器，以解決資料密集的計算。而各個內處理器能夠交換、同步和共享資料。GeForce 8800 GTX 的運算能力可達到 520GFlops，如果建設 SLI 系統，就可以達到 1TFlops。

目前，已有軟體廠商利用 CUDA 技術，研發出 Adobe Premiere Pro 的外掛程式。通過外掛程式，使用者就可以利用顯示核心去加速 H.264/MPEG-4 AVC 的編碼速度。速度是單純利用 CPU 作軟體加速的 7 倍左右。

雖然 CUDA 底層是以 C/C++ 為主，並以使用「NVCC」——NVIDIA 基於 LLVM 的 C/C++ 編譯器介面來進行編譯，但程式師也可以使用編譯器指令（如 OpenACC）以及多種程式設計語言擴展對 CUDA 平臺進行操作。如 Fortran 程式師可以使用「CUDA Fortran」，或 PGI 公司的 PGI CUDA Fortran 編譯器進行編譯。除了此之外 CUDA 平臺還支援其它計算介面，如 Khronos Group 的 OpenCL，Microsoft 的 DirectCompute，以及 C++AMP。也可以透過其他語言如 Python，Perl，Java，Ruby，Lua，Haskell，MATLAB，IDL 及 Mathematica 的介面間接調用 CUDA。

CUDA 最初的 CUDA 軟體發展包（SDK）於 2007 年 2 月 15 日公佈，同時支援 Microsoft Windows 和 Linux。而後在第二版中加入對 Mac OS X 的支援 (但於 CUDA Toolkit 10.2 起放棄對 macOS 的支援)，取代 2008 年 2 月 14 日發佈的測試版。所有 G8x 系列及以後的 NVIDIA GPUs 皆支援 CUDA 技術，包括 GeForce，Quadro 和 Tesla 系列。CUDA 與大多數標準作業系統相容。Nvidia 聲明：根據二進位相容性，基於 G8x 系列開發的程式無需修改即可在未來所有的 Nvidia 顯示卡上運行。

## 優點

在 GPUs（GPGPU）上使用圖形 APIs 進行傳統通用計算，CUDA 技術有下列幾個優點：

* 分散讀取 —— 代碼可以從記憶體的任意位址讀取
* 統一虛擬記憶體（Unified Memory, 從 CUDA 6.0 開始）—— 將所有 CPU 和 GPU 的記憶體置於統一管理的虛擬記憶體空間下。
* 共享記憶體（Global Memory）—— 存取快速的區域，使之在多個執行緒間共享，有效頻寬比紋理記憶體（Texture Memory）更大。
* 與 GPU 之間更快的下載與回讀
* 全面支援整型與位元運算，包括整型紋理尋找

## 限制

* CUDA 不支援完整的 C 語言標準。它在 C++ 編譯器上運行主機程式碼時，會使一些在 C 中合法（但在 C++ 中不合法）的代碼無法編譯。
* 不支援紋理彩現（CUDA 3.2 及以後版本通過在 CUDA 陣列中引入「表面寫操作」—— 底層的不透明資料結構 —— 來進行處理）
* 受系統主線的頻寬和延遲的影響，主機與裝置記憶體之間資料複製可能會導致效能下降（通過過 GPU 的 DMA 引擎處理，非同步記憶體傳輸可在一定範圍內緩解此現象）
* 當執行緒總數為數千時，執行緒應按至少 32 個一組來運行才能獲得最佳效果。如果每組中的 32 個執行緒使用相同的執行路徑，則程式分支不會顯著影響效果；在處理本質上不同的任務時，單指令流多資料流執行模型將成為一個瓶頸（如在光線追蹤演算法中遍歷一個空間分割的資料結構）
* 只有 NVIDIA 的 GPUs 支援 CUDA 技術
* 由於編譯器需要使用優化技術來利用有限的資源，即使合法的 C/C++ 有時候也會被標記並中止編譯
* CUDA（計算能力 1.x）使用一個不包含遞迴、函式指標的 C 語言子集，外加一些簡單的擴展。而單個進程必須運行在多個不相交的記憶體空間上，這與其它 C 語言運行環境不同。
* CUDA（計算能力 2.x）允許 C++ 類功能的子集，如成員函式可以不是虛擬的（這個限制將在以後的某個版本中移除）[參見《CUDA C 程式設計指南 3.1》－附錄 D.6]
* 雙精度浮點（CUDA 計算能力 1.3 及以上）與 IEEE754 標準有所差異：倒數、除法、平方根僅支援捨入到最近的偶數。單精確度中不支援反常值（denormal）及 sNaN（signaling NaN）；只支援兩種 IEEE 捨入模式（舍位與捨入到最近的偶數），這些在每條指令的基礎上指定，而非控制字碼；除法 / 平方根的精度比單精確度略低。

## 顯示卡的受支援情況

'\*' – 僅限 OEM 產品

詳情請參見 Nvidia（頁面存檔備份，存於網際網路檔案館）:

## 應用

利用 CUDA 技術，配合適當的軟體（例如 MediaCoder、Freemake Video Converter），就可以利用顯示核心進行高畫質影片編碼加速。影片解碼方面，同樣可以利用 CUDA 技術實現。此前，NVIDIA 的顯示核心本身已整合 PureVideo 單元。可是，實現相關加速功能的一個微軟 API－DXVA，偶爾會有加速失效問題。所以利用 CoreAVC 配合 CUDA，變相在顯示核心上實現軟體解碼，解決相容性問題。另外，配合適當的引擎，顯示核心就可以計算光線跟蹤。NVIDIA 就放出了自家的 Optix 即時光線跟蹤引擎，透過 CUDA 技術利用 GPU 計算光線跟蹤。

## 支援的產品

所有基於 G80 及之後架構的民用與專業顯示卡或運算模組皆支援 CUDA 技術。

## 範例

### CUDA Driver API

下面將示範以最底層的 CUDA Driver API （頁面存檔備份，存於網際網路檔案館）調用 GPU 做列向量的加法，**以下為 CPU 端的程式碼**

**而以下是 GPU 端的程式碼**

### CUDA Runtime API

下列的範例是以相較於 Driver API 來說比較簡便的 CUDA Runtime API （頁面存檔備份，存於網際網路檔案館） 做列向量的加法：

### Python

以下以 pycuda （頁面存檔備份，存於網際網路檔案館），間接調用 CUDA 做列向量的阿達瑪乘積 (也就是元素間乘積而非內積)

也可以用 pycublas 間接調用 CUDA ，來計算矩陣乘法

## 相關條目

* OpenCL
* Vulkan

## 參考文獻

## 外部連結

* 官方網站
* 周秉誼. GPU 高效能運算環境 —CUDA 與 GPU Cluster 介紹。台灣大學計算機及資訊網路中心. [2010-12-05]. （原始內容存檔於 2010-05-16） （中文（繁體））.