zoukankan      html  css  js  c++  java
  • 【转】MPI入门

    author: Menglong TAN; email: tanmenglong_at_gmail; twitter/weibo: @crackcell; source:http://blog.crackcell.com/posts/2013/07/15/mpi_quick_start.html.

    1 前言

      不知道为啥,MPI的入门教程似乎很少,也不太明了。今天看了一些教程,整理一下入门需要知道的知识点。

    2 开发环境设置

      环境:debian sid 安装开发环境:

    $ sudo apt-get install openmpi-bin openmpi-doc libopenmpi-dev gcc g++

    3 Learn by example

     

    3.1 例子1:Hello world

    #include <iostream>
    #include <mpi/mpi.h>
    
    using namespace std;
    
    int main(int argv, char* argc[]){
        MPI_Init(&argv, &argc);
        cout << "hello world" << endl;
        MPI_Finalize();
        return 0;
    }
    

    编译:

    $ mpicxx -o hello.exe hello.cpp

    运行:

    $ mpirun -np 10 ./hello.exe

    • -np 10 参数制定了运行了程序的10个拷贝

    3.2 代码结构

       我们来看代码,MPI程序的结构一般是:

    1. 头文件、全局定义
    2. 初始化MPI环境:MPI_Init()
    3. 分布式代码
    4. 终止MPI环境:MPI_Finalize()
    5. 结束

    3.3 一些基本的API

     

    3.3.1 初始化环境:MPI_Init

    #include <mpi.h>
    int MPI_Init(int *argc, char ***argv)
    

    3.3.2 是否初始化:MPI_Initialized

    #include <mpi.h>
    int MPI_Initialized(int *flag)
    

    3.3.3 终止环境:MPI_Finalize

    #include <mpi.h>
    int MPI_Finalize()
    

    3.3.4 获取进程数:MPI_Comm_size

    获取一个communicator中的进程数

    #include <mpi.h>
    int MPI_Comm_size(MPI_Comm comm, int *size)
    

    如果communicator是MPI_COMM_WORLD,那就是当前程序能用的所有进程数

    3.3.5 获取当前进程id:MPI_Comm_rank

    #include <mpi.h>
    int MPI_Comm_rank(MPI_Comm comm, int *rank)
    

    3.3.6 获取程序运行的主机名:MPI_Get_processor_name

    #include <mpi.h>
    int MPI_Get_processor_name(char *name, int *resultlen)
    

    3.3.7 终止一个communicator的所有进程:MPI_Abort

    #include <mpi.h>
    int MPI_Abort(MPI_Comm comm, int errorcode)
    

    3.4 例2:稍微复杂一点

    #include <stdio.h>
    #include <mpi/mpi.h>
    
    int main(int argc, char *argv[]) {
        char hostname[MPI_MAX_PROCESSOR_NAME];
        int task_count;
        int rank;
        int len;
        int ret;
    
        ret = MPI_Init(&argc, &argv);
        if (MPI_SUCCESS != ret) {
            printf("start mpi fail
    ");
            MPI_Abort(MPI_COMM_WORLD, ret);
        }
    
        MPI_Comm_size(MPI_COMM_WORLD, &task_count);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
        MPI_Get_processor_name(hostname, &len);
    
        printf("task_count = %d, my rank = %d on %s
    ", task_count, rank, hostname);
    
        MPI_Finalize();
    
        return 0;
    }
    

    运行一下:

    $ mpirun -np 3 ./hello3.exe task_count = 3, my rank = 0 on crackcell-vm0 task_count = 3, my rank = 1 on crackcell-vm0 task_count = 3, my rank = 2 on crackcell-vm0

    3.5 基本通信API

    • MPI提供了消息的缓存机制
    • 消息可以以阻塞或非阻塞的方式发送
    • 顺序性:MPI保证接收者收到消息的顺序和发送者的发送顺序一致
    • 公平性:MPI不保证调度公平性,程序员自己去防止进程饥饿

    3.5.1 消息数据类型

        为了可移植性,MPI定义了自己的消息数据类型,具体参考1

    3.5.2 点对点通信API

    • 阻塞发送:MPI_Send
      int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest,
                   int tag, MPI_Comm comm)
      
    • 非阻塞发送:MPI_Isend
      int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest,
                   int tag, MPI_Comm comm)
      
    • 阻塞接收:MPI_Recv
      int MPI_Recv(void *buf, int count, MPI_Datatype datatype,
                   int source, int tag, MPI_Comm comm, MPI_Status *status)
      
    • 非阻塞接收:MPI_Irecv
      int MPI_Irecv(void *buf, int count, MPI_Datatype datatype,
                    int source, int tag, MPI_Comm comm, MPI_Request *request)
      

    3.6 例3:阻塞的消息传递

    #include <stdio.h>
    #include <mpi/mpi.h>
    
    int main(int argc, char *argv[]) {
        int task_count;
        int rank;
        int dest;
        int src;
        int count;
        int tag = 1;
    
        char in_msg;
        char out_msg = 'x';
    
        MPI_Status status;
    
        MPI_Init(&argc, &argv);
        MPI_Comm_size(MPI_COMM_WORLD, &task_count);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    
        if (0 == rank) {
            dest = 1;
            src = 1;
            // 向1发送一个字符,然后等待返回
            MPI_Send(&out_msg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
            MPI_Recv(&in_msg, 1, MPI_CHAR, src, tag, MPI_COMM_WORLD, &status);
        } else if (1 == rank) {
            dest = 0;
            src = 0;
            // 向0发送一个字符,然后等待返回
            MPI_Recv(&in_msg, 1, MPI_CHAR, src, tag, MPI_COMM_WORLD, &status);
            MPI_Send(&out_msg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
        }
    
        MPI_Get_count(&status, MPI_CHAR, &count);
        printf("task %d: recv %d char(s) from task %d with tag %d
    ",
               rank, count, status.MPI_SOURCE, status.MPI_TAG);
    
        MPI_Finalize();
    
        return 0;
    }
    

    3.7 协同通信API

    • 协同通信必须涉及同一个communicator中的所有进程
    • 协同通信操作的类型
      1. 同步操作:进程等待同组的其它成员到达某一同步点
      2. 数据移动操作:broadcast、scatter/gather操作
      3. 协同计算:某个成员收集其它成员的数据,然后执行某个操作

    3.7.1 阻塞直到同组其它任务完成:MPI_Barrier

    #include <mpi.h>
    int MPI_Barrier(MPI_Comm comm)
    

    3.7.2 Broadcast消息:MPI_Bcast

    #include <mpi.h>
    int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype,
                  int root, MPI_Comm comm)
    

    3.7.3 散播消息:MPI_Scatter

    #include <mpi.h>
    int MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype,
                    void *recvbuf, int recvcount, MPI_Datatype recvtype, int root,
                    MPI_Comm comm)
    

    3.7.4 收集消息:MPI_Gather

    #include <mpi.h>
    int MPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
                   void *recvbuf, int recvcount, MPI_Datatype recvtype, int root,
                   MPI_Comm comm)
    

    更多API参考2

    3.8 组和通信器

    • 一堆有序的进程组成一个group,每个进程有一个唯一的整数标识
    • 一个communicator组织起了一堆需要相互之间通信的进程。MPI_COMM_WORLD包含了所有进程

    group用来组织一组进程,communicator用来关联他们之前的通信关系。

    Date: Mon Jul 15 11:55:20 2013

    Author: Tan Menglong

    Org version 7.9.3f with Emacs version 24

    Validate XHTML 1.0

  • 相关阅读:
    118/119. Pascal's Triangle/II
    160. Intersection of Two Linked Lists
    168. Excel Sheet Column Title
    167. Two Sum II
    172. Factorial Trailing Zeroes
    169. Majority Element
    189. Rotate Array
    202. Happy Number
    204. Count Primes
    MVC之Model元数据
  • 原文地址:https://www.cnblogs.com/gkwang/p/4337679.html
Copyright © 2011-2022 走看看