MPI分布式计算

1、并行计算简介

都得从性能提升说起

  • 不断提升的计算能力成为许多飞速发展领域的核心力量
    • 人类基因解码、更精准的医疗成像等等
    • 气候模拟、蛋白质折叠、药物发现、数据分析等等
  • 需要更加强大的计算能力
  • 并行计算是云计算的重要支撑技术之一

为什么要构建并行系统

  • 单处理器的性能提升已经接近极限。
  • 通过继续增快集成电路的速度来提高处理器性能的方法不再可行。但集成电路晶体管的密度还在增加,如何利用不断增加的晶体管密度来提高计算能力?答案是并行
  • 与其构建更快更复杂的但处理器,不如在单个芯片放置多个相对简单的处理器。这样的集成电路为多核处理器。传统的成为单核处理器。

为什么要编写并行程序

  • 单核系统编写的程序无法利用多核处理器,所以需要将串行程序改为并行程序。
  • 自动将串行改为并行鲜有突破,需要手动编写
  • 最好的并行化实现是通过一步步的回溯,然后发现一个全新的算法来获得

怎么编写并行程序

  • 任务并行:将待解决问题所需要执行的各个任务分配到各个核上执行
  • 数据并行:将待解决问题的数据分配给各个核,每个核在分配到的数据集上执行大致相似操作。

并行计算的难点

  • 核之前独立,和串行相似。核之间需要协调工作,复杂
  • 协调包括:通信,负载平衡,同步
  • 核的执行顺序不确定,存在共享内存临界区的竞争访问和线程安全性问题
  • 并行程序的设计与程序所依赖的并行硬件平台有着紧密关系,特别是需要设计高性能并行程序时,一定要针对硬件平台进行优化。
  • 尚且没有统一标准,常用的拓展库有MPI、Pthread、OpenMP、OpenACC

并行硬件

通过系统可处理的指令数量和数据流数量区分各类并行硬件。

  • 单指令单数据流(SISD)系统

    如传统的冯.诺依曼系统,拥有单个的指令流和单个的数据流

  • 单指令多数据流(SIMD)系统

    系统在任何时间执行一条指令,但是该指令可以对多个数据项进行操作。这种并行系统通常使用数据并行程序,即将数据划分给各个处理器,各个数据由相同的指令序列来处理。向量处理器和GPU一般划分为SIMD系统。

  • 多指令多数据流(MIMD)系统

    系统同时执行多个指令流,每个指令流有自己的数据流。大多数大型MIMD系统其实是混合系统,是由多个相对小的共享内存系统通过网络连接来实现的。系统内的共享内存系统一般称为节点。有些MIMD系统是异构系统,处理器拥有不同的性能。如果一个系统中所有的处理器都是相同结构的,则是同构的。

并行程序的性能

  • 加速比

    • 用**T表示串行程序执行时间,T表示并行程序的执行时间,并行程序的加速比S=T / T**,即使用并行程序后执行速度提升了多少倍
    • 阿姆达尔定律:如果原有串行程序中无法并行化部分在整个程序中所占的比例是r,那么无论使用线程/进程,得到的加速比无法超越1/r。
  • 效率

    *E=T/(pT)**,P是核数,或者进程/线程数,理想值是1

2、MPI概述

  • MPI提供了了解集群之间通信机制的一种重要模型
  • MPI是消息传递接口的英文简称。描述的是一种消息传递编程模型
  • MPI本身不是一个具体实现,是一种标准描述

3、MPI的架构和特点

  • MPI的核心工作就是实现大量服务器资源的整合输出

  • 主要思想是通过消息传递来对位于多个计算机上通过网络分布式内存系统进行编程

  • 提供最大的灵活性和自由度,但是编程复杂

  • MPI的主要特点有:

    • 程序编写灵活,功能强大

      MPI提供了功能强大的消息通信函数,如阻塞通信、非阻塞通信、组通信、规约、自定义函数类型等。为程序设计人员灵活地实现算法的并行化工作提供了手段。

    • 支持多种语言

    • 对计算的支持强大,对文件的支持较弱。

    • MPI需要自己实现求解问题的并行化

    • 没有提供计算失效的处理机制,节点失效,需要重启计算

    • 网络是MPI的瓶颈

