程式開發環境與未來展望 (Programming Environment and Future Outlook)

重點總覽 (Overview)

主題 關鍵概念 引入版本 / 架構
Unified device memory space global / local / shared 併入單一位址空間,單一組 load/store 指令與指標即可存取 Fermi (2009)
C/C++ pointer 支援 完整 C/C++ 指標支援;new/delete/constructor/destructor 已可用於 kernel Fermi+
高階程式介面 OpenACC、Thrust、CUDA FORTRAN、C++AMP 提升異質平行開發生產力
PC sampling 指令級 (instruction-level) 剖析,精準定位最耗時的程式行 CUDA 7.5
Critical path analysis Visual Profiler 找出真正位於關鍵路徑上的 kernel / API call CUDA 8 (2016)
Future outlook 生產力、軟體工程實踐持續演進;硬體潛力需數年才被 SDK 完全發揮
Important

本節 (22.4/22.5) 的主軸是「開發者生產力 (productivity)」:讓 CUDA 程式更可組合 (composable)、更容易移植 CPU 程式碼、更容易找到正確的優化目標。底層的記憶體模型、kernel 執行控制與硬體吞吐量分別由 22-Advanced-Practices-And-Future-Evolution/01-Host-Device-Interaction-Memory-Model22-Advanced-Practices-And-Future-Evolution/02-Kernel-Execution-Control22-Advanced-Practices-And-Future-Evolution/03-Memory-Bandwidth-and-Compute-Throughput 涵蓋。


統一裝置記憶體位址空間 (Unified Device Memory Space)

[Fermi 之前] 各自獨立的位址空間 — 一個 device function 需為每種記憶體寫一份實作
  ptr_g ──ld.global──> [ global memory ]
  ptr_s ──ld.shared──> [ shared memory ]
  ptr_l ──ld.local ──> [ local  memory ]

[Fermi 之後] 統一位址空間 — 單一 ld/st 指令、單一 device function 即可
                    ┌───────────────────────────┐
        ptr ──ld──> │  single virtual addr space│
                    │   ├── global  (慢)        │
                    │   ├── local             │
                    │   └── shared  (快)        │
                    └───────────────────────────┘
// 統一位址空間下:同一份 device function 不論 p 指向
// global / shared / local memory 都能運作 (composable)
__device__ float reduce(float* p, int n) {
    float s = 0.0f;
    for (int i = 0; i < n; ++i) s += p[i];   // 同一組 ld 指令
    return s;
}
別把兩個「unified」搞混

  • Unified device memory space (本節, Fermi 2009):把 GPU 晶片內 的 global / local / shared 併入「同一位址空間」,屬編譯器/ISA 層級。它們仍是不同的物理記憶體、速度不同
  • Unified / managed memory (CUDA 6, Pascal page-fault):CPU 與 GPU 共享的 managed memory pool,屬 host/device 互動模型 — 見 22-Advanced-Practices-And-Future-Evolution/01-Host-Device-Interaction-Memory-Model

統一位址空間不等於統一效能

指標指向 shared memory 時程式跑得,指向 global memory 時較慢。位址空間統一只簡化了「寫法」,手動資料放置與搬移仍是有效的效能優化手段


高階程式設計介面 (High-Level Programming Interfaces)

