訊息傳遞介面(英語:Message Passing Interface,縮寫 MPI)是一個平行計算的應用程式接口(API),常在超級電腦、電腦叢集等非共享記憶體環境程序設計。
# Process vs. Thread
在多功作業系統 (Multitasking Operating System) 中,可以同時執行數個 Process ,然而一個 CPU 一次只能執行一個 Process (因此才有現在的多核處理器),而 Process 的運行量總量不會少於 CPU 的總量,又 Process 會佔用記憶體,因此如何排程 (Scheduling,恐龍本第五章) 、如何有效管理記憶體 (恐龍本第八章) 則是 OS 所關注的事。
- Process: 旨已經執行並且 load 到記憶體中的 Program。
- 每一個 Process 是互相獨立的。
- Process 間不會共享記憶體。
- Thread: 在同一個 Process 中會有很多個 Thread ,每一個 Thread 負責某一項功能。
- 同一個 Process 底下的 Thread 共享資源,如 記憶體、變數等,不同的 Process 則否。
# MPI vs. MP
- MP: 讓程式可以在單節點上,使用多核心(cores)平行跑。
- 平行出來的部分叫做 thread
- 記憶體使用:Shared Memory Processor(SMP)架構
- CPU 的核心使用同節點上的記憶體
- MPI: 讓程式可以跨計算節點(nodes)平行跑。
- 平行出來的部分叫做 rank
- 記憶體使用:Distributed memory 架構
- CPU 的核心使用不同的記憶體,透過網路溝通
# MPI 語法
MPI_Init()
: Initialize the MPI enviromentMPI_Comm_size(MPI_COMM_WORLD, &world_size)
: Get the number of processesMPI_Comm_rank(MPI_COMM_WORLD, &process_rank)
: Get the rank of processMPI_Finalize()
: Finalize the MPI enviromentMPI_Wtime()
: process time, return type is doubleMPI_Reduce(&send, &recv, count, dataType, MPI_Op, root, MPI_COMM_WORLD)
: 把 send 的值經過 MPI_Op 的運算處理過後丟到 recv 中,變成 recv 的新值MPI_Bcast(&bcast, count, dataType, root, MPI_COMM_WORLD)
: 把 root 的 bcast 廣播給大家MPI_Recv(&value, count, dataType, source, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE)
: 將 source 的直接收MPI_Send(&value, count, dataType, dest, tag, MPI_COMM_WORLD)
: 將值發送給 destMPI_ALLreduce
: 包括 MPI_Reduce 和 MPI_BcastMPI_Scatter
: 與 MPI_Bcast 很像,但區別於他是用於接收一個陣列,幫他分隔成不同區塊,然後同區塊傳給不同人MPI_Gather
: 與 MPI_Scatter 剛好相反,將不同的東西收到一起,集中到其中一個MPI_Barrier()
: 保證在通訊域內,所有的進程都已經執行完了呼叫之前的所有操作- 可以用於要確保其他 processor 前面計算正確,到後面使用
- 在計算時間時可以確保計算大家都跑完的時間
# MPI_Op
MPI_MIN
: 找最小值MPI_SUM
: 計算總值
# MPI Hello World Code
#include <mpi.h> | |
#include <stdio.h> | |
int main(int argc, char** argv) { | |
// Initialize the MPI environment | |
MPI_Init(&argc, &argv); | |
// Get the number of processes | |
int world_size; | |
MPI_Comm_size(MPI_COMM_WORLD, &world_size); | |
// Get the rank of the process | |
int world_rank; | |
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); | |
// Get the name of the processor | |
char processor_name[MPI_MAX_PROCESSOR_NAME]; | |
int name_len; | |
MPI_Get_processor_name(processor_name, &name_len); | |
// Print off a hello world message | |
printf("Hello world from processor %s, rank %d out of %d processors\n", | |
processor_name, world_rank, world_size); | |
// Finalize the MPI environment. | |
MPI_Finalize(); | |
return 0; | |
} |