多維 Grid 組織 (Multidimensional Grid Organization)
重點總覽 (Overview)
| 項目 | 內容 | 重點 |
|---|---|---|
| 階層 (hierarchy) | grid → block → thread,兩層 | grid 是 block 的 3D 陣列;block 是 thread 的 3D 陣列 |
| 執行設定 (execution config) | <<<dimGrid, dimBlock>>> |
第 1 參數 = grid 維度 (以 block 計);第 2 參數 = block 維度 (以 thread 計) |
dim3 型別 |
三元素整數向量 (x, y, z) |
未用維度設為 1 即可降維 |
| 座標變數 (built-in) | blockIdx, threadIdx |
thread 自身座標,用來定位資料 |
| 維度變數 (built-in) | gridDim, blockDim |
grid/block 的尺寸,由執行設定預先初始化 |
| block 上限 | 總 thread 數 ≤ 1024 | x*y*z ≤ 1024,分配方式任意 |
| gridDim 上限 | x: 1..2³¹-1;y,z: 1..65535 |
各維度範圍不同 |
grid 中所有 thread 執行同一個 kernel function,靠 blockIdx/threadIdx 座標彼此區分並認領各自負責的資料區段。grid 一旦啟動,grid/block 維度在整個 grid 執行完畢前保持不變。
兩層執行緒階層 (Two-Level Thread Hierarchy)
- grid 由一個或多個 block 組成;每個 block 由一個或多個 thread 組成。
- 一般情況:grid 是 block 的 3D 陣列,block 是 thread 的 3D 陣列。
- 同一 block 內所有 thread 共享相同的
blockIdx.x/.y/.z。 - grid 與 block 不必同維度:grid 可高於 block,反之亦可。
| 內建變數 | 意義 | 由誰決定 | 在 kernel 內可否改名 |
|---|---|---|---|
gridDim |
grid 各維 block 數 | 第 1 個執行設定參數 | 否 (CUDA C 規範) |
blockDim |
block 各維 thread 數 | 第 2 個執行設定參數 | 否 |
blockIdx |
本 block 在 grid 的座標 | 排程時指定 | 否 |
threadIdx |
本 thread 在 block 的座標 | 排程時指定 | 否 |
記法:*Dim 是「尺寸」(總共幾個),*Idx 是「索引」(我是第幾個)。Dim 來自 host 的執行設定;Idx 由硬體在排程時賦予。
執行設定參數與 dim3 (Execution Configuration & dim3)
每個執行設定參數型別為 dim3:三個元素 x, y, z 的整數向量。用不到的維度設為 1 即可。
// 1D grid:32 個 block,每個 block 128 threads -> 共 128*32 = 4096 threads
dim3 dimGrid(32, 1, 1);
dim3 dimBlock(128, 1, 1);
vecAddKernel<<<dimGrid, dimBlock>>>(...);
// host 變數名稱任意 (只要型別是 dim3),下列效果完全相同
dim3 dog(32, 1, 1);
dim3 cat(128, 1, 1);
vecAddKernel<<<dog, cat>>>(...);
維度可由其他變數在 runtime 計算,讓 block 數隨資料量變化:
// block 固定 256;grid 大小隨 n 變動
dim3 dimGrid(ceil(n/256.0), 1, 1);
dim3 dimBlock(256, 1, 1);
vecAddKernel<<<dimGrid, dimBlock>>>(...);
// n=1000 -> 4 blocks;n=4000 -> 16 blocks (皆足以覆蓋所有元素)
1D 捷徑 (shorthand):直接傳算術運算式,編譯器把它當 x 維、y/z 自動為 1:
vecAddKernel<<<ceil(n/256.0), 256>>>(...); // 等同上面的 dim3 寫法
此捷徑利用 C++ 建構子的預設參數:dim3 的三個參數預設值皆為 1,傳單一值時只填第一個參數 (x),y、z 取預設 1。
kernel 內讀到的是維度值,例如 n=4000 時 gridDim.x = 16、blockDim.x = 256。這些名稱不可更改 (與 host 端可自取的 dimGrid/dog 不同)。
各維度尺寸限制 (Per-Dimension Size Limits)
| 變數 / 限制 | 範圍 |
|---|---|
gridDim.x |
1 .. 2³¹ − 1 |
gridDim.y |
1 .. 2¹⁶ − 1 (65,535) |
gridDim.z |
1 .. 2¹⁶ − 1 (65,535) |
blockIdx.x |
0 .. gridDim.x − 1 |
blockIdx.y |
0 .. gridDim.y − 1 |
blockIdx.z |
0 .. gridDim.z − 1 |
| block 總 thread 數 | blockDim.x * blockDim.y * blockDim.z ≤ 1024 |
block 形狀範例 (上限 1024):
(x, y, z) |
總數 | 合法? |
|---|---|---|
(512, 1, 1) |
512 | ✅ |
(8, 16, 4) |
512 | ✅ |
(32, 16, 2) |
1024 | ✅ |
(32, 32, 2) |
2048 | ❌ 超過 1024 |
- 降維方式:2D block 設
blockDim.z = 1;1D block 設blockDim.y = blockDim.z = 1。 - 1024 個 thread 可在三維間任意分配,只要乘積不超過上限。
邊界情況:compute capability < 3.0 的舊裝置,gridDim.x (即 x 維 block 數) 上限只到 2¹⁶ − 1,而非 2³¹ − 1。寫可攜程式時別假設第一維可無限大。
維度標記順序 (Dimension Labeling Order)
圖 3.1 玩具範例:gridDim = (2, 2, 1)、blockDim = (4, 2, 2)。
dim3 dimGrid(2, 2, 1); // C 寫法:低維 (x) 在前
dim3 dimBlock(4, 2, 2);
KernelFunction<<<dimGrid, dimBlock>>>(...);
Grid gridDim=(x=2, y=2, z=1) block 標記 = (blockIdx.y, blockIdx.x)
bIdx.x=0 bIdx.x=1
+-----------+-----------+
y=0 | block(0,0)| block(0,1)|
+-----------+-----------+
y=1 | block(1,0)| block(1,1)| block(1,0): blockIdx.y=1, blockIdx.x=0
+-----------+-----------+
每個 block blockDim=(x=4, y=2, z=2) -> 4*2*2 = 16 threads
thread 標記 = (threadIdx.z, threadIdx.y, threadIdx.x)
例: thread(1,0,2) -> z=1, y=0, x=2
全 grid 共 4 blocks * 16 = 64 threads
標記順序與 C 設定順序相反:圖示中的 block/thread 標記最高維在前 (z, y, x);但在 dim3(...) 與執行設定裡是最低維在前 (x, y, z)。此「反序」是為了之後把 thread 座標映射到多維資料索引時更直覺 (見 03-Multidimensional-Grids-And-Data/02-Mapping-Threads-to-Multidimensional-Data)。
考試/面試重點 (Exam / Test Patterns)
| 情境 / 關鍵字 | 答案 / 技巧 |
|---|---|
<<<A, B>>> 兩參數意義 |
A = grid 維度 (block 數),B = block 維度 (thread 數) |
| 算 grid 中總 thread 數 (1D) | gridDim.x * blockDim.x;2D/3D 再乘上各維 |
dimGrid 名稱能改嗎? |
host 端可 (型別需 dim3);kernel 內 gridDim/blockDim 不可 |
| block 最多幾 threads? | 1024,且 x*y*z ≤ 1024 |
(32, 32, 2) 合法嗎? |
否,2048 > 1024 |
gridDim.y / .z 上限 |
65,535 (2¹⁶−1);gridDim.x 才是 2³¹−1 |
blockIdx.x 範圍 |
0 .. gridDim.x − 1 (索引從 0 起) |
<<<ceil(n/256.0), 256>>> 意義 |
算術式當 x 維、y/z=1;block 固定 256,grid 隨 n 變 |
| grid 與 block 必須同維? | 否,可不同維度 |
| 圖中 block(1,0) 代表 | blockIdx.y=1, blockIdx.x=0 (高維在前,與 C 設定反序) |
| 啟動後維度可變嗎? | 否,整個 grid 執行完前維度固定 |
Related Notes
- 03-Multidimensional-Grids-And-Data/02-Mapping-Threads-to-Multidimensional-Data
- 03-Multidimensional-Grids-And-Data/03-Image-Blur-Kernel
- 03-Multidimensional-Grids-And-Data/04-Matrix-Multiplication-Kernel
- 02-Heterogeneous-Data-Parallel-Computing/03-Kernel-Functions-and-Threading
- 02-Heterogeneous-Data-Parallel-Computing/04-Calling-Kernels-Compilation-and-Summary
- 04-Compute-Architecture-And-Scheduling/01-GPU-Architecture-and-Block-Scheduling