zoukankan      html  css  js  c++  java
  • 并行编程——MPI

    MPI是Message Passing Interface的简称,通过这个协议可以在各个进程——尤其是分布式内存进程——间能够进行通信,交流消息共同完成一个任务。

    进行mpi编程的基本流程如下

    首先要载入头文件

    Fortran 77:
    include 'mpif.h'
    Fortran 90:
    use mpi
    C/C++:
    #include "mpi.h"

    第二步是初始化MPI环境

    Fortran 77/90:
    Call MPI_INIT(ierror)
    其中integer ierror
    C:
    int MPI_Init(int *argc, char ***argv);
    C++:
    int MPI::Init(int *argc, char ***argv);

    第三步是获知参与并行的核的总数

    Fortran 77/90:
    Call MPI_COMM_SIZE(comm, size, ierror)
    其中integer comm, size, ierror
    C:
    int MPI_Comm_size (MPI_Comm comm, int *size);
    C++:
    int MPI::COMM_WORLD.Get_size( );

    第四步是得知自己所在的进程的序列号

    Fortran 77/90:
    Call MPI_COMM_RANK(comm, rank, ierror)
    其中 integer comm, rank, ierror
    C:
    int MPI_Comm_rank(MPI_Comm comm, int *rank);
    C++:
    int MPI::COMM_WORLD.Get_rank( );

    进行相关计算后

    第五步是结束MPI环境

    Fortran 77/90:
    Call MPI_FINALIZE(ierror)
    其中integer ierror
    C:
    int MPI_Finalize();
    C++:
    MPI::Finalize();

    还有两个不常用的方法

    计算逝去的时间

    Fortran 77/90:
    double precision MPI_WTIME()
    C:
    double MPI_Wtime();
    C++:
    double MPI::Wtime();

    和中止MPI环境

    Fortran:
    Call MPI_ABORT(comm, errorcode, ierror)
    其中integer comm, errorcode, ierror
    C:
    int MPI_Abort(MPI_Comm comm int errorcode );
    C++:
    MPI::COMM_WORLD.Abort( int errorcode );

    MPI的数据类型则包括以下几种

    C data type

    MPI data type

    char MPI_CHAR
    short int MPI_SHORT
    int MPI_INT
    long int MPI_LONG
    float MPI_FLOAT
    double MPI_DOUBLE
    long double MPI_LONG_DOUBLE

    Fortran data type

    MPI data type

    INTEGER MPI_INTEGER
    REAL MPI_REAL
    REAL*8 MPI_REAL8
    DOUBLE PRECISION MPI_DOUBLE_PRECISION
    COMPLEX MPI_COMPLEX
    LOGICAL MPI_LOGICAL
    CHARACTER MPI_CHARACTER

    通常所用的消息交换方法有以下几种

    MPI_SEND&MPI_RECV

    Fortran 77/90:
    Call MPI_SEND(BUF, COUNT, DATATYPE, DEST, TAG, COMM, IERROR)
    其中<type> BUF(*);INTEGER COUNT, DATATYPE, DEST, TAG, COMM, IERROR
    C:
    int MPI_Send(void* buf, int count, MPI_Datatype datatype, int dest,int tag, MPI_Comm comm)
    C++:
    MPI::Comm::Send(const void* buf, int count, const MPI::Datatype& datatype, int dest, int tag)
    Fortran 77/90:
    Call MPI_RECV(BUF, COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS, IERROR)
    其中<type> BUF(*);INTEGER COUNT, DATATYPE, SOURCE, TAG, COMM, STATUS(MPI_STATUS_SIZE),IERROR

    C:
    int MPI_Recv(void* buf, int count, MPI_Datatype datatype, int source,int tag, MPI_Comm comm, MPI_Status *status)
    C++:
    MPI::Comm::Recv(void* buf, int count, const MPI::Datatype& datatype,int source, int tag, MPI::Status& status)

    这一组方法是阻塞式的,也就是会导致程序等待直到收到对应消息,所以有可能会发生程序死锁例如

    if (myid==0)
    {
    MPI_RECV(a,100,MPI_INTEGER,0,10,comm, status)
    MPI_SEND(b,100,MPI_INTEGER,1,11,comm,status)
    }
    else
    {
    MPI_RECV(a,100,MPI_INTEGER,0,11,comm,status)
    MPI_SEND(b,100,MPI_INTEGER,0,10,comm,status)
    }

    还有Scatter&Gather

    Fortran 77/90:
    MPI_SCATTER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
    其中<type> SENDBUF(*), RECVBUF(*); INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR
    C:
    int MPI_Scatter(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,MPI_Comm comm)
    C++:
    MPI::Comm::Scatter(const void* sendbuf, int sendcount, const MPI::Datatype& sendtype, void* recvbuf, int recvcount,
    const MPI::Datatype& recvtype, int root)
    Fortran 77/90:
    Call MPI_GATHER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)
    其中<type> SENDBUF(*), RECVBUF(*);INTEGER SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR
    C:
    int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
    C++:
    MPI::Comm::Gather(const void* sendbuf, int sendcount, const MPI::Datatype& sendtype, void* recvbuf, int recvcount,
    const MPI::Datatype& recvtype, int root)

    以下是例子

    Fortran的

    Program mpitest
    use mpi
    Implicit None
    Integer,Parameter :: row=5000
    Integer,Parameter :: col=5000
    Real(Kind=8) :: mat_a(row,col),mat_b(row,col),mat_c(row,col)
    Integer :: myid,numprocs,rc,ierr,iprovided
    Integer(kind=sp) :: startcol,endcol,colsn
    Integer(kind=sp) :: i,j,k
    Call MPI_INIT(ierr)
    Call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)
    Call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)
    mat_a=0.0d0
    mat_b=0.0d0
    mat_c=0.0d0
    colsn=col/numprocs
    startcol=colsn*myid+1
    endcol=colsn*(myid+1)
    If (myid==0) Then
    mat_a=100.0d0
    mat_b=80.0d0
    End If
    Call MPI_SCATTER(mat_a,colsn*row,MPI_DOUBLE_PRECISION,mat_a,colsn*row,MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD,ierr)
    Call MPI_SCATTER(mat_b,colsn*row,MPI_DOUBLE_PRECISION,mat_b,colsn*row,MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD,ierr)
    mat_c(:,1:colsn)=mat_a(:,1:colsn)-mat_b(:,1:colsn)
    Call MPI_GATHER(mat_c(:,1:colsn),colsn*row,MPI_DOUBLE_PRECISION,mat_c,colsn*row,MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD,ierr)

    Call MPI_FINALIZE(rc)
    Stop
    End Program mpitest

    C++的

    # include <cstdlib>
    # include <iostream>
    # include <ctime>
    # include "mpi.h"

    using namespace std;

    int main ( int argc, char *argv[] );

    //****************************************************************************80

    int main ( int argc, char *argv[] )

    {
    const int row=5000;
    const int col=5000;
    int myid;
    int nprocs;
    int colsn;
    int i,j,k;
    MPI::Init(argc,argv);
    myid=MPI::COMM_WORLD.Get_rank();
    nprocs=MPI::COMM_WORLD.Get_size();
    colsn=row/nprocs;
    double (*mat_a)[col];
    double (*mat_b)[col];
    double (*mat_c)[col];
    double (*tmp_a)[col];
    double (*tmp_b)[col];
    double (*tmp_c)[col];
    tmp_a=new double[colsn][col];
    tmp_b=new double[colsn][col];
    tmp_c=new double[colsn][col];
    if (myid==0)
    {
    mat_a=new double[row][col];
    mat_b=new double[row][col];
    mat_c=new double[row][col];
    for ( i = 0; i < row; i++ )
    {
    for ( j = 0; j < col; j++ )
    {
    mat_a[i][j]=100.0;
    }
    }
    for ( i = 0; i < row; i++ )
    {
    for ( j = 0; j < col; j++ )
    {
    mat_b[i][j]=80.0;
    }
    }
    for ( i = 0; i < row; i++ )
    {
    for ( j = 0; j < col; j++ )
    {
    mat_c[i][j]=0.0;
    }
    }
    }
    else
    {
    mat_a=new double[1][col];
    mat_b=new double[1][col];
    mat_c=new double[1][col];
    for ( i = 0; i < colsn; i++ )
    {
    for ( j = 0; j < col; j++ )
    {
    tmp_a[i][j]=0.0;
    }
    }
    for ( i = 0; i < colsn; i++ )
    {
    for ( j = 0; j < col; j++ )
    {
    tmp_b[i][j]=0.0;
    }
    }
    for ( i = 0; i < colsn; i++ )
    {
    for ( j = 0; j < col; j++ )
    {
    tmp_c[i][j]=0.0;
    }
    }


    }

    MPI::COMM_WORLD.Scatter(mat_a, colsn*col, MPI::DOUBLE, tmp_a, colsn*col,MPI::DOUBLE,0);
    MPI::COMM_WORLD.Scatter(mat_b, colsn*col, MPI::DOUBLE, tmp_b, colsn*col,MPI::DOUBLE,0);

    for (i=0;i<colsn;i++)
    {
    for (j=0;j<col;j++)
    {
    tmp_c[i][j]=tmp_a[i][j]+tmp_b[i][j];
    }
    }

    MPI::COMM_WORLD.Gather(tmp_c, colsn*col, MPI::DOUBLE, mat_c, colsn*col,MPI::DOUBLE,0);
    MPI::Finalize();
    return 0;
    }

    教程

    http://www.lam-mpi.org/tutorials/bindings/

    http://www.amazon.com/Introduction-Parallel-Computing-Ananth-Grama/dp/0201648652

    http://www.megashare.com/3146342











  • 相关阅读:
    defer与async的区别
    Promise 的含义
    SCSS 与 Sass 异同
    CSS总结2
    CSS总结1
    jQuery-插件,优化
    jQuery-表格以及表单
    jQuery-事件以及动画
    jQuery-ajax
    jQuery-DOM操作
  • 原文地址:https://www.cnblogs.com/sickboy/p/2410769.html
Copyright © 2011-2022 走看看