CUDA 是什麼?你的工作有大量重複計算嗎?那就要搞懂 CUDA

CUDA 是由 NVIDIA 推出的平行運算架構,讓 GPU 不只是拿來打電動,而是能處理通用型運算任務(GPGPU)。本文用淺顯易懂的方式,拆解 CUDA 架構與執行流程,從 G80 顯示卡開始,讓你理解 GPU 如何改變平行運算世界。

首先,你不要再看那些根本沒有研究過 GPU 的人在寫 CUDA 的文章了,他們會害死你,他們只是要 CUDA 這個關鍵字的流量,尤其是財金網站上的內容。

辛普森風格的校園大掃除場景,學生們(代表 Thread)在不同班級(代表 Block)中同時擦窗戶、掃地和整理書架,象徵著 CUDA 平行運算模型中 CPU 如何協調 GPU 執行大量任務。

為什麼「不是 CPU 來算」?GPU 是怎麼崛起的?

先講結論:GPU 是拿來跑大量「一樣的事情」的怪物。

當 CPU 一次只能專心做幾件事(靠快取與分支預測來彌補),GPU 的策略就是直接開好幾百個小核心,全部丟進去一起算,而這就是平行運算的本質。

但問題來了,早期你想用 GPU 做這件事,要靠 OpenGL、DirectX 這種圖形 API 想辦法繞出來搞 GPGPU。整個開發體驗卡到爆,根本不是為了做通用運算設計的。

NVIDIA 在 2006 推出 G80 晶片時,同時發表了 CUDA 架構,這才真正讓 GPU 平行運算邁進主流。

CUDA 是什麼?不是語言,而是一整套平行運算平台

CUDA 全名是 Compute Unified Device Architecture,是一個讓開發者可以用 C 語言去控制 GPU 執行一般運算任務的開發架構。

簡單說,CUDA 把 GPU「解放出來」,不再只能跑圖形,而是變成一顆平行運算協同處理器(co-processor),由 CPU 控制、GPU 加速。

G80 架構開啟了統一架構(Unified Architecture)

NVIDIA 在於 G80 晶片導入的「統一架構」概念。以前 GPU 是一塊一塊功能分工(Vertex、Pixel)的硬體單元,而 G80 開始,把這些處理器整合成 128 個可程式化的 Stream Processors(SP),每個都是能處理浮點運算的 ALU。

每個 SP 能獨立執行指令,還能關閉做成低階版型號,整塊 G80 晶片有:

  • 128 個 SP,分成 8 個 Block,每個 Block 裝 16 顆 SP
  • 每個 Block 有自己的 texture unit、filter unit、shared memory
  • 支援 348-bit 記憶體頻寬,用 GDDR3 做顯示記憶體

這讓 GPU 不再只是「畫畫(3D圖形)」,而是可以拿來「算數學」。

CUDA 平行運算模型:Thread、Block、Grid 是什麼?

假設今天學校要進行「全校大掃除」,校長(GPU)要分配工作給所有學生(Thread)。但學生太多,直接分配會很亂,所以校長用以下方式組織:

Thread(執行緒)→ 最小工作單位 = 「一個學生」

  • 每個學生負責「一個具體任務」,例如:
    • 學生A:擦第1扇窗戶
    • 學生B:擦第2扇窗戶
    • …(每個學生做一件事)

Block(區塊)→ 一組學生 = 「一個班級」

  • 一個班級(Block)裡有多個學生(Thread),例如:
    • 1年1班(Block 0):學生A、B、C…(共1024人)
    • 1年2班(Block 1):學生D、E、F…(共1024人)
  • 班級內的特點:
    • 學生可以互相幫忙(共享記憶體)。
    • 班長可以協調工作(Block內同步)。
    • 但不同班級的學生不能直接溝通(Block之間獨立)。

Grid(網格)→ 所有班級 = 「全校」

  • 全校(Grid)由所有班級(Block)組成,例如:
    • 1年級(Block 0~10)、2年級(Block 11~20)…
  • 校長(GPU)的指令:
    • 校長廣播:「現在全校擦窗戶!」(一個Kernel指令)。
    • 每個班級(Block)收到指令後,分配給自己的學生(Thread)執行。

為什麼要這樣分層?

  1. 每個 Block 只能容納有限數量 Thread(例如 1024)
  2. 有了 Grid,就能無限 scale(幾萬、幾十萬筆資料一起處理)
  3. 每個 Thread / Block 都有自己的 ID,可以定位資料在處理陣列中的位置

而這樣的分層帶來的好處是:

  1. 效率問題
    • 如果校長直接管1萬個學生(Thread),會累死(管理成本高)。
    • 透過班級(Block)分層,校長只需管班長,班長再管學生。
  2. 資源限制
    • 一個班級(Block)最多只能有1024人(硬體限制)。
    • 但全校(Grid)可以有無限多班級,所以能處理超大型任務(例如幾十萬扇窗戶)。
  3. 分工明確
    • 每個學生(Thread)知道自己負責哪扇窗(透過ID定位)。
    • 例如:學生ID=5 → 擦第5扇窗;班級ID=3 → 負責3樓的窗戶。

這種模型讓資料可以被「一份邏輯」但「多個資料」同時處理(SIMD),非常適合影像處理、矩陣運算、模擬等平行性高的任務,例如:

  • 影像處理
    • 一張圖片有100萬畫素 → 用100萬個Thread(每個Thread處理1畫素)。
    • 這些Thread分到多個Block(例如1024 Threads/Block),最後組成一個Grid。
  • 科學計算
    • 矩陣運算時,每個Thread算一個格子,Block和Grid幫你自動分配任務。

CUDA 記憶體模型:不是一堆 RAM,就能跑得快

很多人以為 GPU 快,是記憶體大、頻寬高,但其實 CUDA 架構裡記憶體分成:

記憶體類型層級誰可以用特性
RegisterThread 層單一 Thread 使用最快
Shared MemoryBlock 層同一個 Block 的 Threads 可共用快速通訊
Global MemoryGrid 層所有 Block 都能訪問慢但共享
Constant / Texture MemoryGrid 層所有執行緒都能讀,但不能寫適合放「不會變」的資料,快取友善,能加速影像與查表任務

這種分層結構,加上記憶體搬運流程(host ↔ device 的 copy),是 CUDA 執行效能最佳化的關鍵,也是為何寫 CUDA 時記憶體配置會佔那麼多功夫。

假設學校合作社(GPU)要讓學生(Thread)快速存取物品(資料),但直接讓所有人搶同一個大櫃子(Global Memory)會很慢,所以設計了多層儲物櫃系統來最佳化效率:

Register(寄存器)→ 學生口袋(最快但最小)

  • 特性
    • 每個學生(Thread)有自己的口袋(Register),只能放少量東西(例如一支筆、一張紙)。
    • 超快:東西放在身上,隨手就能拿(無需排隊)。
  • 限制
    • 口袋空間小,放不下課本(大資料)。

CUDA 用途:暫存計算中的臨時變數(如迴圈計數器)。

Shared Memory(共享記憶體)→ 班級共用櫃(Block 專用)

  • 特性
    • 每個班級(Block)有一個共用櫃(Shared Memory),全班同學(Thread)都能存取。
    • 速度快:櫃子在教室內(GPU晶片上),不用跑去合作社。
    • 適合小組協作:例如全班一起算數學題,中間結果放共用櫃。
  • 限制
    • 只有同班同學(同Block的Thread)能用,別班不能偷看。

CUDA 用途:加速Block內Thread的通訊(如矩陣分塊計算)。

Global Memory(全局記憶體)→ 合作社大倉庫(全GPU共用)

  • 特性
    • 全校(Grid)共用的大倉庫(Global Memory),所有班級(Block)都能存取。
    • 速度慢:要從教室走到合作社(存取延遲高)。
    • 容量大:能放課本、掃具等所有東西(大型資料)。
  • 關鍵問題
    • 如果全校學生同時去倉庫拿東西,會塞車(頻寬瓶頸)。

CUDA 用途:儲存輸入/輸出資料(如影像、矩陣)。

Constant / Texture Memory(常數/紋理記憶體)→ 公告欄(只讀)

  • 特性
    • 像學校的「公告欄」,貼著全校通用的資訊(例如課表、地圖)。
    • 只能讀取,不能修改(常數資料)。
    • 有快取(Cache):常用資料(如地圖)會複製一份到教室附近,加快讀取。
  • 優勢
    • 適合放不變的參考資料(如數學公式)。

CUDA 用途:儲存預設參數(如機器學習的權重)。

為什麼要分這麼多層?

  1. 速度差異
    • 從「口袋(Register)」拿東西比「跑合作社(Global Memory)」快100倍!
    • 如果所有資料都塞進Global Memory,GPU會卡在「等資料」而非「算資料」。
  2. 協作需求
    • 班級內(Block)要快速共享中間結果(用Shared Memory),避免一直跑倉庫。
  3. 硬體限制
    • Register和Shared Memory空間少,但速度快,必須手動規劃哪些資料放哪裡。

舉個栗子:處理一張圖片

  1. Global Memory:原始圖片(大資料,放倉庫)。
  2. Shared Memory:每個Block載入一小塊圖片(如8×8像素)到教室櫃子,快速處理。
  3. Register:每個Thread計算像素時,用口袋暫存結果。
  4. Constant Memory:儲存濾鏡參數(如模糊效果的參數值)。

如果沒分層,所有Thread都去Global Memory搶資料,速度會像「全校擠合作社」一樣崩潰!

CUDA 程式怎麼執行?

