MPICH2 Hydra进程管理框架分析_wgbljl的博客-程序员宅基地

技术标签: 高性能计算  MPICH2  PMI-1  Hydra  

        MPICH2是由Argonne国家实验室维护的开源MPI库,是高性能计算领域使用最为广泛的MPI库之一。本文主要对其中Hydra进程管理框架进行了简要分析,希望可以为相关领域的学者提供帮助。在阅读本文前,读者可以首先参考其官方介绍:http://wiki.mpich.org/mpich/index.php/Hydra_Process_Management_Framework

        Hydra构建了进程管理框架,MPI进程需要经常与该框架进行交互,其交互的语言就是PMI标准,即进程管理接口(Process Management Interface)。因此要全面掌握该框架需要同时了解Hydra和客户端MPI进程两个部分,下面将分别从两个部分展开分析。需要注意的是,文中涉及的内容均以发稿前最新的mpich3.1为准,且使用PMI-1接口。

1. Hydra 进程管理框架

        下图是mpich wiki给出的Hydra结构图:

        从进程拓扑上看,Hydra由一个运行在服务器上的作业加载程序JLE(Job Launching Executable)和多个运行在不同计算节点上的进程管理代理PMP(Process Manager Proxy)组成。之所以称为PMP是因为它基本上具备了PM(Proxy Manager)的所有功能,代理PM并运行在计算节点上负责具体维护本节点上所有进程的状态。换言之,包括MPI进程在内系统进程拓扑是一个倒树状结构,JLE处于树根,负责在各计算节点上创建进程PMP;PMP在本节点上创建一个或多个MPI进程。JLE对应的执行程序就是我们经常使用的作业加载程序mpiexec.hydra;PMP为hydra_pmi_proxy。

        在介绍进程拓扑结构后,我们来看看上图中主要功能模块的作用,按照自底向上的顺序:

      1、I/O Demux Engine

        Demux的字面意思是“解复用器”。顾名思义,Demux 本质上一个消息管理系统,可以监听多个文件描述符的状态,当文件描述符接收到消息后,回调注册的处理函数。

Demux相关的代码位于src\pm\hydra\tools\demux目录下;其主要函数如下所示:

        1)HYDT_dmx_init:根据用户选项指定wait_for_event为HYDT_dmxu_poll_wait_for_event或HYDT_dmxu_select_wait_for_event。

        2) HYDT_dmx_register_fd(int num_fds, int *fd, HYD_event_t events, void *userp, HYD_status(*callback) (int fd, HYD_event_t events, void *userp)):注册描述符处理函数,根据描述符数量“num_fds”,描述符队列指针“fd”,事件类型“events”,回调函数“callback”,将处理函数添加进HYDT_dmxu_cb_list。
        3) HYDT_dmx_deregister_fd:注销函数。
        4) HYDT_dmx_wait_for_event:等待事件并调用事件处理函数,可以为HYDT_dmxu_poll_wait_for_event或HYDT_dmxu_select_wait_for_event。
        5) HYDT_dmx_query_fd_registration:查询指定描述符是否已经被注册。
        6) HYDT_dmx_finalize:结束函数,释放HYDT_dmxu_cb_list结构。
        7) HYDT_dmxi_stdin_valid:检查输入是否有效,使用read函数并设置长度为0判断函数返回值是否为0。
        8) HYDT_dmx_stdin_valid:获得输入有效标志。

      2、Bootstrap

        BSCI-BootStrap Control Interface,即引导控制接口,负责程序的加载和状态的维护,该模块定义在hydra\tools\bootstrap目录下。主要包含两个数据结构:struct HYDT_bsci_info 定义主要状态信息;struct HYDT_bsci_fns 定义主要核心函数,这里主要介绍其中有关启动作业的函数

        HYD_status(*launch_procs) (char **args, struct HYD_proxy * proxy_list, int *control_fd);

        在我们的实验平台中默认使用ssh启动进程,其launsh回调函数指定为HYDT_bscd_common_launch_procs。该函数的主要功能是准备待运行程序的参数,如果发现目标机器为本地节点,则通过fork启动进程;否则通过ssh远程启动进程。两种方式的启动过程均是调用函数HYDU_create_process,差别在于传递该函数的参数不同。例如,在本地创建进程时,参数为:

        ./examples/hellow  

即直接传递MPI程序名称,直接通过fork创建子进程执行程序;

在远程创建进程时,参数为:

         /home/wgb/mpich-3.1/install/bin/hydra_pmi_proxy --control-port server:50687 --rmk user --launcher ssh --demux poll --pgid 0 --retries 10 --usize -2 --proxy-id 1

即通过ssh在远程创建进程管理代理hydra_pmi_proxy,参数为本地地址/端口等信息;待执行MPI程序的信息将在后续通知PMP。

        BootStrap向外提供下列API接口,可以看出所有函数名均以HYDT_bsci开头:

1)HYD_status HYDT_bsci_init(const char *rmk, const char *launcher, const char *launcher_exec, int enablex, int debug);

2)HYD_status HYDT_bsci_launch_procs(char **args, struct HYD_proxy *proxy_list, int *control_fd);
3)HYD_status HYDT_bsci_finalize(void);
4)HYD_status HYDT_bsci_wait_for_completion(int timeout);
5)HYD_status HYDT_bsci_query_node_list(struct HYD_node **node_list);
6)HYD_status HYDT_bsci_query_proxy_id(int *proxy_id);
7)HYD_status HYDT_bsci_query_native_int(int *ret);

8)HYD_status HYDT_bsci_launcher_XXX_init(void);

      3、Process Binding

        用于进程与CPU或Memory绑定的模块,貌似是使用Open MPI的hwloc(Portable Hardware Locality)子模块实现的。

      4、PM和PMP

        PM和PMP完成进程管理的相关功能,PMP执行在计算节点上,完成JLE和MPI进程间的“上传下达”功能。PMP维护了上行通路(upstream)和下行通路(downstream),分别连接了JLE进程和MPI进程。在完成相关初始化后,PMP通过Demux模块等待来自JLE进程和MPI进程的消息。PMP和PM的主要逻辑和数据结构相似。其中enum HYD_pmcd_cmd是两者共用的核心数据结构之一,定义了进程管理需要处理的所有消息类型。

enum HYD_pmcd_cmd {

        INVALID_CMD = 0,        /* for sanity testing */

        /* UI to proxy commands */

        PROC_INFO,  CKPOINT, PMI_RESPONSE,  SIGNAL, STDIN,

        /* Proxy to UI commands */

        PID_LIST,  EXIT_STATUS, PMI_CMD,  STDOUT, STDERR, PROCESS_TERMINATED

    } cmd;

          如注释所示,PROC_INFO至STDIN为JLE向PMP发送的消息类型;PID_LIST至PROCESS_TERMINATED为PMP向JLE发送的消息类型。

         PMP的消息处理函数为HYD_pmcd_pmip_control_cmd_cb(pmip_cb.c):

        PROC_INFO:完成application进程创建过程。首先为应用进程配置环境变量等准备工作,而后调用HYDU_create_process创建进程。

        CKPOINT:检查点功能。

        PMI_RESPONSE:处理来自服务器端的请求或相应,根据消息类型调用HYD_pmcd_pmip_pmi_handle中的回调函数,回调函数列表定义在pmi_v1_handle_fns_foo(pmip_pmi_v1.c)中。

        SIGNAL:向application进程发送进行killpg或kill。

        STDIN:转发来自服务器端的输入数据到MPI进程。

        JLE的消息处理函数为control_cb(pmiserv_cb.c)。

        PID_LIST:接受并保存PMP发送的MPI进程号列表

        EXIT_STATUS:保存MPI进程的退出状态,并清理PMP

        PMI_CMD:调用handle_pmi_cmd处理各类消息,回调函数列表定义在pmi_v1_handle_fns_foo。

        STDOUT、STDERR:处理标准输出流和错误流

        PROCESS_TERMINATED:处理MPI进程退出

      5、User Interface

        UI定义了mpiexec.hydra的入口函数,其所有代码定义在hydra/ui目录下。

