个人主页:丷从心·
系列专栏:并行计算
3.1|预备知识
编译与执行
打印来自进程问候语句的MPI程序
#include <stdio.h>
#include <string.h>
#include <mpi.h>
const int MAX_STRING = 100;
int main(void)
{
char greeting[MAX_STRING];
int comm_sz;
int my_rank;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
if (my_rank != 0)
{
sprintf(greeting, "Greetings from process %d of %d!", my_rank, comm_sz);
MPI_Send(greeting, strlen(greeting) + 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
}
else
{
printf("Greetings from process %d of %d!\n", my_rank, comm_sz);
for (int q = 1; q < comm_sz; q++)
{
MPI_Recv(greeting, MAX_STRING, MPI_CHAR, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("%s\n", greeting);
}
}
MPI_Finalize();
return 0;
}
编译
mpicc -g -Wall -o mpi_hello mpi_hello.c
执行
mpiexec -n 4 ./mpi_hello
通信子
- 通信子指的是一组可以互相发送消息的进程集合
- 通信子称为
MPI_COMM_WORLD
SPMD程序
- S P M D SPMD SPMD是指单程序多数据流
- 一个单一程序,让不同进程产生不同动作,让进程按照它们的进程号来匹配程序分支
MPI_Send()方法
- 参数
tag
是个非负int
型,用于区分看上去完全一样的消息,例如tag
为 0 0 0表示消息用于打印,tag
为 1 1 1表示消息用于计算 - 一个通信子中的进程所发送的消息不能被另一个通信子中的进程所接收
status_p参数
MPI_Status
是一个有至少三个成员MPI_SOURCE
、MPI_TAG
、MPI_ERROR
的结构- 接收到的数据量不是存储在应用程序可以直接访问到的域中,可以通过调用
MPI_Get_count
函数找回这个值
int MPI_Get_count(MPI_Status* status_p, MPI_Datatype type, int* count_p)
MPI_Send()和MPI_Recv()的语义
MPI_Send()
典型的实现方法有一个默认的消息截止大小,如果一条消息的大小小于截止大小,它将被缓冲;如果大于截止大小,那么MPI_Send()
函数将被阻塞- M P I MPI MPI要求消息是不可超越的,即如果 q q q号进程发送了两条消息给 r r r号进程,那么 q q q进程发送的第一条消息必须在第二条消息之前可用
潜在的陷阱
- 如果一个进程试图接收消息,但没有相匹配的消息,那么该进程将会被永远阻塞在那里,即进程悬挂
- 如果调用
MPI_Send()
发生了阻塞,并且没有相匹配的接收,那么发送进程就悬挂;如果调用MPI_Send()
被缓冲,但没有相匹配的接收,那么消息将被丢失