MPI 叢集背景、Stencil 執行範例與 MPI Basics
重點總覽 (Overview)
| 項目 | 重點 | 對應 CUDA 概念 |
|---|---|---|
| 問題規模 | 單一 host+device 不夠,HPC 需要 cluster(多 node、每 node 多 host/device)的聚合運算力 | 從單卡擴展到多節點 |
| 記憶體模型 | MPI 假設 distributed memory:process 間只能靠訊息傳遞 (message passing) 交換資料,不能共享變數 | 與 CUDA 的 global memory 不同(非共享) |
| 程式模型 | SPMD:所有 process 跑同一支程式,靠 rank 走不同分支 | CUDA kernel 也是 SPMD(靠 threadIdx 分支) |
| 行程識別 | MPI rank / process id(0 ~ np-1,一維) | blockIdx.x*blockDim.x + threadIdx.x |
| 執行範例 | 3D 25-point stencil(Jacobi 熱傳導),沿 z 維度 切成 domain partitions | 08-Stencil/01-Stencil-Background-and-Basic-Kernel |
| 資料邊界 | 鄰近 partition 需互換 halo cells(每方向 4 片 slice);最外緣用 ghost cells(補 0) | convolution / stencil 的 halo |
| 角色分工 | 1 個 data server(最大 rank, np-1)負責 I/O;其餘 np-1 個 compute process 算 stencil | 某些工作只由 thread 0 做 |
Important
本章把「單卡 CUDA kernel」放大成「多節點叢集」:核心三件事是 domain partitioning(切資料)、point-to-point / collective communication(換資料)。本篇只涵蓋 20.1–20.3 的背景、範例與啟動 API;通訊細節見 sibling notes。
為何叢集需要 MPI/CUDA (Background)
- 2009 年前幾乎無頂級超算用 GPU;為了能源效率 (energy efficiency),GPU 快速普及(見 Green500 排名)。
- 今日多數頂級超算每個 node 同時有 CPU + GPU。
- 叢集的主流程式介面是 MPI (Message Passing Interface):一組讓叢集中各 process 互相通訊的 API。
- 電話系統類比:process 用邏輯編號 (rank) 互相定址,不需知道對方實體位置或網路如何路由 —— 就像打電話只需號碼。
| 對照 | Shared memory (單機/CUDA) | Distributed memory (MPI) |
|---|---|---|
| 資料交換 | 直接讀寫共同位址 | 送/收訊息 (send/recv) |
| 程式員看到 | 同一位址空間 | 各 process 獨立位址空間 |
| 同步 | __syncthreads() / barrier |
MPI_Barrier()(collective) |
┌──────── Node 0 ────────┐ ┌──────── Node 1 ────────┐
│ (proc) (proc) │ │ (proc) (proc) │
│ CPU+GPU CPU+GPU │ │ CPU+GPU CPU+GPU │
└───────┬────────┬───────┘ └───────┬────────┬───────┘
│ └──── messages ──────┘ │
└─────────── interconnect ─────────────┘
每個 node 內含 1+ 個 process(雲朵);process 間靠「訊息」傳資料
Tip
程式員不需處理 interconnect 細節:呼叫通訊 API,MPI 實作負責路由。這讓同一份程式能在不同網路拓樸的叢集上跑。
Stencil 執行範例與 Domain Partitioning (A Running Example)
25-point stencil 是什麼
- 用 Jacobi 迭代法解偏微分方程,模擬熱傳導 (heat transfer, finite difference)。
- 每個格點下一步的值 = 自己與 6 方向(north/east/south/west/up/down)鄰居的加權和。
- 為提高數值穩定性 (numerical stability),每方向取 4 個間接鄰居 → 高階 stencil。
(i,j,k+4) z 方向 ±1..±4
⋮ y 方向 ±1..±4
(i-4..i+4, j, k) ─●─ (i, j±1..±4, k) x 方向 ±1..±4
⋮
(i,j,k-4) 中心 ● 連同 24 鄰居 = 25 點
記憶體佈局 (row-major)
- 系統建模為 structured grid(各方向間距固定)→ 用 3D 陣列,每元素存一格點狀態。
- row-major:x 最低維、y 次之、z 最高維。
- 結論(全章關鍵):同一 z slice 的所有元素在記憶體中連續。
範例 2(x)×2(y)×4(z):先放 z=0 整片,再 z=1,依此類推
index: 0 1 | 2 3 || 4 5 | 6 7 || 8 9 |10 11 ||12 13|14 15
└z=0 slice ┘ └z=1 slice ┘ └z=2 slice ┘ └z=3 slice┘
(每片 = dimx*dimy = 4 個元素,沿 x 連續,y 次之)
沿 z 維度切 Domain Partitions
- 叢集常把輸入切成 domain partitions,每片指派給一個 MPI compute process。
- 本例沿 z 維度切:z=0 → D0、z=1 → D1 …(因為一個 z slice 連續,切割最自然)。
- 每 partition 格點數 =
dimx * dimy * (dimz / num_comp_procs)。
Halo cells 與 Ghost cells
- Jacobi 每步需鄰居上一步的值 → partition 左右邊界需要鄰居的資料 = halo cells。
- 25-point 每方向 4 片 → 每側需 4 片 halo slices。
- 某 process 的 halo slice,正是鄰居的 boundary slice。
D(i-1) D(i) (一個 internal partition) D(i+1)
┌───────────┐ ┌─────┬───────────────────┬─────┐ ┌───────────┐
│ ... bdry │→ │halo │ internal points │halo │ ←│ bdry ... │
│ (4 片) │ │ 4片 │ dimx*dimy*(P) │ 4片 │ │ (4 片) │
└───────────┘ └─────┴───────────────────┴─────┘ └───────────┘
↑左 halo 來自 D(i-1) 右 halo 來自 D(i+1)↑
internal process 兩側都有鄰居 → +8 片;edge process 只一側 → +4 片
Warning
Edge vs Internal process 的 halo 數不同:最外緣(process 0 與 np-2)只有一側鄰居,另一側用 ghost cells(補 0,如 convolution),不需收資料。
- Internal:收
dimx*dimy*((dimz/num_comp)+8)(兩側各 4 片) - Edge:收
dimx*dimy*((dimz/num_comp)+4)(單側 4 片)
(資料如何依此偏移分發,見 20-Heterogeneous-Computing-Cluster/02-MPI-Point-to-Point-Communication)
MPI Basics 與 SPMD 設定 (MPI Basics)
五個建立/拆除通訊系統的核心函式
| 函式 | 作用 | 關鍵參數 |
|---|---|---|
MPI_Init(&argc,&argv) |
初始化所有 process 的通訊系統 | 命令列引數 |
MPI_Comm_rank(comm,&pid) |
回傳本 process 的唯一 rank | communicator、輸出 pid |
MPI_Comm_size(comm,&np) |
回傳 communicator 內總 process 數 | communicator、輸出 np |
MPI_Abort(comm,code) |
中止通訊並回傳錯誤碼(非 0 = 出錯) | scope、error code |
MPI_Finalize() |
釋放所有 MPI 通訊資源 | 無 |
Important
Communicator (MPI_Comm) = 一群 process 的通訊範圍。預設 MPI_COMM_WORLD 代表「跑這支程式的所有 process」。MPI_Comm 等型別定義在 mpi.h(所有用 MPI 的 C 檔都要 #include)。
SPMD 主程式(Fig. 20.6)
#include "mpi.h"
int main(int argc, char *argv[]) {
int pad = 0, dimx = 480+pad, dimy = 480, dimz = 400, nreps = 100;
int pid = -1, np = -1;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &pid); // 本 process 的 rank
MPI_Comm_size(MPI_COMM_WORLD, &np); // 總 process 數
if (np < 3) { // 本例至少需 3 個 process
if (0 == pid) printf("Needed 3 or more processes.\n"); // 只由 rank0 報錯
MPI_Abort(MPI_COMM_WORLD, 1); return 1;
}
if (pid < np - 1)
compute_process(dimx, dimy, dimz / (np - 1), nreps); // 計算行程
else
data_server(dimx, dimy, dimz); // 資料伺服器 (rank np-1)
MPI_Finalize();
return 0;
}
- 用
mpirun/mpiexec在 login node 啟動;np 由使用者指定,但系統不保證能開到那麼多 → 程式應自行檢查np。 - MPI rank 的角色 = CUDA 的
blockIdx.x*blockDim.x + threadIdx.x:唯一識別、用來分流;差別是 MPI rank 是一維。 - 只由 rank 0 報錯的慣例 = CUDA 中「只由 block 內某一 thread 做某事」。
Data server / Compute process 分工
np 個 process (rank 0 .. np-1)
├─ rank 0 .. np-2 → compute_process() ← 算 stencil,共 np-1 個
└─ rank np-1 → data_server() ← 做 I/O / 分發+收集資料
注意:傳給 compute 的 dimz 是 dimz/(np-1)(每個只負責一片 partition)
Warning
不是所有 np 個 process 都在計算:最大 rank(np-1)被保留當 data server 做 I/O,真正算 stencil 的只有 np-1 個。這是設計決策,compute 端與 server 端的程式碼都依此一致。
Tip
同一份程式靠 rank 分支走不同 function call path(compute vs server)——這正是 SPMD:同碼、不同流程,與 CUDA kernel 內用 thread id 分支同理。
考試/面試重點 (Exam / Test Patterns)
| 情境 / 關鍵字 | 答案 / 技巧 |
|---|---|
| 「MPI 用哪種記憶體模型?」 | Distributed memory + message passing;process 不能透過 shared memory 存同一變數 |
| 「MPI rank 對應 CUDA 的什麼?」 | blockIdx.x*blockDim.x + threadIdx.x(但 rank 是一維) |
| 「25-point stencil 怎麼來的?」 | 6 方向 × 每方向 4 鄰居 = 24,加自己 = 25 |
| 「np 個 process 有幾個在算?」 | np-1 個 compute;rank np-1 是 data server |
| 「沿哪一維切?為何?」 | 沿 z;因 row-major 下一個 z slice 連續,切割/傳輸最自然 |
| 「internal vs edge 需多少 halo?」 | internal +8 片(兩側各 4);edge +4 片(單側,另一側 ghost 補 0) |
| 「為何要檢查 np?」 | 系統不保證開到使用者要求的 process 數,需 MPI_Comm_size 驗證 |
| 「五大設定 API?」 | MPI_Init / MPI_Comm_rank / MPI_Comm_size / MPI_Abort / MPI_Finalize |
| 「只報一次錯怎麼做?」 | if(0==pid) printf(...)(只由 rank 0),等同 CUDA thread 0 |
| 「MPI_COMM_WORLD 是什麼?」 | 預設 communicator,涵蓋所有跑此程式的 process |
Related Notes
- 20-Heterogeneous-Computing-Cluster/02-MPI-Point-to-Point-Communication
- 20-Heterogeneous-Computing-Cluster/03-Overlapping-Computation-and-Communication
- 20-Heterogeneous-Computing-Cluster/04-Collective-Communication-and-CUDA-Aware-MPI
- 08-Stencil/01-Stencil-Background-and-Basic-Kernel
- 07-Convolution/03-Tiled-Convolution-and-Halo-Handling
- 01-Introduction/01-Heterogeneous-Parallel-Computing-and-the-Demand-for-Speed