初識並發編程 MPI


MPI是一個跨語言的通訊協議,用於並發編程。MPI標准定義了一組具有可移植性的編程接口。

安裝環境

MPICH 是開源的消息傳遞接口(MPI)標准的實現。
下載地址

# 解壓文件
tar -xzvf mpich-3.2.1.tar.gz
cd mpich-3.2.1
# /usr/local/Cellar/mpich 改為你要安裝 MPICH 的路徑
./configure –-prefix=/usr/local/Cellar/mpich |& tee c.log
make |& tee m.log
make install |& tee mi.log
# 將你安裝 MPICH 的路徑添加到 PATH
export PATH=/usr/local/Cellar/mpich:$PATH;

編程例子

1. 簡單 MPI 編程之進程識別

#include <mpi.h> // mpi 頭文件
#include <stdio.h>

int main(int argc, char **argv) {
    int numprocs, myid;
    MPI_Init (&argc, &argv); // 初始化 MPI 執行環境
    MPI_Comm_size (MPI_COMM_WORLD, &numprocs); // 獲取有多少個進程屬於 MPI_COMM_WORLD 通信域
    MPI_Comm_rank (MPI_COMM_WORLD, &myid); // 獲取當前進程的 id

    if (myid == 0) {
        // 進程號為0的進程執行的操作...
    } else {
        // 其它進程執行的操作...
    }
    // 所有進程都執行的操作...

    MPI_Finalize(); // 結束 MPI 執行環境
    return 0;
}

2. MPI 簡單通信

#include <mpi.h> // mpi 頭文件
#include <stdio.h>

int main(int argc, char **argv) {
    int data[100], myid;
    MPI_Init (&argc, &argv);
    MPI_Comm_rank (MPI_COMM_WORLD, &myid); 

    if (myid == 0) 
        MPI_Send(data, 100, MPI_INT, 1, 0, MPI_COMM_WORLD);
    else if (myid == 1)
        MPI_Recv(data, 100, MPI_INT, 0, 0, MPI_COMM_WORLD,
                                    MPI_STATUS_IGNORE);

    MPI_Finalize(); // 結束 MPI 執行環境
    return 0;
}

其中,MPI_SEND(buf, count, datatype, dest, tag, comm) 是發送消息的 API,
buf 是消息緩存區。
count是消息大小。
datatype是數據類型。
dest是目的進程在指定的進程域 comm 的進程號。
tag是用戶定義的消息的類型。

MPI_RECV(buf, count, datatype, source, tag, comm, status) 是(阻塞)接收消息的 API。
source 是來源進程在指定的進程域 commMPI_ANY_SOURCE 的進程號。
tag 可以是 MPI_ANY_TAG
status 用來接收更多信息,可以用 MPI_STATUS_IGNORE 如果我們不需要更多信息。

編譯運行程序

封裝的編譯器:

  • 對於 C 程序:mpicc test.c -o test
  • 對於 C++ 程序:mpicxx test.cpp -o test
  • 對於 Fortran 77 程序:mpif77 test.f -o test
  • 對於 Fortran 90 程序:mpif90 test.f90 -o test

你也可以鏈接其它庫:mpicc test.c -o test -lm

運行:
啟動 16 個進程:mpiexec -n 16 ./test
如果-n 指定的進程數超過了系統的CPU(核)數,就會報錯如下:

There are not enough slots available in the system to satisfy the 16 slots
that were requested by the application:
./test

Either request fewer slots for your application, or make more slots available
for use.

進階一些:

// 非阻塞發送。非阻塞接收為 MPI_Irecv,具體說明可以用 man 命令查詢.
int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,
              MPI_Comm comm, MPI_Request *request)

// 檢測非阻塞通信是否完成。阻塞等待為 MPI_Wait,可以等待全部(MPI_Waitall)、等待一些(MPI_Waitsome,MPI_Waitany)
nt MPI_Test( MPI_Request *request, int *flag, MPI_Status *status );

// 數據歸約:通過計算收集到的多個數據得到一個數據。
int MPI_Reduce (void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM