热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一切靠自己的MPI框架

本文主要介绍关于网络,分布式存储的知识点,对【一切靠自己的MPI框架】和【如何建立自己的工作框架】有兴趣的朋友可以看下由【新爷话数据】投稿的技术文章,希望该技术和经验能帮到你解决你所遇的【】相关技术问

本文主要介绍关于网络,分布式存储的知识点,对【一切靠自己的MPI框架】和【如何建立自己的工作框架】有兴趣的朋友可以看下由【新爷话数据】投稿的技术文章,希望该技术和经验能帮到你解决你所遇的【】相关技术问题。

如何建立自己的工作框架

MPI是高性能计算常用的实现方式,它的全名叫做Message Passing Interface。顾名思义,它是一个实现了消息传递接口的库。MPI作为编程库很丰满,作为计算框架很骨感。它的好处在于一切自己动手,不利也在于一切全靠自己。 本文的目的不是探讨如何使用MPI,MPI标准是这方面最有参考价值的文档。本文笔者仅仅讨论它在并行编程上的特点,帮助用户决定何时或在何种场景下使用MPI。

1.什么是MPI?

MPI是一个跨语言的通讯协议,支持高效方便的点对点、广播和组播。它提供了应用程序接口,包括协议和和语义说明,他们指明其如何在各种实现中发挥其特性。从概念上讲,MPI应该属于OSI参考模型的第五层或者更高,他的实现可能通过传输层的sockets和Transmission Control Protocol (TCP)覆盖大部分的层。大部分的MPI实现由一些指定的编程接口(API)组成,可由C, C++,Fortran,或者有此类库的语言比如C#, Java或者Python直接调用。MPI优于老式信息传递库是因为他的可移植性和速度。 MPI标准也不断演化。主要的MPI-1模型不包括共享内存概念,MPI-2只有有限的分布共享内存概念。但是MPI程序经常在共享内存的机器上运行。MPI有很多参考实现,例如mpich或者openmpi。

?

2.同步是重点也是难点

顾名思义,MPI是基于消息传递的并行编程,它提供了语义丰富的消息通信机制,包括点对点、组播和多播模式。用户程序利用这些接口进行进程之间的数据移动、聚集、规约和同步。MPI标准规定了这些接口的调用规范和语义,不同的实现(例如mpich或者openmpi)可能采用不同的优化策略。

2.1 点对点通信

点对点通信指的是两个进程之间的通信,可用于控制同步或者数据传输,例如MPI_Send和MPI_Recv。

存储技术

如上图所示,两个进程计算结束后,相互交换消息后,进行下一阶段的计算。这是MPI典型的工作模式。 点对点通信有同步(阻塞blocking)版本和异步(非阻塞non-blocking)版本。阻塞对发送端和接收端的意义不一样。MPI_Send返回意味着应用程序发送数据结束(至少数据已存储到系统缓冲区),应用程序缓冲可以重用或者覆盖,但不一定意味着接收者收到了数据。MPI_Recv返回则意味着数据已经接收到应用程序的缓冲区,可以使用了。非阻塞接口的意义在于操作马上返回,继续后续阶段的计算。当程序要求操作必须确认完成时,调用相应的测试接口(例如MPI_Wait)阻塞等待操作完成。异步编程相对麻烦,但是它使得计算和通信可以一定程度重叠,降低了数据同步带来的运行时间开销。

2.2 聚集通信(Collective Communication)

聚合通信包括了一对多、多对一和多对多的通信方式,常用于一组进程之间的数据交换。MPI提供了如下的聚合通信接口。

虚拟存储

聚合通信接口的语义与进程的拓扑结构有关系。参见后续章节,当MPI程序启动后,每个进程会分配一个唯一的序号(rank)。聚合通信常常需要指定一个协调者(例如rank 0进程),由它负责将数据发送给所有进程(包括它自己)。我们以接口MPI_BCAST为例,它将数据从根进程发送到所有其它进程(包括根进程自己)。所有的进程都调用MPI_BCAST,如下例子所示:

存储空间

它的一个典型实现如下图所示:

虚拟存储器

虽然每个进程都调用了MPI_Bcast,但是根进程负责广播数据,其它进程接收数据。接口MPI_Gather行为恰好相反,每个进程将数据发送给根进程。例如如下的代码实现了一个典型的聚合数据的过程:

移动式存储设备

对应的典型实现是:

动态存储器

从中可以看到MPI聚合通信的编程模式:每个程序独立完成一定的计算工作,到达交汇点,同时调用聚合通信原语(primitive)完成数据交换,然后根据结果进行后续计算。当计算规模较大,聚合通信的性能非常关键,不同的MPI实现框架实现了不同的优化方案。上图描述的只是最直接和简单的实现方式,实际中往往采用更复杂的拓扑结构例如树形结构、环形结构来达到更好的性能。

2.3 同步

某些场景下,多个进程需要协调同步进入某个过程。MPI提供了同步原语例如MPI_Barrier。所有进程调用MPI_Barrier,阻塞程序直到所有进程都开始执行这个接口,然后返回。由此可见它的作用就是让所有进程确保MPI_Barrier之前的工作都已完成,同步进入下一个阶段。

3.MPI程序如何运行? 3.1 编程模型(Programming Model)

从前面的例子,大家可能发现MPI程序的编程模式,那就是迭代式的“计算 + 通信”。如下图所示,程序可以分为计算块和通信块。每个程序可以独立完成计算块,计算完成后进行交互,即通信或者同步。交互完成后进入下一个阶段的计算。直到所有任务完成,程序退出。

存储库

上篇我们讨论了分治法,即并行程序的任务分解和结果合并。MPI程序怎么实现任务分解呢?事实上,MPI框架只是提供了通信机制,即任务之间同步和通信的手段。计算任务怎么分解,数据怎么划分,计算怎么实现,任务怎么合并等等问题都由程序开发者自己决定。MPI框架在程序启动的时候,为每个程序副本分配了唯一的序号(rank)。通常程序可以通过获取rank确定自己是谁,根据rank决定谁该做什么工作。

磁盘存储

由上图可以看出,一个典型的MPI程序由用户程序部分链接MPI库构成,计算任务本身的算法实现、任务分解和合并实现在用户程序部分,与MPI无关,也不受MPI限制。所以说,MPI框架提供给编程者最大的灵活性,实现了最小的封装。

3.2 调度和PMI

虽然MPI标准主要关注通信和进程间交互,但是资源管理和进程调度问题是任何一个分布式计算的框架必须解决的问题。进程管理接口PMI (Process Management Interface)定义了MPI程序与运行时环境的交互接口,尝试解决资源管理问题。PMI有很多具体实现,典型的例子是Hydra进程管理器,它是PMI-1标准的具体实现。任何一个实现了PMI标准的进程管理器负责的功能包括资源管理、启动和清除MPI用户进程、运行环境初始化等等。

存储阵列

如上图所示,Hydra框架提供进程启动工具和PMI代理程序。当用户运行mpiexec命令启动MPI程序,同时指定一个主机列表。Hydra框架通过资源管理器(例如PBS等)分配或者验证节点资源,在每个节点上启动代理(hydra proxy)进程。代理进程互相连接,形成集群,设置执行环境,启动用户的MPI程序。用户MPI程序启动后,通过内置的PMI客户端与启动它的Hydra代理建立反向连接。在这个过程中,MPI进程的拓扑结构建立起来,每个进程拥有独立的rank,开始后续的并行执行。下图展示了Hydra进程管理器的启动过程,其中Hydra代理进程建立了一个树形拓扑。

消息存储

一旦上述拓扑建立,完成了用户进程的启动,框架的工作完成,用户程序的计算开始。直到某个用户进程故障退出,或者用户主动停止程序,进程管理器再度介入,完成错误处理和清理工作。

3.3 容错

所有的分布式系统都需要容错。那么MPI程序如何容错呢?不同的框架实现提供了不同程度的容错支持。主要的方式是快照(checkpoint)和程序重启机制。例如Hydra框架基于Berkerly的BLCR快照和重启库(checkpoing and restart)实现MPI程序的快照功能。例如用户通过下述方式启动程序,指定快照机制和快照数据目录:

存储容量

当程序启动后,用户可以通过给mpiexec程序发送信号sigUSR1启动快照,Hydra也可以周期性的执行快照操作。Hydra框架根据启动时建立的PMI代理进程集群,为每个节点上的MPI用户进程生成快照,保存程序运行状态、文件IO状态或者网络状态,保存在指定的目录下。当程序出错退出,用户可通过执行下述命令从上一个快照重启程序,继续执行:

计算机存储

4.容器时代的MPI

传统的高性能计算大多采用MPI模型编程,通过传统调度器如SGE、SLURM、PBS投递计算任务。随着容器技术的应用和云原生概念的兴起,容器化不但政治正确,确实简化运维和部署。那么怎么容器化MPI应用?通常有两种选择:

依赖调度器的云原生支持。这种方案依赖调度器自己的演进,且对用户选型增加了限制。

将传统的调度器部署在容器中,运行在类似k8s的容器云中。这种方案的实质是调度器的容器化,无论是用户体验还是资源利用率都不是最优的。

本文《一切靠自己的MPI框架》版权归新爷话数据所有,引用一切靠自己的MPI框架需遵循CC 4.0 BY-SA版权协议。


推荐阅读
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • “你永远都不知道明天和‘公司的意外’哪个先来。”疫情期间,这是我们最战战兢兢的心情。但是显然,有些人体会不了。这份行业数据,让笔者“柠檬” ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 标题: ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • position属性absolute与relative的区别和用法详解
    本文详细解读了CSS中的position属性absolute和relative的区别和用法。通过解释绝对定位和相对定位的含义,以及配合TOP、RIGHT、BOTTOM、LEFT进行定位的方式,说明了它们的特性和能够实现的效果。同时指出了在网页居中时使用Absolute可能会出错的原因,即以浏览器左上角为原始点进行定位,不会随着分辨率的变化而变化位置。最后总结了一些使用这两个属性的技巧。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
author-avatar
凌晨
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有