2. MPICH PMI接口及其实现

        MPI应用程序通过PMI接口与PMP交互,PMI-1的接口实现均定义在src/pmi/simple目录下。下面简要介绍其中的主要函数:

PMI_Init:初始化PMI相关变量,例如,PMI_fd,PMI_rank等,PMI_fd用于与PMP通信的描述符,PMI_rank即为MPI进程的rank。

PMI_Get_appnum:获得App序号,从0开始。

PMI_Barrier:同步操作,直至等到JLE返回"barrier_out"消息为止。

PMI_KVS_Get_my_name:从JLB获得进程组标识。

PMI_KVS_Put:发布键-值对。

PMI_KVS_Get:获得键相应的值。

3.PMI交互过程实例

        我们一个MPI的发送过程介绍MPI进程通过PMI与PMP和JLB的交互过程。
        实验平台有两个节点一个是服务节点server,一个是计算节点cn0。测试程序会在cn0上派生一个进程P0;在server派生两个进程P1和P2,P0会分别向P1和P2发送一条消息。
        1、MPI进程会向PMP请求进程组标识,格式如下:
              cmd= get_my_kvsname
        2、PMP将返回进程组标识:
              cmd= my_kvsname kvsname= kvs_53934_0// kvs_53934_0是PMIServer设置的进程组的标识,也可以认为是该作业的标识
        3、MPI进程以上述标识为头继续后续操作,之后询问进程映射关系:
              cmd= get kvsname= kvs_53934_0 key= PMI_process_mapping
        4、MPIProxy返回进程映射关系:
              content:cmd= get_result rc= 0msg= success value= (vector,(0,1,1),(1,1,2))
        5、MPI进程会主动向PMP报告进程地址,以P1为例:
               kvsname= kvs_53934_0 key= P1-businesscard value= description#server$port#42070$ifname#192.168.43.10$
        6、PMP负责将本节点所有进程的地址上传到JLE:
              cmd= put P2-businesscard=description#server$port#45975$ifname#192.168.43.10$ P1-businesscard=description#server$port#42070$ifname#192.168.43.10$
        7、这样JLE可以获得所有进程的地址信息,然后再向下广播这些信息,以便各节点进程可以获得其他节点进程的地址:
              cmd= keyval_cache P0-businesscard=description#cn0$port#45884$ifname#192.168.43.20$ P2-businesscard=description#server$port#45975$ifname#192.168.43.10$ P1-businesscard=description#server$port#42070$ifname#192.168.43.10$ 
        8、当MPI进程需要进行通信操作前,会请求本节点的PMP目标进程的地址,以P0->P1为例,P0会发出如下消息:
              cmd= get kvsname= kvs_53934_0key= P1-businesscard
        9、PMP返回结果:

              cmd=get_resultrc=0 msg=success value=description#server$port#42070$ifname#192.168.43.10$

        这样P0获得了P1的机器名(server)和端口号(42070)和IP地址(192.168.43.10),可以启动发送过程。





版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wgbljl/article/details/24038539

智能推荐

leetcode 621. 任务调度器(贪心算法)_Gogo-2020的博客-程序员宅基地