基本流程如下:

  1. 程式寫好後,用 CUDA 編譯器把 GPU 部分編譯成 device code
  2. CPU 負責初始化、分配記憶體、發動 kernel 呼叫
  3. GPU 接到 kernel 後,用所有 Multiprocessor(SM)分批執行 block
  4. 每個 active block 被切成 warps,每個 warp 同時執行(但順序不保證)
  5. 資料處理完後傳回 host(CPU)

但這段你看不懂對不對?對! 20 年前的我也看不懂,沒關係。

辛普森風格的學校合作社,學生們(代表 Thread)從口袋(Register)、班級共用櫃(Shared Memory)、合作社大倉庫(Global Memory)和公告欄(Constant/Texture Memory)獲取物品,以圖解 CUDA 記憶體模型中不同層級記憶體的存取速度與特性。

用「學校園遊會分工」比喻 CUDA 執行流程

假設學校要舉辦一場大型園遊會(GPU 計算任務),整個活動的運作流程和 CUDA 程式執行非常相似:

1. 事前準備:寫程式 & 編譯

  • 主辦組(CPU):
    先規劃好園遊會的所有工作內容(寫好程式碼),並把需要「大量人力並行處理」的工作(如攤位遊戲、餐飲製作)特別標記出來(GPU 代碼)。
    • 這些標記的工作會交給專業活動公司(CUDA 編譯器)轉換成「園遊會專用指令」(device code)。

2. 活動啟動:CPU 發起任務

  • 主辦組(CPU) 負責:
    • 租借場地(分配 GPU 記憶體)
    • 通知所有工作人員待命(初始化 GPU)
    • 大喊:「現在開始執行園遊會!」(發動 Kernel 呼叫)

3. 現場執行:GPU 分工處理

  • 活動公司(GPU) 收到指令後:
    • 將所有工作分成多個大組(Block),例如:
      • 遊戲區(Block 1)
      • 餐飲區(Block 2)
      • 表演區(Block 3)
    • 每組分配給一個專業小隊(Multiprocessor, SM)負責執行。
  • 小隊(SM)內部:
    • 每個組(Block)再細分成小隊列(Warp,通常是 32 人),例如:
      • 遊戲區的「套圈圈小隊」(Warp 1)
      • 遊戲區的「投籃小隊」(Warp 2)
    • 這些小隊列同時開工,但誰先做完不保證(執行順序不固定)。

4. 工作完成:回報結果

  • 當所有攤位(Block)的工作結束後:
    • 活動公司(GPU)把成果(如營業額、照片)整理好,送回主辦組(CPU)。
    • 主辦組(CPU)繼續處理後續報表(例如統計總收益)。

白話總結

  • 開發者只需寫「每個 Block 要做什麼」,其他分工細節 CUDA 自動搞定。
  • CPU 像主辦單位,只負責「發號施令」和「收結果」。
  • GPU 像專業活動公司,接到指令後:
  • 把大任務拆成 Block(攤位)
  • 分給 SM(小隊)
  • 小隊內用 Warp(小隊列)快速並行處理

顯示卡不只是跑遊戲,還能進叢集、搞 HPC

綜合以上所說,CUDA 的架構設計,讓 GPU 可以很自然地接入大型平行運算環境,像是 supercomputer、server farm、cluster 等。

每台機器都有自己的顯示卡(作為 co-processor),整體算力是以「node × GPU 數量」來疊加,這讓 GPU 不再是「單機加速器」,而是真正的分散式算力單元。

這也是今天 AI 模型訓練、深度學習架構大量依賴 GPU 的根本原因之一。

常見問題

CUDA 是不是一種程式語言?

不是!CUDA 是 NVIDIA 設計的「工具箱」,裡面包含:
架構設計圖(怎麼讓 GPU 高效工作)
開發工具(編譯器、除錯器)
現成函式庫(像數學公式速查表)
你還是用 C/C++ 寫程式,只是加上一些「特殊標記」告訴 GPU 哪些部分要加速。

CUDA 可以跑在所有顯示卡上嗎?

只有 NVIDIA 顯示卡(型號 GeForce 8 系列之後)才能用。
AMD 或 Intel 的顯示卡要用其他工具(如 OpenCL)。
就好比,CUDA 是「NVIDIA 公司專屬的變壓器」,別家顯示卡插了沒電。

CUDA 和 OpenCL 有什麼不同?

CUDA 像 iPhone:封閉但順暢,專為 NVIDIA 顯卡設計。
OpenCL 像 Android:開放但各家體驗不同。

我不是寫 AI,也要學 CUDA 嗎?

看情況!

需要學的情境
你的工作有「大量重複計算」(例如:影片轉檔、科學模擬、3D 渲染)。
你想讓程式跑快 10 倍~100 倍(GPU 平行加速)。

不用學的情境
你寫網頁、手機 App、文書處理(用不到 GPU 加速)。

就好比:
你只是「煮泡麵」(簡單任務),不需要買專業廚房(CUDA)。
你要「開餐廳」(高效能計算),CUDA 就是你的 高效爐具。

返回頂端