介面 表達方式 特色 / 適用
OpenACC 循序迴圈上加 compiler directive (#pragma) 編譯器自動產生 CUDA kernel;最低侵入式移植
Thrust type-generic 的平行函式 / 類別 / iterator 函式庫 描述運算,底層自動生成並設定 kernel(類似 C++ STL)
CUDA FORTRAN FORTRAN 直接撰寫 CUDA kernel 多維陣列索引支援強
C++AMP 把 kernel 描述為對邏輯資料結構的平行迴圈 操作 C++ 應用中的多維陣列等
// OpenACC:在循序迴圈上加 directive,編譯器產生 CUDA kernel
#pragma acc kernels
for (int i = 0; i < n; i++)
    y[i] = a * x[i] + y[i];          // SAXPY → 自動 GPU 化
// Thrust:描述運算,函式庫自動生成/設定 kernel
#include <thrust/device_vector.h>
#include <thrust/sort.h>
thrust::device_vector<int> d(h.begin(), h.end());
thrust::sort(d.begin(), d.end());    // 無須手寫 sort kernel
Tip

這些介面與 lambda / metaprogramming(見 22-Advanced-Practices-And-Future-Evolution/02-Kernel-Execution-Control 的 device lambda)是「生產力路線」:用較少程式碼換合理效能,後續仍可再做手動 tuning。


關鍵路徑剖析 (Profiling with Critical Path Analysis)

Fig 22.2:為何要看 critical path

時間 ───────────────────────────────────────────────►
CPU :  |======= A =======|···idle···|== 使用 Y 的結果 ==|
GPU :  |==== Kernel X ====|                              (與 A 完全重疊)
GPU :       |======== Kernel Y ========|                 (位於 critical path)
                                       ▲
                              CPU 在此空轉等待 Y 完成

• Kernel X 較長,但執行時間「完全被 CPU 活動 A 重疊」
  → 只加速 X 而不同時加速 A,應用幾乎不會變快 (speedup ≈ 1)
• Kernel Y 較短,卻在 critical path 上;CPU 空等 Y
  → 加速 Y 可減少 CPU 等待時間 ⇒ 才是最佳優化目標
工具 版本 解決的問題
PC sampling CUDA 7.5 哪一行 程式碼耗時最多(指令級熱點)
Critical path analysis (Visual Profiler) CUDA 8 (2016) 哪一個 kernel/API 真正決定整體執行時間
PC sampling 與 critical path 互補,缺一不可

PC sampling 只告訴你「最熱的程式行」,卻不知道該 kernel 是否與 CPU 活動重疊。若該熱點 kernel(如上圖的 X)被完全重疊,優化它幾乎無效。必須再用 critical path analysis 確認它確實在關鍵路徑上。這與 19-Parallel-Programming-And-Computational-Thinking/01-Goals-of-Parallel-Computing-and-Amdahls-Law 的 Amdahl 思維一致:只優化「真正占用串列關鍵時間」的部分才有 speedup。


未來展望 (Future Outlook)

硬體紅利的時間差

記憶體架構、kernel 執行控制、運算核心效能等硬體強化,會先反映在對應的 SDK 釋出中;但其真正潛力可能需要數年,才會被 SDK 與 runtime 完全發揮。作者預期未來幾年產學界在 GPU 程式工具與 runtime 環境會有大量創新。


考試/面試重點 (Exam / Test Patterns)

情境 / 關鍵字 答案 / 技巧
「unified device memory space」何時引入、做了什麼 Fermi (2009);把 global/local/shared 併入單一位址空間,單一 load/store 指令 + 單一指標,使 device function 可組合 (composable)
統一位址空間是否讓三種記憶體變同一塊/同速? 。仍是不同物理記憶體、速度不同(shared 快、global 慢);只統一「位址空間與指令」,手動放置仍是優化手段
區分 unified device memory space vs unified (managed) memory 前者:晶片內 global/local/shared 位址統一 (Fermi);後者:CPU-GPU 共享 managed memory (CUDA 6 / Pascal page-fault)
OpenACC 是什麼 循序迴圈compiler directive (#pragma acc),讓編譯器自動生成 CUDA kernel
Thrust 是什麼 type-generic 平行函式/類別/iterator 函式庫,自動生成並設定 kernel(類 STL)
CUDA FORTRAN 特色 以 FORTRAN 寫 kernel;多維陣列索引支援強
C++AMP 特色 把 kernel 描述為對邏輯資料結構(多維陣列)的平行迴圈
PC sampling 是什麼、哪版 CUDA 7.5;指令級 profiling,定位最耗時的程式行
為何「最長的 kernel」未必是優化目標 若它與 CPU 活動完全重疊(off critical path),加速它 speedup≈1;應優化位於 critical path 的 kernel(CPU 空等者)
critical path analysis 哪版工具提供 CUDA 8 (2016) Visual Profiler;非關鍵路徑活動灰階淡化,關鍵路徑高亮
既有 Thrust 應用如何受惠於新硬體 高階工具自動生成 CUDA,常無須改碼即得效能提升