MPI易于入门 |
对于基本的应用,MPI同其它消息传送系统一样易于使用。下面的样本代码包含了用于动态负载平衡的主/从应用的全部通信框架。下面的代码描述了一些编写典型并行应用程序所需的函数。
#include <mpi.h> #define WORKTAG 1 #define DIETAG 2 main(argc, argv) int argc; char *argv[]; { int myrank; MPI_Init(&argc, &argv); /* MPI 初始化 */ MPI_Comm_rank( MPI_COMM_WORLD, /* 总使用 */ &myrank); /* 进程标识数,0到N-1 */ if (myrank == 0) { master(); } else { slave(); } MPI_Finalize(); /* MPI 结束*/ } master() { int ntasks, rank, work; double result; MPI_Status status; MPI_Comm_size( MPI_COMM_WORLD, /* 总使用 */ &ntasks); /* #应用程序中的进程 */ /* * Seed the slaves. */ for (rank = 1; rank < ntasks; ++rank) { work = /* get_next_work_request */; MPI_Send(&work, /* 消息缓冲区 */ 1, /* 一个数据项 */ MPI_INT, /* 数据项是整数 */ rank, /* 目的进程标识数 */ WORKTAG, /* 用户所选的进程标识 */ MPI_COMM_WORLD);/* 总使用 */ } /* * 从任意从属进程接收结果,同时分派新工作 * 工作请求已用尽 */ work = /* 得到下一个工作请求 */; while (/* 有效的新工作请求 */) { MPI_Recv(&result, /* 消息缓冲区 */ 1, /* 一个数据项 */ MPI_DOUBLE, /* 双精度实类型 */ MPI_ANY_SOURCE, /* 从任意发送者接受 */ MPI_ANY_TAG, /* 任意消息类型 */ MPI_COMM_WORLD, /* 总使用 */ &status); /* 所接受的消息信息 */ MPI_Send(&work, 1, MPI_INT, status.MPI_SOURCE, WORKTAG, MPI_COMM_WORLD); work = /* 得到下一个工作请求 */; } /* * 为优异的工作请求接收结果 */ for (rank = 1; rank < ntasks; ++rank) { MPI_Recv(&result, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); } /* * 告知所有的从属进程退出 */ for (rank = 1; rank < ntasks; ++rank) { MPI_Send(0, 0, MPI_INT, rank, DIETAG, MPI_COMM_WORLD); } } slave() { double result; int work; MPI_Status status; for (;;) { MPI_Recv(&work, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); /* * 检查所接受消息的标识 */ if (status.MPI_TAG == DIETAG) { return; } result = /* 工作 */; MPI_Send(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); } }
进程由一个唯一的“标识数”(整数)表示,标识数为数0、1、2、……、N-1。MPI_COMM_WORLD指“MPI应用中的所有进程”,它称为通信子,并且提供消息传递所需的所有信息。可移植库对通信子做更多的工作,以提供大多数其它系统所不能处理的同步保护。
与其它系统一起,提供两个函数来初始化和结束MPI进程:
MPI_Init(&argc, &argv); MPI_Finalize( );
典型地,并行程序中的进程需要知道它是谁(它的标识数)以及其它进程是怎样存在的。一个进程通过调用MPI_Comm_rank( )来发现它自己的标识数:
int myrank; MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Comm_size( )返回进程总数:
int nprocs; MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
消息是一组给定数据类型的元素。MPI支持所有的基本数据类型,并且允许更复杂的应用程序在运行时间构造新的数据类型。
消息被发给一个指定的进程,而且用一个由用户说明的标识来标记。标识用来区分不同的由一个进程所能发送/接受的消息类型。在上面的样本代码中,标识用于区分工作和结束消息。
MPI_Send(buffer, count, datatype, destination, tag, MPI_COMM_WORLD);
接受进程说明标识和发送进程的标识数。MPI_ANY_TAG和MPI_ANY_SOURCE可选地用于接受任意标识和从任意发送进程而来的消息。
MPI_Recv(buffer, maxcount, datatype, source, tag, MPI_COMM_WORLD, &status);
有关所接受消息的信息在一个状态变量中返回。所接受消息的标识是status.MPI_TAG,发送进程的标识数是status.MPI_SOURCE。
另一函数,在样本代码中没有使用,返回所接受的数据元素的个数。当所接受的元素个数小于‘最大数’时使用它。
MPI_Get_count(&status, datatype, &nelements);
通过这些函数,你会准备编写任意的应用。在MPI中有许多其它、更特异的函数,但是迄今为止所有这些函数可以在这里提到的函数上构造。
Copyright: NPACT |