【MPI学习1】简单MPI程序示例

来源:互联网 发布:面包板与单片机的连接 编辑:程序博客网 时间:2024/06/06 05:01

有了apue的基础,再看mpi程序多进程通信就稍微容易了一些,以下几个简单程序来自都志辉老师的那本MPI的书的第七章。

现在ubuntu上配置了一下mpich的环境:

http://www.cnblogs.com/liyanwei/archive/2010/04/26/1721142.html

注意,为了编译运行方便,在~/.bashrc文件中添加mpi的两个环境变量

设置完之后注意执行source ~/.bashrc命令

 

程序1 计时功能

主要用到的MPI_Wtime()这个函数

复制代码
 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h>  4 #include "mpi.h" 5  6 int main(int argc, char *argv[]) 7 { 8     int err = 0; 9     double t1, t2;10     double tick;11     int i;12 13     MPI_Init(&argc, &argv);14     t1 = MPI_Wtime();15     t2 = MPI_Wtime();16     if (t2-t1>0.0 || t2-t1<0.0) {17         err++;18         fprintf(stderr, "two successive calls to MPI_Wtime gave strange results: (%f)(%f)\n", t1, t2);19     }20 21     for( i=0; i<10; i++)22     {23         t1 = MPI_Wtime();24         sleep(1);25         t2 = MPI_Wtime();26         if (t2-t1>=(1-0.1) && t2-t1<=5) {27             break;28         }29         if (t2-t1>5.0) {30             i = 9;31         }32     }33     if (i==10) {34         fprintf(stderr, "timer around sleep(1) did not give 1 second; gave %f\n", t2-t1);35         err++;36     }37     tick = MPI_Wtick();38     if (tick>1.0 || tick<0.0) {39         err++;40         fprintf(stderr, "MPI_Wtick gave a strange result:(%f)\n", tick);41     }42     MPI_Finalize();43 }
复制代码

执行结果如下(在程序中故意设定了触发问题):

 

程序2 进程间数据接力传送

这里主要是MPI_Send和MPI_Recv两个函数,发送和接受来自其他进程的消息

代码如下:

复制代码
 1 #include <stdio.h> 2 #include "mpi.h" 3  4 int main(int argc, char *argv[]) 5 { 6     int rank, value, size; 7     MPI_Status status; 8     MPI_Init(&argc, &argv); 9     MPI_Comm_rank(MPI_COMM_WORLD, &rank); /*当前进程在MPI_COMM_WORLD这个通信组下面 编号是多少*/10     MPI_Comm_size(MPI_COMM_WORLD, &size); /*MPI_COMM_WORLD这个通信组下面 有多少个进程*/ 11     do {12         if (rank==0) {13             fprintf(stderr, "\nPlease give new value=");14             scanf("%d",&value);15             fprintf(stderr, "%d read <-<- (%d)\n",rank,value);16             /*必须至少有两个进程的时候 才能进行数据传递*/17             if (size>1) {18                 MPI_Send(&value, 1, MPI_INT, rank+1, 0, MPI_COMM_WORLD);19                 fprintf(stderr, "%d send (%d)->-> %d\n", rank,value,rank+1);20             }21         }22         else {23             MPI_Recv(&value, 1, MPI_INT, rank-1, 0, MPI_COMM_WORLD, &status);24             fprintf(stderr, "%d receive(%d)<-<- %d\n",rank, value, rank-1);25             if (rank<size-1) {26                 MPI_Send(&value, 1, MPI_INT, rank+1, 0, MPI_COMM_WORLD);27                 fprintf(stderr, "%d send (%d)->-> %d\n", rank, value, rank+1);28             }29         }30         MPI_Barrier(MPI_COMM_WORLD);31     }while(value>=0);32     MPI_Finalize();33 }
复制代码

执行结果如下:

这里注意运行时候,参数 -np 4的意思是设置开启4个进程

 

程序3 进程间互相发送数据

复制代码
 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "mpi.h" 4  5 void Hello(void); 6  7 int main(int argc, char *argv[]) 8 { 9     int me, option, namelen, size;10     char process_name[MPI_MAX_PROCESSOR_NAME];11     MPI_Init(&argc, &argv);12     MPI_Comm_rank(MPI_COMM_WORLD, &me);13     MPI_Comm_size(MPI_COMM_WORLD, &size);14 15     if (size < 2) {16         fprintf(stderr, "system requires at least 2 processes");17         MPI_Abort(MPI_COMM_WORLD, 1);18     }19     MPI_Get_processor_name(process_name, &namelen);20     fprintf(stderr, "Process %d is alive on %s\n", me, process_name);21     MPI_Barrier(MPI_COMM_WORLD);22     Hello();23     MPI_Finalize();24 }25 26 void Hello()27 {28     int nproc, me;29     int type = 1;30     int buffer[2], node;31     MPI_Status status;32     MPI_Comm_rank(MPI_COMM_WORLD, &me);33     MPI_Comm_size(MPI_COMM_WORLD, &nproc);34     if (me==0) {35         printf("\nHello test from all to all\n");36         fflush(stdout);37     }38     for(node = 0; node < nproc; node++)39     {40         if (node != me) {41             buffer[0] = me;42             buffer[1] = node;43             MPI_Send(buffer, 2, MPI_INT, node, type, MPI_COMM_WORLD);44             MPI_Recv(buffer, 2, MPI_INT, node, type, MPI_COMM_WORLD, &status);45             if (buffer[0] != node || buffer[1] != me) {46                 fprintf(stderr, "Hello: %d != %d or %d != %d\n", buffer[0], node, buffer[1], me);47                 printf("Mismatch on hello process ids; node = %d\n",node);48             }49             printf("Hello from %d to %d\n",me,node);50             fflush(stdout);51         }52     }53 }
复制代码

执行结果如下:

 

 

程序4 多个进程向一个进程发送消息

复制代码
 1 #include "mpi.h" 2 #include <stdio.h> 3  4 int main(int argc, char *argv[]) 5 { 6     int rank, size, i, buf[1]; 7     MPI_Status status; 8     MPI_Init(&argc, &argv); 9     MPI_Comm_rank(MPI_COMM_WORLD, &rank);10     MPI_Comm_size(MPI_COMM_WORLD, &size);11     if (rank==0) {12         /*主进程不断接收从各个进程发送过来的消息*/13         for(i=0; i<5*(size-1); i++)14         {15             MPI_Recv(buf, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);16             printf("Msg=%d from %d with tag %d\n",buf[0], status.MPI_SOURCE, status.MPI_TAG);17         }18     }19     else {20         /*其他进程向主进程发送消息*/21         for(i=0; i<5; i++)22         {23             buf[0] = rank+i;24             MPI_Send(buf, 1, MPI_INT, 0, i, MPI_COMM_WORLD);25         }26     }27     MPI_Finalize();28 }
复制代码

执行结果如下:

 

上面几个程序的核心是MPI_Send和MPI_Recv,在上面的程序中来看,这两个函数都是阻塞函数。

因此,进程之间如果有消息的互相发送和接收,就可能会产生死锁现象。

这个书上P47~49有说明,但是由于涉及到MPI通讯模式的问题,因此留到后面再看。

 

这几个程序目的是为了数据mpi的编译运行环境以及一些基本函数,后面开始学习并行程序的设计方法。

原创粉丝点击