简单的MPI+Fortran95实现

发布于:2022-12-20 ⋅ 阅读:(428) ⋅ 点赞:(0)

MPI程序实现

       作为比较“古老”的多核多线程并行技术,MPI已逐渐被CUDA等异构编程所取代。两者有本质区别,前者是一种库函数,面向编程语言本身,利用特定语句来指定CPU中各线程来分工完成任务。后者在GPU上实现,利用的主要是GPU具有大量运算单元的优势,从硬件本身来实现并行。若要从程序本身上实现并行,MPI实现并行计算则更加有优势。MPI是一种消息传递编程模型,目的是服务于进程间的通信。使用者需要一定的进程消息传递的空间想象能力。

参考书

高性能计算之并行编程技术——MPI并行程序设计(都志辉)

获取途径

1、MPICH是一种最重要的MPI实现,可以免费从http://www-unix.mcs.anl.gov/mpi/mpich 获得。
2、CHIMP是另一个免费的MPI实现,可以从ftp://ftp.epcc.ed.ac.uk/pub/packages/chimp/release/        中获得。
3、Ubuntu官网Ubuntu – Ubuntu Packages Search中下载。

并行程序实现

       一个MPI并行程序主要由5部分构成,分别是头文件、相关变量声明、程序开始、程序体计算与通信、程序结束 。废话不多说,直接上实例,以下代码实现在5个进程中分别打印“Hello World"

program main
    use mpi
    character(MPI_MAX_PROCESSOR_NAME) :: processor_name
    integer :: myid, numprocs, namelen, rc, iree

    call MPI_INIT(ierr)
    call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr)
    call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
    call MPI_GET_PROCESSOR_NAME(processor_name, namelen, ierr)
    write(*,10) myid, numprocs, processor_name
10  format('Hello World',I2,' of',I1,' on ',20A)
    call MPI_FINALIZE(rc)
    end program

程序第二行“use mpi”是头文件,我用的是Fortran95,用Fortran77的写法应该为“include”写法。第四行声明了需要使用的相关变量。第六行是程序开始,任何MPI程序写法都一样。第七至第十行是程序计算与通信部分,此程序还未涉及任何消息传递的过程。倒数第二行是程序结束命令。程序整体实现流程图如下。

程序实现流程图

输出结果:

Hello World 2 of 5 on nuaa-Super-server
Hello World 1 of 5 on nuaa-Super-server
Hello World 0 of 5 on nuaa-Super-server
Hello World 4 of 5 on nuaa-Super-server
Hello World 3 of 5 on nuaa-Super-server

 由于每一次输出顺序未指定,因此四个线程同时进行输出。

消息发送、消息接受、返回状态

消息发送

MPI_SEND(buf,count,datatype,dest,tag,comm)

IN  buf 发送缓冲区的起始地址(可选类型)

IN  count 将发送的数据的个数(非负整数)

IN  datatype 发送数据的数据类型(句柄)

IN  dest 目的进程标识号(整型)

IN  tag 消息标志(整型)

IN  comm 通信域(句柄)

消息接收

MPI_RECV(buf,count,datatype,source,tag,comm,status)

OUT  buf 接收缓冲区的起始地址(可选数据类型)

IN  count 最多可接收的数据的个数(整型)

IN  datatype 接收数据的数据类型(句柄)

IN source 发送数据的进程的进程标识号(整型)

IN  tag 消息标识 (整型)

IN  comm 本进程和发送进程所在的通信域(句柄)

返回状态

OUT  status 返回状态 (状态类型)

例子

         现在我们来利用消息的发送和接受实现一个并行计算,程序实现1+2+3+……+100,分别利用5个进程进行计算,进程1负责计算1+2+……+25;进程2负责计算26+27+……+50;进程3负责计算51+52+……+75;进程4负责计算76+77+……+100;进程0负责将进程1234的计算结果汇总。需要注意的是,在并行计算中0进程往往不参与并行运算,它往往是多个运算进程的汇总。这就是我们常说的主从模式MPI设计。

program main
      use mpi
      implicit none
      integer,parameter :: num=100, nccp=4
      integer,save :: myid, numprocs, namelen, rc, ierr
      integer,save :: istat(MPI_STATUS_SIZE)
      integer(8) :: i, objval, temp_objval
      call MPI_INIT(ierr)
      call MPI_COMM_RANK(MPI_COMM_WORLD, myid, ierr)
      call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr)
      objval=0
      temp_objval=0
      if(myid.ne.0) then
          do i=(myid-1)*(num/nccp)+1, myid*(num/nccp)
             temp_objval=temp_objval+i
          end do
          write(*,10) myid, temp_objval
10        format('Process',I2,' calculation is :',I6)
          call MPI_SEND(temp_objval, 1, MPI_INTEGER8, 0, mpi_tag,MPI_COMM_WORLD, ierr)
      else
          do i=1, nccp
             call MPI_RECV(temp_objval, 1, MPI_INTEGER8, i,mpi_any_tag, MPI_COMM_WORLD, istat, ierr)
             objval=temp_objval+objval
          end do
          write(*,20) objval
20        format('The final result is :',I6)
      end if
      call MPI_FINALIZE(rc)
      end program main

本文含有隐藏内容,请 开通VIP 后查看