【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的编译运行环境以及一些基本函数,后面开始学习并行程序的设计方法。

时间: 2024-11-07 01:32:56

【MPI学习1】简单MPI程序示例的相关文章

【MPI学习3】MPI并行程序设计模式:不同通信模式MPI并行程序的设计

学习了MPI四种通信模式 及其函数用法: (1)标准通信模式:MPI_SEND (2)缓存通信模式:MPI_BSEND (3)同步通信模式:MPI_SSEND (4)就绪通信模式:MPI_RSEND 四种通信模式的区别都在消息发送端,而消息接收端的操作都是MPI_RECV. 1.标准通信模式 原理图如下 标准通信模式由MPI决定是否用缓存. 如果MPI决定缓存将要发出的数据:发送操作不管接受操作是否执行,都可以进行:而且缓存结束后发送操作就可以返回,不需要等待接受操作收到数据 如果MPI决定不缓

【MPI学习2】MPI并行程序设计模式:对等模式 &amp; 主从模式

这里的内容主要是都志辉老师<高性能计算之并行编程技术——MPI并行程序设计> 书上有一些代码是FORTAN的,我在学习的过程中,将其都转换成C的代码,便于统一记录. 这章内容分为两个部分:MPI对等模式程序例子 & MPI主从模式程序例子 1. 对等模式MPI程序设计 1.1 问题背景 这部分以Jacobi迭代为具体问题,列举了三个求解Jacobi迭代问题的MPI对等模式程序. 这里需要阐明一下,书上的Jacobi迭代具体的背景可以参考这个内容:http://www.mcs.anl.g

【MPI学习6】MPI并行程序设计模式:具有不连续数据发送的MPI程序设计

基于都志辉老师<MPI并行程序设计模式>第14章内容. 前面接触到的MPI发送的数据类型都是连续型的数据.非连续类型的数据,MPI也可以发送,但是需要预先处理,大概有两类方法: (1)用户自定义新的数据类型,又称派生类型(类似定义结构体类型,但是比结构体复杂,需要考虑<类型,偏移量>两方面的内容) (2)数据的打包和解包(将不连续的数据给压缩打包到连续的区域,然后再发送:接受到打包数据后,先解包再使用) 这样做的好处,我猜一个是可以有效减少通信的次数,提高程序效率:另一方面可以减轻

DuiLib学习笔记2——写一个简单的程序

我们要独立出来自己创建一个项目,在我们自己的项目上加皮肤这才是初衷.我的新建项目名为:duilibTest 在duilib根目录下面有个 Duilib入门文档.doc 我们就按这个教程开始入门 首先新建一个win32项目 去DuiLib根目录,把目录下DuiLib文件夹拷贝到新建项目的根目录.再把这个项目添加进我们解决方案中. 从教程里面把以下代码粘贴到我们项目的stdafx.h中 // Duilib使用设置部分 #pragma once #define WIN32_LEAN_AND_MEAN

单片机 学习笔记(二)——简单小程序

今天收获了单片机的几个简单小程序:     延时程序: void Delay(unsigned int xx) //输入 xx :ms { while(xx--) { Delay1ms(); } } void Delay1ms() //@11.0592MHz 1ms { unsigned char i, j; _nop_(); _nop_(); _nop_(); i = 11; j = 190; do { while (--j); } while (--i); } 流水灯程序: #include

【opengl 学习笔记01】HelloWorld示例

<<OpenGL Programming Guide>>这本书是看了忘,忘了又看,赶脚还是把笔记做一做心里比较踏实,哈哈. 我的主题是,好记性不如烂笔头. ================================================================ 1. 下载glut库 glut库地址为:www.opengl.org/resources/libraries/glut/glutdlls37beta.zip glut全称为:OpenGL Utilit

UNIX网络编程笔记(4)—TCP客户/服务器程序示例

TCP客户/服务器程序示例 这一章信息量开始大起来了,粗略来看它实现了简单的TCP客户/服务器程序,里面也有一些费解的细节. 1.概述 完整的TCP客户/服务器程序示例.这个简单的例子将执行如下步骤的一个回射服务器(这里的回射服务器就是服务简单的把客户端发送的消息返回给客户): 1)客户从标准输入读入一行文本,并写给服务器 2)服务器从网络输入读入这行文本,并回射给客户 3)客户从网络输入读入这行回射文本,并显示在标准输出上 这样实际上就构成了一个全双工的TCP连接. 本章就围绕了这个简单的TC

(java)selenium webdriver学习---实现简单的翻页,将页面内容的标题和标题链接取出

selenium webdriver学习---实现简单的翻页,将页面内容的标题和标题链接取出: 该情况适合能能循环page=1~n,并且每个网页随着循环可以打开的情况, 注意一定是自己拼接的url可以打开,如:http://ask.testfan.cn/articles?page=15,就可以翻到文章分类的第15页: import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.u

初学Java:整理的几个简单小程序以及初学心得

整理这几天里写的几个小程序,都是循环练习//设N是一个四位数,它的9倍恰好是其反序数//(例如:1234的反序数是4321),求N值package Azhi;public class Job_5 {public static void main(String[] args) { for(int n=1000;n<=9999;n++){ int ge=n%10; int shi=n%100/10; int bai=n%1000/100; int qian=n/1000; int temp=ge*1

gdb 调试openmp多线程程序 示例介绍

 首先一个简单程序源代码: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <omp.h> 4 int main(int argc, char * argv[]){ 5 int i, k,m,n; 6 printf("i=%d,threads_num=%d\n",i, omp_get_num_threads()); 7 printf("i=%d,thread_id=%d\n&quo