4、MPI分布式程序设计

C+MPI程序示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# include "mpi.h"
# include<stdio.h>
# include<math.h>
void main(argc,argv)
int argc;
char *argv[];
{
//myid某一个并行执行的标识
//numprocs参与计算的进程个数
//processor_name实际得到的机器名字
int myid,numprocs;
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];

MPI_Init(&argc,&argv);
//MPI_Comm_rank得到当前正在运行的进程的标识号,放在myid中。
MPI_Comn_rank(MPI_COMN_WORLD,&myid);
//MPI_Comm_size得到所有参加运算的进程的个数,放在numprocs中。
MPI_Comn_size(MPI_COMN_WORLD,&numprocs);
//MPI_Get_processor_name得到本进程运行的机器的名称 ,结果放在processor_name中,它是一个字符串而该字符串的长度放在namelen中。
MPI_Get_processor_name(processor_name,&namelen);

fprintf(stderr,"Hello World!Process %d of %d on %s\n",myid,numprocs,processor_name);

MPI_Finalize();
}

MPI参数

  • IN 输入:调用部分传递给MPI的参数,不允许修改
  • OUT 输出:MPI返回给调用部分的结果参数
  • INOUT 输入输出:调用部分首先将该参数传递给MPI,引用修改后将结果返回给外部调用。该参数的初始值和返回值都有意义。

MPI接口调用

说明格式:

  • 独立于具体语言的说明
  • C形式的原型声明
  • FORTRAN形式的原型声明

MPI初始化

1
2
3
4
MPI_INIT()
int MPI_Init(*argc,**argv)
MPI_INIT(IERROR)
INTEGER IERROR

MPI_INIT是MPI程序的第一个调用,他完成程序的初始化工作,所有MPI程序的第一条可执行语句

MPI结束

1
2
3
4
MPI_FINALIZE()
int MPI_Finalize(void)
MPI_FINALIZE(ERROR)
INTEGER IERROR

MPI_FINALIZE是MPI程序的最后一个调用,结束MPI的运行,是MPI的最后一条可执行语句。

当前进程标识

1
2
3
4
5
6
MPI_COMM_RANK(comm,rank)
IN comm 该进程所在的通信域(句柄)、
OUT rank 该进程在comm的标识号
int MPI_Comm_rank(MPI_Comm comm,int *rank)
MPI_COMM_RANK(COMM,RANK,IERROR)
INTEGER COMM,RANK,IERROR

这一调用返回调用进程在给定域中的进程标识号,不同的进程就可以将自身和其他进程区分开来,实现各自进程的并行和协作

通信域包含额进程数

1
2
3
4
5
6
MPI_COMN_SIZE(comm,size)
IN comn
OUT size 通信域包含的进程数
int MPI_Comm_size(MPI_Comm comm,int *size)
MPI_COMM_SIZE(COMM,SIZE,IERROR)
INTEGER COMM,SIZE,IERROR

这一调用返回给定的通信域中所包含的进程的个数,不同的进程通过这一调用得知在给定的通信域中一共有多少个进程在并行执行。

消息发送

1
2
3
4
5
6
7
8
9
10
11
12
13
MPI_SEND(buf,count,datatype,dest,comm)
In buf //发送缓冲区的起始地址
IN count//将发送的数据的个数
IN datatype //数据类型(句柄)
IN dest //目标的进程标识号
IN tag //消息标志
IN comm //通信域(句柄)

int MPI_Send(void *buf,int count,MPI_Datatype,int dest,int tag,MPI_Comm comm)

MPI_SEND(BUF,COUNT,DATATYPE,DEST,TAG,COMM,IERROR)
<type> BUF(*)
INTEGER COUNT,DATATYPE,DEST,TAG,COMM,IERROR

消息接收

1
MPI_RECV(buf,count,datatype,sourvr,tag,comm,status)

返回状态status

status是MPI定义的一个数据类型,使用之前需要分配空间

在C实现中,状态变量至少由至少三个域组成,分别是:MPI_SOURCE,MPI_TAG,MPI_ERROR。

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

请我喝杯咖啡吧~

支付宝
微信