第一個例子:MPI最常用的6個調用說明,以"Hello_World.f90"為例


MPI Massage Passing Interface. 一旦完成初始化,在結束MPI之前,除非特別指定,每個進程都會完全一致地執行相同的命令。

在MPI中有上百個調用接口,但是最常用的只有幾個,掌握這幾個調用的用法,就可以快速上手並行計算編程了。一旦入門,之后的學習就會簡單許多。

 !!!!!!!!!

  MPI_INIT    MPI_COMM_RANK   MPI_COMM_SIZE   MPI_SEND   MPI_RECV   MPI_FINALIZE

 !!!!!!!!!

頭文件

1 use mpi

Fortran90使用 use mpi 加載MPI頭文件。

 

MPI_INIT,並行環境MPI初始化。

MPI_INIT(ierr)

!!!說明!!!

MPI初始化后,返回一個錯誤代碼 ierr。這個ierr在定義變量的時候,也要定義

說明:MPI程序的第一個調用,完成MPI的初始化工作,所有MPI程序的第一條可執行語句都是這個。一旦完成初始化,在結束MPI之前,除非特別指定,每個進程都會完全一致地執行相同地命令。比如10行,11行,和13行,這些命令所有的進程都會執行一遍,因此,在運行程序后,會看到屏幕上有4行write的內容。但是如果有特別指定,比如17行if判斷,只有符合條件的進程才會執行if內的命令。

 

MPI_COMM_RANK,當前進程標識。

MPI_COMM_RANK(COMM,RANK,IERROR)
!!!說明!!!

COMM -- 該進程所在的通信域,定義在該通信域中的進程processor都在該通信域中通信。不同的通信域有不同的名稱
RANK -- 調用進程processor在COMM通信域中的標識號,意思就是給不同的進程都取名字,比如用4個核並行計算,那么名字就是0,1,2,3,從0開始標記,並且一般把0,也就是第一個進程看作主進程
IERROR -- 和上邊的ierr一樣,都是返回的錯誤代碼

說明:這一調用返回調用進程在給定的通信域中的進程標識號,有了這一標識號,不同的進程就可以將自身和其它的進程區別開來,實現各進程的並行和協作。

 

MPI_COMM_SIZE,通信域包含的進程數

MPI_COMM_SIZE(COMM,SIZE,IERROR)
!!!說明!!!

COMM -- 通信域
SIZE -- 該通信域COMM中總共有多少個進程,就是用了多少個核並行計算
IERROR -- 返回的錯誤代碼

說明:這一調用返回給定的通信域中所包括的進程的個數,不同的進程通過這一調用得知在給定的通信域中一共有多少個進程在並行執行。

 

MPI_SEND,消息發送

MPI_SEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
!!!說明!!!
  BUF   -- 發送緩沖區的起始地址(可選類型),就是需要發送什么數據
  COUNT -- 將發送的數據的個數(非負整數)
  DATATYPE -- 發送數據的數據類型(句柄),就是發送的數據的類型,比如 MPI_INTEGER,MPI_CHAR 等
  DEST  -- 目的進程標識號(整型),就是要把數據發給誰(發給哪個進程)
  TAG   -- 消息標志(整型),區分此進程項同意目的進程發送的其他消息
  COMM  -- 通信域
  IERROR   -- 返回的錯誤代碼

說明:MPI_SEND將發送緩沖區中的count個datatype數據類型的數據發送到目的進程,目的進程在通信域中的標識號是dest,本次發送的消息標志是tag,使用這一標志,就可以把本次發送的消息和本進程向同一目的進程發送的其它消息區別開來。

 

MPI_RECV,消息接收

