【转】MPI入门

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

Table of Contents

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\n");
        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\n", 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\n",
           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用来关联他们之前的通信关系。

Footnotes:

1 MPI教程, https://computing.llnl.gov/tutorials/mpi/#Point_to_Point_Routines

2 协同通信, https://computing.llnl.gov/tutorials/mpi/#Collective_Communication_Routines

Date: Mon Jul 15 11:55:20 2013

Author: Tan Menglong

Org version 7.9.3f with Emacs version 24

Validate XHTML 1.0

Related Posts

  • 03 May 2011 » Rejected Bio from The Setup
  • 29 Mar 2011 » Ten Lessons from GitHub‘s First Year
  • 11 Dec 2010 » Designer, Architect, Developer

-->

© Menglong TAN

时间: 2024-08-10 11:37:25

【转】MPI入门的相关文章

MPI 初认识 (入门教程)

并行计算的实验课,布置了MPI做热传导的题,老师讲的少之又少,自己琢磨了半天才对MPI懂了一点点 1.首先MPI是基于消息传递的并行计算模式,与之前的pthread,openMP等共享内存的完全两码事,这是首先要明白的. 2.MPI程序中,既有串行执行的程序,也有并行执行的程序.其中,并行的部分全部放在MPI_Init(&argc,&argv)和MPI_Finalize()内部. 3.也是最让我开始纳闷的地方:MPI 的程序怎么在代码中控制开多少个进程啊?费了我半天劲,原来MPI有自己

工控安全入门分析

转载(http://bobao.360.cn/learning/detail/659.html) 0x00写在前面 工业4.0,物联网趋势化,工控安全实战化.安全从业保持敏感,本篇以科普角度对工控安全做入门分析,大牛绕过,不喜轻喷. 0x01专业术语 SCADA:数据采集与监视控制系统 ICS:工业控制系统 DCS:分布式控制系统/集散控制系统 PCS:过程控制系统 ESD:应急停车系统 PLC:可编程序控制器(Programmable Logic Controller) RTU:远程终端控制系

Linux上安装使用boost入门指导

Data Mining Linux上安装使用boost入门指导 获得boost boost分布 只需要头文件的库 使用boost建立一个简单的程序 准备使用boost二进制文件库 把你的程序链接到boost库 1.获得boost 下载boost_1_46_1.tar.bz2 解压 2.boost分布 boost_1_46_1.........................boost根目录 boost/.....................................所有boost头文件

xgboost入门与实战(原理篇)

http://blog.csdn.net/sb19931201/article/details/52557382 xgboost入门与实战(原理篇) 前言: xgboost是大规模并行boosted tree的工具,它是目前最快最好的开源boosted tree工具包,比常见的工具包快10倍以上.在数据科学方面,有大量kaggle选手选用它进行数据挖掘比赛,其中包括两个以上kaggle比赛的夺冠方案.在工业界规模方面,xgboost的分布式版本有广泛的可移植性,支持在YARN, MPI, Sun

工控安全简单入门

0x00写在前面 工业4.0,物联网趋势化,工控安全实战化.安全从业保持敏感,本篇以科普角度对工控安全做入门分析,大牛绕过,不喜轻喷. 0x01专业术语 SCADA:数据采集与监视控制系统 ICS:工业控制系统 DCS:分布式控制系统/集散控制系统 PCS:过程控制系统 ESD:应急停车系统 PLC:可编程序控制器(Programmable Logic Controller) RTU:远程终端控制系统 IED:智能监测单元 HMI:人机界面(Human Machine Interface) MI

「03」机器学习、深度学习该怎样入门?

我本科是个和计算机.数学毫不相关的人文类专业,后来用了大三.大四两年时间,从中学级别的数学捡起,一路自学.实习.读研到现在.我太熟悉入门时候的坑了,直接从一大堆概念.公式.书单入手,谁看谁懵. 所谓入门,绝不是粘课程链接.讲概念定义.有些答案确实解释的非常通俗,但这不叫入门. 古语说入门,就一句话 师傅领进门,修行在个人 所以我不会随便复制粘贴一些高分书目,或者讲讲什么是深度学习.我希望能从一个不一样的角度来回答该如何入门深度学习,希望可以授人与渔,教教大家入门的方法论. 对于自学成分居多.想转

R语言快速上手入门

R语言快速上手入门 课程学习网址:http://www.xuetuwuyou.com/course/196 课程出自学途无忧网:http://www.xuetuwuyou.com 课程简介 本教程深入浅出地讲解如何使用R语言玩转数据.课程中涵盖R语言编程的方方面面,内容涉及R对象的类型.R的记号体系和环境系统.自定义函数.if else语句.for循环.S3类R的包系统以及调试工具等.本课程还通过示例演示如何进行向量化编程,从而对代码进行提速并尽可能地发挥R的潜能.本课程适合立志成为数据科学家的

笔记:Spring Cloud Zuul 快速入门

Spring Cloud Zuul 实现了路由规则与实例的维护问题,通过 Spring Cloud Eureka 进行整合,将自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取了所有其他微服务的实例信息,这样的设计非常巧妙的将服务治理体系中维护的实例信息利用起来,使得维护服务实例的工作交给了服务治理框架自动完成,而对路由规则的维护,默认会将通过以服务名作为 ContextPath 的方式来创建路由映射,也可以做一些特别的配置,对于签名校验.登录校验等在微服务架构中的冗余问题

linux入门基础知识及简单命令介绍

linux入门基础知识介绍 1.计算机硬件组成介绍 计算机主要由cpu(运算器.控制器),内存,I/O,外部存储等构成. cpu主要是用来对二进制数据进行运算操作,它从内存中取出数据,然后进行相应的运算操作.不能从硬盘中直接取数据. 内存从外部存储中取出数据供cpu运存.内存的最小单位是字节(byte) 备注:由于32的cpu逻辑寻址能力最大为32内存单元.因此32位cpu可以访问的最大内存空间为:4GB,算法如下: 2^32=2^10*2^10*2^10*2^2 =1024*1024*1024