程式設計大量平行處理器:實務導向方法
本課程提供對使用 CUDA C 環境進行 GPU 計算與並行程式設計的全面介紹。內容涵蓋 GPU 架構、資料平行性、線程管理、記憶體優化以及高階效能考量,並透過真實案例(如磁振造影重建與分子可視化)加以說明。
課程總覽
📚 內容概要
本課程提供對使用 CUDA C 環境進行 GPU 計算與平行程式設計的全面介紹。內容涵蓋 GPU 架構、資料平行性、線程管理、記憶體優化以及進階效能考量,並透過如磁振造影重建與分子可視化等真實案例加以說明。
透過實用且動手導向的指南,掌握高效能平行運算的藝術,深入理解 CUDA 與 GPU 架構。
作者: David B. Kirk, Wen-mei W. Hwu
致謝: Ian Buck, John Nickolls, NVIDIA DevTech 團隊,Jensen Huang, David Luebke, Bill Bean, Simon Green, Mark Harris, Manju Hedge, Nadeem Mohammad, Brent Oster, Peter Shirley, Eric Young, 及 Cyril Zeller。
🎯 學習目標
- 区分多核心 CPU 與多核心 GPU 之間的設計哲學與效能發展路徑。
- 認識現代 GPU 架構中的關鍵組件,包括串流多處理器(SMs)與記憶體結構。
- 應用阿姆達爾定律(Amdahl's Law)計算理論加速比,並辨識順序瓶頸的影響。
- 對比 固定功能管线與可程式化統一處理器陣列之間的架構差異。
- 解釋 「GPGPU」作為中間階段的角色,以及早期著色器程式模型的限制。
- 分析 原生硬體功能(如原子操作、屏障同步與雙精確度支援)如何促成可擴展通用計算的轉變。
- 在矩陣-矩陣乘法演算法中辨識並利用資料平行性。
- 實作裝置記憶體管理,包含記憶體配置、主機與裝置間的資料傳輸,以及釋放。
- 使用適當的線程索引與格網/區塊組態,建構並啟動 CUDA 核心。
- 設計 多維度線程層次結構(格網與區塊),以將複雜資料結構映射至 GPU 硬體。
🔹 第 1 課:平行運算與 GPU 架構導論
概述: 本課探討從序列運算到平行運算的根本轉變,此轉變由 CPU 與 GPU 的設計哲學分歧所驅動。學生將檢視「多核心」與「大量核心」的發展路徑,理解使 GPU 能實現巨大吞吐量的硬體架構,並學習阿姆達爾定律所帶來的加速比數學限制。
學習成果:
- 区分多核心 CPU 與多核心 GPU 之間的設計哲學與效能發展路徑。
- 認識現代 GPU 架構中的關鍵組件,包括串流多處理器(SMs)與記憶體結構。
- 應用阿姆達爾定律計算理論上的加速比,並辨識順序瓶頸的影響。
🔹 第 2 課:GPU 計算的演進與未來展望
概述: 本課追溯圖形處理單元(GPU)的架構歷程,從最初專門用於三角形渲染的固定功能硬體,演變為現今強大、統一且通用的平行處理器。學生將探索從僵化的圖形管线轉向可程式化著色器的轉變,研究 GPGPU 運動的興起,以及推動當代科學與工程模擬的現代可擴展架構。
學習成果:
- 對比 固定功能管线與可程式化統一處理器陣列之間的架構差異。
- 解釋 「GPGPU」作為中間階段的角色,以及早期著色器程式模型的限制。
- 分析 原生硬體功能(如原子操作、屏障同步與雙精確度支援)如何促成可擴展通用計算的轉變。
🔹 第 3 課:CUDA 程式結構與記憶體管理
概述: 本課介紹 CUDA 程式的基礎架構,強調主機(CPU)與裝置(GPU)執行之間的區別。學生將學習在矩陣運算中辨識資料平行性,使用 CUDA API 管理獨立的記憶體空間,並透過單一程式、多重資料(SPMD)風格,組織格網、區塊與線程的平行執行層次。
學習成果:
- 在矩陣-矩陣乘法演算法中辨識並利用資料平行性。
- 實作裝置記憶體管理,包含配置、主機與裝置間的資料傳輸,以及釋放。
- 使用適當的線程索引與格網/區塊組態,建構並啟動 CUDA 核心。
🔹 第 4 課:進階 CUDA 線程與排程
概述: 本課探討 CUDA 中線程的階層化組織,重點在於多維度索引如何對應至實際資料與硬體資源。詳述屏障同步機制與透明可擴展性的原理,最終總結出用於高效率運算中容忍延遲的線程指派與瓦片(warp-based)排程之架構原則。
學習成果:
- 設計 多維度線程層次結構(格網與區塊),以將複雜資料結構映射至 GPU 硬體。
- 實作 利用內建的 CUDA 變數(
blockIdx、threadIdx、blockDim)進行精確的資料索引。 - 應用 屏障同步,確保資料完整性,同時在不同 GPU 架構上保持透明的可擴展性。
🔹 第 5 課:記憶體優化與共享記憶體分塊
概述: 本課探討記憶體頻寬與資源限制如何成為平行運算中的主要瓶頸。詳細說明「分塊」(tiling)技術如何減少全域記憶體流量,並解釋同步屏障(__syncthreads())的關鍵角色,以及在暫存器與共享記憶體之間策略性選擇以優化效能。
學習成果:
- 分析暫存器與共享記憶體的限制如何決定核函數中的平行程度(佔用率, occupancy)。
- 量化透過分塊技術所實現的全域記憶體頻寬消耗降低程度。
- 辨識同步功能的必要性,以在共享記憶體存取期間維持資料完整性。
🔹 第 6 課:效能分析與 SIMT 執行
概述: 本課探討優化 CUDA 核函數所需的架構與演算法考量。從基本執行模型(特別是單指令、多線程(SIMT)單元與瓦片分割)過渡到進階效能調校技術,包括記憶體合併、分塊矩陣乘法,以及串流多處理器(SM)資源的動態分割。
學習成果:
- 分析 多維度線程區塊如何映射至硬體的線性瓦片執行順序。
- 評估 並最小化平行歸約演算法中的控制流程分歧。
- 優化 全域記憶體頻寬,透過實作記憶體合併與分塊資料存取模式。
🔹 第 7 課:浮點運算與數值準確性
概述: 本課探討浮點數的基本架構,聚焦於 IEEE 754 標準的元件:符號位、超編碼指數與規範化尾數。學生將探索這些位元模式如何對應至離散的數字軸,並理解此表示方式的限制如何影響大型求和等複雜演算法的準確性。
學習成果:
- 解析 浮點格式,利用規範化表示與超編碼方法,從位元模式計算數值。
- 視覺化 數字軸上可表示數字的分布,並解釋指數與尾數之間位元配置的影響。
- 量化 數值不準確性,使用單位最後一位(ULP),並識別不同捨入模式如何導致誤差。
🔹 第 8 課:案例研究:磁振造影重建的平行化
概述: 本課探討在 GPU 上平行化先進磁振造影(MRI)重建的技術。重點在於針對非笛卡兒軌跡的迭代重建過程,特別是透過迴圈轉換、常數記憶體管理、資料布局重新組織,以及使用硬體加速的三角函數來優化計算密集型的 F^H d 核心。
學習成果:
- 理解從基於笛卡兒 FFT 的重建,轉變為針對非笛卡兒 k-空間資料的迭代線性求解器演算法。
- 應用迴圈分裂與迴圈交換,將序列式 C 程式碼轉換為適合大量 CUDA 線程映射的結構。
- 透過常數記憶體分塊與結構陣列(AoS)資料布局,優化記憶體吞吐量。
🔹 第 9 課:案例研究:分子可視化與多 GPU 執行
概述: 本課探討 GPU 計算在分子可視化中的實際應用,特別是以直接庫侖求和(DCS)方法計算靜電位圖。學生將從基本的核心實作逐步進階至高度優化的版本,利用指令展開、記憶體合併與填充技術。
學習成果:
- 使用 CUDA 常數記憶體與全域記憶體延遲隱藏技術,實作直接庫侖求和(DCS)核心。
- 透過指令展開與重複使用共同座標計算,優化核心效能。
- 透過記憶體合併與填充策略,對齊 GPU 全域記憶體存取,以達到最大頻寬。
🔹 第 10 課:計算思維與平行演算法選擇
概述: 本課探討從序列思維轉向平行問題解決的方法,聚焦於平行程式設計的目標與策略性演算法選擇。學生將學習如何將問題分解為可平行化的單元,運用計算思維彌補領域科學與硬體架構之間的差距,並評估演算法效能。
學習成果:
- 識別平行程式設計的主要目標,並使用阿姆達爾定律計算理論加速比。
- 区分任務層級與資料層級的分解,並應用以原子為中心(scatter)與以格網為中心(gather)的策略。
- 根據記憶體頻寬、計算複雜度與架構限制等標準,評估並選擇平行演算法。
🔹 第 11 課:OpenCL 程式模型導論
概述: 本課介紹 OpenCL 作為異質平行運算的框架,著重於其資料平行模型與階層化硬體抽象。學生將學習如何將 OpenCL 的 NDRange 與記憶體結構映射至 CUDA 對應架構,並掌握透過動態編譯模型管理主機端設備的方法。
學習成果:
- 將 OpenCL 的平行模型與記憶體層次結構映射至特定的 CUDA 架構(例如將工作群組映射至區塊,本地記憶體映射至共享記憶體)。
- 實作 OpenCL 核心函數,並使用環境(Contexts)與命令佇列(Command Queues)管理主機端執行環境。
- 執行動態編譯工作流程,於執行時期從原始碼建立核心。
🔹 第 12 課:現代 GPU 特性與未來展望
概述: 本課探討 GPU 架構與功能的演進,聚焦於朝向複雜記憶體管理、增強核心執行能力與提升核心效能的轉變。學生將檢視統一裝置記憶體空間與核心層級函數呼叫等特性,如何使 GPU 轉變為通用處理器。
學習成果:
- 解釋記憶體架構演進的重要性,以及朝向 64 位元統一裝置記憶體空間的趨勢。
- 分析增強的原子操作與核心層級函數呼叫如何促進複雜資料結構與演算法的實作。
- 評估現代 GPU 環境中同時執行多個核心、雙精度運算速度提升,以及控制流程效率對效能的影響。