目录
1、MPI基本函数
#include <stdio.h>
#include "mpi.h"
int main(int argc, char** argv){
int rank,size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &rank);
printf("I am %d.\n", rank);
printf("There are %d processes.\n",size);
MPI_Finalize();
return 0;
}
MPI_Init(&argc, &argv)
告知MPI系统进行所有必要的初始化设置。例如,系统可能需要为消息缓冲区分配存储空间,为进程指定进程号等
.PS:在调用MPI_Init前不应该调用其他MPI函数
MPI_Finalize()
用来清理 MPI 环境的。这个调用之后就没有 MPI 函数可以被调用了。
MPI_Comm_rank(MPI_COMM_WORLD, &rank)
返回 communicator 中当前进程的 rank。 communicator 中每个进程会以此得到一个从 0 开始递增的数字作为 rank 值。rank 值主要是用来指定发送或者接受信息时对应的进程。
MPI_Comm_size(MPI_COMM_WORLD, &rank)
返回 communicator 的大小,也就是 communicator 中可用的进程数量。
2、点对点通信函数
例、使用MPI,计算cos x 函数的积分值,积分区间为(0,2PI)
#include<stdio.h>
#include "mpi.h"
#include "math.h"
int main(int argc,char **argv)
{
int size, rank,n,p,i;
double h;
MPI_Comm comm = MPI_COMM_WORLD;
n = 4;
MPI_Init(&argc, &argv);
MPI_Comm_size(comm,&size);
MPI_Comm_rank(comm,&rank);
h = M_PI/2/n;
double sum = 0;
double flag;
double psum,total;
switch(rank)
{
case 0:
{
flag = 0;
break;
}
case 1:
{
flag = M_PI/2;
break;
}
case 2:
{
flag = M_PI;
}
case 3:
{
flag = 1.5*M_PI;
}
}
for(i = 0; i < n;i++)
{
sum += fabs(cos(flag+i*h+h/2.0)*h);
}
if(rank != 0)
{
MPI_Send(&sum, 1, MPI_DOUBLE, 0, 99, comm);
}
printf("part sum of process %d is %lf.\n", rank, sum);
if(rank == 0)
{
total = sum;
for(i = 1; i < 4; i++)
{
MPI_Recv(&psum, 1, MPI_DOUBLE, i, 99, comm, &status);
total += psum;
}
printf("sum is %lf.\n",total);
}
MPI_Finalize();
return 0;
}
MPI_Send
MPI_Send(
void* data,
int count,
MPI_Datatype datatype,
int destination,
int tag,
MPI_Comm communicator)
本端点发送包含 count 个 datatype 类型的数据 *data 给 rank 为 destination 的目标端点,数据标签为 tag,通讯器为 communicator(通常为 MPI_COMM_WORLD)。
该方法会阻塞直到发送缓存可以被回收。这意味着当网络可以缓冲消息时,该方法就可以返回;如果网络不可以缓存消息,就会一直阻塞至遇到匹配的接受方法。
datatype 取值有:
MPI_Recv
MPI_Recv(
void* data,
int count,
MPI_Datatype datatype,
int source,
int tag,
MPI_Comm communicator,
MPI_Status* status)
本端点接受 rank 为 source (不限制时用 MPI_ANY_SOURCE )的源端点传来的,标签为 tag (不限制时用 MPI_ANY_TAG),类型为 datatype 的数据,数据保存在 *data 中,最大长度为 count,实际接受的数据长度和 tag 保存在 status 中,status.MPI_SOURCE 为实际接受的源 rank,status.MPI_TAG 为实际接受的 tag,通讯器为 communicator。
该方法会阻塞来接受匹配 source 和 tag 的数据。
3、集体通信函数
例、
1.求数组最大值
2.每个进程处理一部分数组元素
3.每个进程在程序结束的时候需要知道最大值
MPI_Bcast
MPI_Bcast(
void* data,
int count,
MPI_Datatype datatype,
int root,
MPI_Comm communicator)
一个广播发生的时候,一个进程会把同样一份数据传递给一个 communicator 里的所有其他进程。根节点调用 MPI_Bcast 函数的时候,data 变量里的值会被发送到其他的节点上。当其他的节点调用 MPI_Bcast 的时候,data 变量会被赋值成从根节点接受到的数据。
实现使用了一个树形广播算法来获得比较好的网络利用率。
MPI_Scatter
MPI_Scatter(
void* send_data,
int send_count,
MPI_Datatype send_datatype,
void* recv_data,
int recv_count,
MPI_Datatype recv_datatype,
int root,
MPI_Comm communicator)
root 进程执行该函数时,接收一个数组 send_data,并把元素按进程的秩分发出去,给每个进程发送 send_count 个元素。其他进程包括(root)执行该函数时,收到 recv_count 个 revc_datatype 类型的数据,存放在数组 recv_data 中。
MPI_Gather
MPI_Gather(
void* send_data,
int send_count,
MPI_Datatype send_datatype,
void* recv_data,
int recv_count,
MPI_Datatype recv_datatype,
int root,
MPI_Comm communicator)
所有进程执行该函数时,从 send_datatype 类型的数组 send_data 中取出前 send_count 个元素,发送给 root 进程。root 进程同时还会将从每个进程中收集到的 recv_count 个数据,存放在 recv_data 数组中。