• 【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)
    ", 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
    ", 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)
    ", 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, "
    Please give new value=");
    14             scanf("%d",&value);
    15             fprintf(stderr, "%d read <-<- (%d)
    ",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
    ", 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
    ",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
    ", 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
    ", 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("
    Hello test from all to all
    ");
    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
    ", buffer[0], node, buffer[1], me);
    47                 printf("Mismatch on hello process ids; node = %d
    ",node);
    48             }
    49             printf("Hello from %d to %d
    ",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
    ",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的编译运行环境以及一些基本函数,后面开始学习并行程序的设计方法。

  • 相关阅读:
    secureCRT 6.5 ssh登陆openeuler提示交换秘钥不支持
    ediary电子日记本-力荐
    centos8.4 iso下载地址
    Manjaro Cutefish 安装体验类似macos风格
    脚本启动第一行提示sh/bash找不到
    securecrt双击克隆会话
    开源的window/linux远程连接工具-mRemoeteNG
    securecrt设置日志缓存
    怎么实现通过扫描二维码进行登录
    使用link rel="shortcut icon"为网页标题加图标
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/5140675.html
Copyright © 2020-2023  润新知