MPI_RECV(BUF, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
!!!說明!!!
  BUF      -- 接受緩沖區的起始地址(可選類型),就是需要接收什么數據
  COUNT    -- 最多可接收的數據的個數(非負整數)
  DATATYPE -- 接收數據的數據類型(句柄),就是接收的數據的類型,比如 MPI_INTEGER,MPI_CHAR 等
  SOURCE   -- 接收數據的來源即發送數據的進程的進程標識號(整型),就是要從哪個進程接收數據
  TAG      -- 消息標識 與相應的發送操作的表示相匹配相同(整型)
  COMM     -- 通信域
  STATUS   -- 返回狀態 (狀態類型)
  IERROR   -- 返回的錯誤代碼

說明:MPI_RECV從指定的進程source接收消息,並且該消息的數據類型和消息標識和本接收進程指定的datatype和tag相一致,接收到的消息所包含的數據元素的個數最多不能超過count。

status 是包含 MPI_STATUS_SIZE 個整型的數組,status(MPI_SOURCE),status(MPI_TAT)和status(MPI_ERROR)分別表示發送數據的進程標識,發送數據使用tag標識和該接收操作返回的錯誤代碼。所以在定義時,status被定義為一個為數組。
 

MPI_FINALIZE,並行環境MPI結束

MPI_FINALIZE(IERROR)
!!!說明!!!
IERROR -- 返回的錯誤代碼

 說明:MPI_FINALIZE是MPI程序的最后一個調用,它結束MPI程序的運行,它是MPI程序的最后一條可執行語句,否則程序的運行結果是不可預知的。

 

例:Hello_World.f90

 1 program main
 2 
 3   use mpi
 4   implicit none
 5 
 6   character(len=20) :: message1,message2,message3
 7   integer :: myid, ierr, status(mpi_status_size), rc, numprocs
 8 
 9   call MPI_INIT(ierr)
10   call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
11   call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)
12   write(*,*) '  process ', myid, ' of ', numprocs, ' is alive'
13 
14   if ( myid .eq. 0) then
15       message1 = 'Hello, process 1'
16       call MPI_SEND(message1,20,MPI_CHAR,1,99,MPI_COMM_WORLD,ierr)
17       message2 = 'Hello, process 2'
18       call MPI_SEND(message2,20,MPI_CHAR,2,99,MPI_COMM_WORLD,ierr)
19       message3 = 'Hello, process 3'
20       call MPI_SEND(message3,20,MPI_CHAR,3,99,MPI_COMM_WORLD,ierr)
21   else if ( myid .eq. 1 ) then
22       call MPI_RECV(message1,20,MPI_CHAR,0,99,MPI_COMM_WORLD,status,ierr)
23       write(*,*) message1
24   else if ( myid .eq. 2 ) then
25       call MPI_RECV(message2,20,MPI_CHAR,0,99,MPI_COMM_WORLD,status,ierr)
26       write(*,*) message2
27   else if ( myid .eq. 3 ) then
28       call MPI_RECV(message3,20,MPI_CHAR,0,99,MPI_COMM_WORLD,status,ierr)
29       write(*,*) message3
30   end if
31 
32   call MPI_FINALIZE(rc)
33 
34 end

 

編譯:mpif77和mpif90分別編譯並聯接用FORTRAN77和Fortran90編寫的MPI程序,在這里,用mpif90進行編譯。(這里mpifort也可以編譯f90程序)

1 mpif90 Hello_World.f90 -o Hello_World.out      !   或者      mpifort Hello_World.f90 -o Hello_World.out

執行:用mpirun來執行並行計算程序,mpirun –np N program 或者 mpirun –n N program,N 是指定多少個進程同時運行,即多少核並行計算。

1 mpirun -n 4 Hello_World.out          !   或者      mpirun -np 4 Hello_World.out

 

程序執行結果:

1 process 0 of 4 is alive
2 process 1 of 4 is alive
3 process 2 of 4 is alive
4 Hello, process 2 
5 Hello, process 1 
6 process 3 of 4 is alive
7 Hello, process 3

可以看到,12行的write命令被執行了4次,但是這4次並不連續,因為21行之后的if判斷搶了先。不同的進程,執行速度不太一樣,有快有慢,就造成了如上的結果。要想讓12行的write命令,4個進程都執行完,才執行之后的命令,要用到MPI_BARRIER同步命令。下一篇博文會介紹。

 


免責聲明!

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



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