MPI学习笔记(一):初识MPI
參考自:https://www.cnblogs.com/hantan2008/p/5452353.html#3697454
1. 安裝:
Ubuntu 里似乎很簡單
sudo apt-get install mpich
2. 編寫 mpi 程序
#include<iostream>
using namespace std;
#include"mpi.h"
#include<cmath>
int main(int argc, char ** argv){
int myid, numprocs;
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
", myid, numprocs, processor_name);
MPI_Finalize();
cout<<" argc = "<<argc<<endl;
int n=0;
for(int i=0;i<argc;i++){
cout<<"i="<<i<<" argv[i] = "<<argv[i]<<endl;
}
return 0;
}
需要包含 "mpi.h"
其中,MPI_Init( int * argc_p, char *** argv_p ) 是初始化函數,叫電腦知道,做好 mpi 相關的初始化。傳入的 argc_p, argv_p 是指向 main 函數的命令行參數 argc, argv 的指針。如果沒有命令行參數,也可以輸入 NULL。
MPI_COMM_WORLD:通訊子,“一組可以互發消息的進程集合”
int MPI_Comm_rank( __in MPI_Comm comm, __out int * rank ) :第一個參數是輸入參數——通信子,第二個參數是輸出參數——進程號。
int MPI_Comm_size( __in MPI_Comm comm, __out int * size ):第一個參數是輸入參數——通信子,第二個參數是輸出參數——通信子中總進程數。
MPI_MAX_PROCESSOR_NAME:似乎是一個整數,值為128.
MPI_Get_processor_name( ..):得到處理器的名字
int MPI_Send (void *buf, int count, MPI_Datatype datatype,int dest, int tag,MPI_Comm comm):點對點發送消息。
*buf: 發送緩沖區,指向發送的變量地址
count: 發送的數據個數
datatype:發送的數據類型
dest: 目標進程序號,取值為 0 到 np-1 的整數
tag: 消息標簽,取值為 0 到 MPI_TAG_UB
comm:通信器
int MPI_Recv (void *buf, int count, MPI_Datatype datatype,int source, int tag, MPI_Comm comm,MPI_Status *status):點對點接收消息。
與 MPI_Send 相似,不同的是 MPI_Status * status 為接收狀態。MPI_Status 似乎是 MPI 自己定義的一個類,估計手冊上有。
3. 編譯 mpi 并行程序
mpicxx main.cpp
4. 運行 mpi 并行程序
mpirun -np 2 ./a.out
其中,np 表示進程數。
得到結果為
Hello World! Processor 0 of 2 on DESKTOP_1IJIBGL Hello World! Processor 0 of 2 on DESKTOP_1IJIBGL argc = 1 i=0 argv[i] = ./a.out argc = 1 i=0 argv[i] = ./a.out
令我不解的是,代碼中 MPI_Finilize(); 后面的內容也被執行了兩遍。
5. 點對點通信
#include<iostream>
using namespace std;
#include"mpi.h"
#include<cmath>
int main(int argc, char ** argv){
int myid, numprocs;
int namelen;
char processor_name [ MPI_MAX_PROCESSOR_NAME ];
int ha;
int i;
int total = 0;
MPI_Init( &argc, &argv);
MPI_Comm_rank( MPI_COMM_WORLD, & myid);
MPI_Comm_size( MPI_COMM_WORLD, & numprocs);
if( myid !=0 ){
ha = myid;
MPI_Send( &ha, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
}
else{
for( i = 1; i < numprocs; i++){
MPI_Recv( &ha, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
total += ha;
}
cout<< " total = "<<total<<endl;
}
MPI_Finalize();
return 0;
}
編譯上面的文件以后,運行
mpirun -np n ./a.out
則會得到 n(n-1)/2
進程 1,2,..., np-1 會向進程 0 發送 其序號的值,而進程 0 將收到的這些值全部加起來。
6. 集體通信 (collective communications)
包括各種 點對多,多對點,多對多,可參考第一排的鏈接,或者官網上的 documentation,我還沒搞到一本比較全的 documentation。
這里先試用一下 int MPI_Reduce (void *sendbuf, void *recvbuf, int count,MPI_Datatype datatype, MPI_Op op, int root,MPI_Comm comm)
op 可以是 MPI_MAX, MPI_MIN, MPI_SUM, MPI_PROD 等等。root 為根進程的序號。
#include<iostream>
using namespace std;
#include"mpi.h"
#include<cmath>
int main(int argc, char ** argv){
int myid, numprocs;
int namelen;
char processor_name [ MPI_MAX_PROCESSOR_NAME ];
int ha;
int i;
int total = 0;
MPI_Init( &argc, &argv);
MPI_Comm_rank( MPI_COMM_WORLD, & myid);
MPI_Comm_size( MPI_COMM_WORLD, & numprocs);
MPI_Reduce( & myid, & total, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );
if( myid ==0 ){
cout<<" total = "<<total<<endl;
}
MPI_Finalize();
return 0;
}
和之前的程序功能一樣,都是計算 n(n-1)/2,但是一行就搞定了。
總結
以上是生活随笔為你收集整理的MPI学习笔记(一):初识MPI的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 螺栓的材料及技术标准
- 下一篇: MediaWIKI部署流程