给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。你需要计算完成所有任务所需要的 最短时间 。示例 1:输入:tasks = [“A”,“A”,“A”,“B”,“B”,“B”

Linux之shell、vim和git_loco1223的博客-程序员宅基地

转自:https://www.toutiao.com/i6694009478393627140/1 Linux基础命令与shell脚本通过第一篇的介绍,我们已经知道在Linux下面操作会比windows下效率高很多,下面和大家讲解一下Linux的基础操作,默认大家已经装好了Linux系统。1.1 cd命令命令格式:cd <路径>意义:cd是change directory ...

RDLC报表纵向合并单元格的方法_wenlish的博客-程序员宅基地_rdlc 合并单元格

该博客:https://blog.csdn.net/yixian2007/article/details/51697492?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.ch

3.2 Redis实战应用之限制用户访问频率_一鸭一鸭唷的博客-程序员宅基地_redis限制访问频率

一、场景举例我们日常上网冲浪的时候,常常会遇到这样的情景:多次输错登陆密码,再次尝试登录,页面提示需要输入正确的图形验证码某内容平台限定,每个账号单日可发布的文章数量不得超过规定上限采用短信验证码进行交互的场景,M分钟内请求的验证码次数过多,接下来的N分钟里会被拒绝请求,并提示"用户操作频繁,请稍后再试"当网站的访问量突然很大的时候肯定会对服务器造成影响,甚至无法访问,如果是正常的访问那么很好说明业务量增大可以考虑系统的拓展,但是如果是搜索引擎爬虫频繁访问或是一些恶意访问,那这时候我们就应该限

mac android usb驱动 win10,如何从Mac OS X创建Windows 10安装程序USB驱动器 | MOS86_冬瓜Don的博客-程序员宅基地

Windows 10能够在双引导环境中运行在所有现代的Mac硬件,由于Boot Camp。如果您打算在同一台Mac上与OS X一起运行Windows,您将需要从USB驱动器创建一个可引导的Windows 10安装程序驱动器,这可以从OS X和Boot Camp Assistant工具快速完成。对于不那么熟悉的人,使用Boot Camp本质上意味着Windows 10将直接在硬件上运行,就像Mac是...

Java Web基础入门第二十九讲 基于Servlet+JSP+JavaBean开发模式的用户登录注册_李阿昀的博客-程序员宅基地

Servlet+JSP+JavaBean开发模式(MVC)介绍Servlet+JSP+JavaBean(MVC)模式适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装数据。Servlet+JSP+JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。 这里以一个最常用的用户登录注册程序来讲解Servlet+JSP

随便推点

纯css3实现的创意图片放大镜_weixin_34345753的博客-程序员宅基地

今天要给大家分享的的一款用纯css3实现的图片放大镜特效。页面打开五个小图显示于页面。当鼠标经过图片时,当前图片以灰色背景图的形式展示。效果非常不错。 在线预览   源码下载实现的代码:html代码: <ul class="gallery"> <li class="gallery__item"></li>...

js滚轮事件_进阶的小牛的博客-程序员宅基地

js滚轮事件<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-eq...

java的InputStream和InputStreamReader有什么区别??_weixin_33695082的博客-程序员宅基地

2019独角兽企业重金招聘Python工程师标准>>> ...

修改小程序swiper 点的样式_如何自定义微信小程序swiper轮播图面板指示点的样式..._weixin_39594191的博客-程序员宅基地

微信小程序的swiper组件是滑块视图容器,也就是说平常我们看到的轮播图就可以用它来做,不过这个组件有很多样式是固定的,但是,有时候我们的设计稿的面板指示点是需要个性化的,那么如何去修改swiper组件的面板指示点的样式呢?最近在使用swiper的时候也在想这个,最后发现在调试的时候,可以看到他的选择器。如图:具体代码如下所示:.swiper-box .wx-swiper-dots.wx-swip...

Angular自定义structural指令的实例化过程以及set方法的调用_汪子熙的博客-程序员宅基地_angular set方法

我有一个自定义指令*appUnless, 在第48行使用,这个前面是第39行的,后面是第52行的:观察运行时构造函数传入的elementRef:发现其前面的节点确实为p:且该p的4个子节点如下:且text,span,text和button子节点依次显示如下:给当前的element设置property值:/** * @fileoverview added by tsickle * Generated from: packages/core/src/render3/instructio

数据库 函数依赖_fffffffff_jj的博客-程序员宅基地_数据库函数依赖保持

用处:指导关系模型的设计,规范以及优化非原子 --> 存储复杂,数据冗余改进:1NF处理:复合属性:拆分成多个属性多值属性:创建新的一张表(eg. 一个人有多个手机号)函数依赖(FD)单值映射码是一种特殊的FD:比如超码:可以唯一标识一个元组(SK -> R)候选码(最小超码):CK -> R 且 不存在CK的子集可以 -> RFD的作用:可以检测...

推荐文章

热门文章

相关标签