找回密码
 注册
查看: 1581|回复: 0

MPI入门

[复制链接]
发表于 2004-6-2 14:54:33 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
   
对于基本的应用,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);
   }
}
MPI世界
进程由一个唯一的“标识数”(整数)表示,标识数为数0、1、2、……、N-1。MPI_COMM_WORLD指“MPI应用中的所有进程”,它称为通信子,并且提供消息传递所需的所有信息。可移植库对通信子做更多的工作,以提供大多数其它系统所不能处理的同步保护。
进入和退出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中有许多其它、更特异的函数,但是迄今为止所有这些函数可以在这里提到的函数上构造。
  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表