【MPI學習1】簡單MPI程序示例


有了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的編譯運行環境以及一些基本函數,后面開始學習並行程序的設計方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM