並行開發框架___MPI
1、並行計算機體系架構
2、並行編程模型
-
數據並行模型
相同的操作同時作用於不同的數據
-
共享變量模型
用共享變量實現並行進程間的通信
-
消息傳遞模型
在消息傳遞模型中,駐留在不同節點上的進程可以通過網絡傳遞消息相互通信,實現進程之間的信息交換、協調步伐、控制執行等
3、認識MPI編程
Massage Passing Interface:是消息傳遞函數庫的標準規範,由MPI論壇開發,支Fortran和C/C++,
一種新的庫描述,不是一種語言
共有上百個函數調用接口在Fortran or和C/C++語言中可以直接對這些函數進行調用
是一種標準或規範,而不是特指某一個對它的具體實現
MPI是一種消息傳遞編程模型,併成爲這種編程模型的代表和事實上的標準
4、使用MPI的優勢
-
高可移植性
a.MPI已在PC機、MS Windows以及所有主要的Unix
b.工作站上和所有主流的並行機上得到實現
c.使用MPI作消息傳遞的C/C++或Fortran並行程序可不加改變地在上述平臺實現 -
沒有更好的選擇
並行框架雖然有很多種,但各有優劣,對應不同的場景,總體上MPI爲比較成熟通用的,不斷髮展的最具可行性的。
5、常用的MPI版本 -
MPICH
是MPI最流行的非專利實現,由Argonne國家實驗室和密西西比州立大學聯合開發,具有更好的可移植性
–當前最新版本有MPICH 1.2.7p1和MPICH2 1.3.2p1 -
OpenMPI
LAMMPI的下一代MPI實現
當前最新版本1.4.3 -
更多的商業版本MPI
HP-MPI,MS-MPI,… -
所有的版本遵循MPI標準,MPI程序可以不加修改的運行
6.認識MPI編程
- 首先分別以C語言的形式給出一個最簡單的MPI並行程序hello.c
#include<stdio.h>
#include"mpi.h"
main(int *argc, char *argv[]){
MPI_Init(&argc,&argv);
printf("Hello World!\n");
MPI_Finalize();
}
-
MPI 程序編譯和運行
mpicc –O2 –o hello hello.c
生成hello 可執行代碼
mpirun -np 4 hello
4,指定np的值,表示進程數,由用戶指定
hello, 要運行的MPI並行程序 -
Hello 在MPI下執行過程
SPMD: Single Program Multiple Data(MIMD)
- MPI程序運行模式
7、MPI編程範式
#MPI初始化- MPI_INIT
int MPI_Init(int *argc, char **argv)
MPI INIT(IERROR)
/*#MPI_INIT是MPI程序的第一個調用,完成MPI程序的所有初始化工作。所有的MPI程序的第一條可執行語句都是這條語句
#啓動MPI環境,標誌並行代碼的開始
#並行代碼之前,第一個mpi函數(除MPI_Initialize外)要求main必須帶參數運行。否則出錯
*/
#MPI結束- MPI_FINALIZE
int MPI_Finalize(void)
MPI_ Finalize(IERROR)
/*#MPI_INIT是MPI程序的最後一個調用,它結束MPI程序的運行,它是MPI程序的最後一條可執行語句,否則程序的運行結果是不可預知的。
#標誌並行代碼的結束,結束除主進程外其它進程
#之後串行代碼仍可在主進程(rank = 0)上運行(如果必須)
*/
8、開始寫較爲完善的MPI程序
- 任務執行時使用的進程個數
用MPI_Comm_size獲得進程個數p
int MPI_Comm_size(MPI_Comm comm,int *size) - 任務執行時當前進程
用MPI_Comm_rank獲得進程的一個叫rank的值,該rank值爲0到p-1間的整數,相當於進程的ID
int MPI_Comm_rank(MPI_Comm comm,int *rank)
#完善後的Hello World
#include <stdio.h>
#include "mpi.h"
main( int *argc, char *argv[]){
int myid,numprocess;
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm rank(MPI COMM WORLD,$myid);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Get_processor_name(processor_name,&namelen);
fprintf(stderr,"Hello World!Process %d of %d on %s\n",myid,numprocs,processor_name);
MPI_Finalize();
}
完善後的運行結果:
8、MPI For Python
MPI for Python provides an object oriented approach to message passing which grounds on the standard MPI-2 C++ bindings. The interface was designed with focus in translating MPI syntax and semantics of standard MPI-2 bindings for C++ to Python. Any user of the standard C/C++ MPI bindings should be able to use this module without need of learning a new interface.
- Point-to-Point Communication
#Python objects (pickle under the hood):
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
if rank == 0:
data = {'a': 7, 'b': 3.14}
comm.send(data, dest=1, tag=11)
elif rank == 1:
data = comm.recv(source=0, tag=11)
#Python objects with non-blocking communication:
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
if rank == 0:
data = {'a': 7, 'b': 3.14}
req = comm.isend(data, dest=1, tag=11)
req.wait()
elif rank == 1:
req = comm.irecv(source=0, tag=11)
data = req.wait()
- Collective Communication
#Broadcasting a Python dictionary:
from mpi4py import MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
if rank == 0:
data = {'key1' : [7, 2.72, 2+3j],
'key2' : ( 'abc', 'xyz')}
else:
data = None
data = comm.bcast(data, root=0)
#Gathering Python objects:
from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
data = (rank+1)**2
data = comm.gather(data, root=0)
if rank == 0:
for i in range(size):
assert data[i] == (i+1)**2
else:
assert data is None
9.最基本的MPI程序(實現)
MPI函數的總數雖然龐大,但根據實際編寫MPI的經驗,
常用的MPI調用的個數確實有限。
下面是6個最基本也是最常用的MPI函數:
MPI_Init(…);
MPI_Comm_size(…)
MPI_Comm_rank(…)
MPI_Send(…)
MPI_Recv(…)
MPI_Finalize()