接着上一篇的疑问,我们说道,会执行 try_kill_peers 函数,它的函数定义在 ompi_mpi_abort.c 下:

// 这里注释也说到了,主要是杀死在同一个communicator的进程(不包括自己)
/*
* Local helper function to build an array of all the procs in a
* communicator, excluding this process.
*
* Killing a just the indicated peers must be implemented for
* MPI_Abort() to work according to the standard language for
* a 'high-quality' implementation.
*
* It would be nifty if we could differentiate between the
* abort scenarios (but we don't, currently):
* - MPI_Abort()
* - MPI_ERRORS_ARE_FATAL
* - Victim of MPI_Abort()
*/
// 调用时传入了对应通信子
static void try_kill_peers(ompi_communicator_t *comm,
int errcode)
{
  // 1. 第一部分: 给 ompi_process_name_t 指针申请空间,得到进程个数
int nprocs;
ompi_process_name_t *procs; nprocs = ompi_comm_size(comm);
/* ompi_comm_remote_size() returns 0 if not an intercomm, so
this is safe */
nprocs += ompi_comm_remote_size(comm); procs = (ompi_process_name_t*) calloc(nprocs, sizeof(ompi_process_name_t));
if (NULL == procs) {
/* quick clean orte and get out */
ompi_rte_abort(errno, "Abort: unable to alloc memory to kill procs");
} // 2. 第二部分: 将进程放入数组中
/* put all the local group procs in the abort list */
int rank, i, count;
rank = ompi_comm_rank(comm); //这里可以获取到自己在该 communicator 中的 rank————疑问1
for (count = i = 0; i < ompi_comm_size(comm); ++i) {
if (rank == i) {
/* Don't include this process in the array */
--nprocs;
} else {
assert(count <= nprocs);
procs[count++] =
*OMPI_CAST_RTE_NAME(&ompi_group_get_proc_ptr(comm->c_remote_group, i, true)->super.proc_name);
}
} // 3. 第三部分: 远程的 group 进程也放入数组中
/* if requested, kill off remote group procs too */
for (i = 0; i < ompi_comm_remote_size(comm); ++i) {
assert(count <= nprocs);
procs[count++] =
*OMPI_CAST_RTE_NAME(&ompi_group_get_proc_ptr(comm->c_remote_group, i, true)->super.proc_name);
} // 4. 第四部分: 杀死进程
if (nprocs > 0) {
ompi_rte_abort_peers(procs, nprocs, errcode);
} /* We could fall through here if ompi_rte_abort_peers() fails, or
if (nprocs == 0). Either way, tidy up and let the caller
handle it. */
free(procs);
}

 这个时候,就得去看看 ompi_rte_abort_peers(procs, nprocs, errcode) 函数的定义,

 它在 rte_orte.h 中其实是一个宏定义:

#define ompi_rte_abort_peers(a, b, c) orte_errmgr.abort_peers(a, b, c)

  orte_errmgr 是一个结构体对象,调用了abort_peers成员函数,最后在 errmgr.h 中找到了 orte_errmgr 对象:

/*
* Module Structure
*/
struct orte_errmgr_base_module_2_3_0_t {
/** Initialization Function */
orte_errmgr_base_module_init_fn_t init;
/** Finalization Function */
orte_errmgr_base_module_finalize_fn_t finalize; orte_errmgr_base_module_log_fn_t logfn;
orte_errmgr_base_module_abort_fn_t abort;
orte_errmgr_base_module_abort_peers_fn_t abort_peers;
};
typedef struct orte_errmgr_base_module_2_3_0_t orte_errmgr_base_module_2_3_0_t;
typedef orte_errmgr_base_module_2_3_0_t orte_errmgr_base_module_t;
ORTE_DECLSPEC extern orte_errmgr_base_module_t orte_errmgr; //这是一个导出的extern全局变量

  再顺便附上该结构体中的函数的定义,也在 rte_orte.h  头文件中:

/*
* Framework Interfaces
*/
/**
* Module initialization function.
*
* @retval ORTE_SUCCESS The operation completed successfully
* @retval ORTE_ERROR An unspecifed error occurred
*/
typedef int (*orte_errmgr_base_module_init_fn_t)(void); /**
* Module finalization function.
*
* @retval ORTE_SUCCESS The operation completed successfully
* @retval ORTE_ERROR An unspecifed error occurred
*/
typedef int (*orte_errmgr_base_module_finalize_fn_t)(void); /**
* This is not part of any module so it can be used at any time!
*/
typedef void (*orte_errmgr_base_module_log_fn_t)(int error_code, char *filename, int line); /**
* Alert - self aborting
* This function is called when a process is aborting due to some internal error.
* It will finalize the process
* itself, and then exit - it takes no other actions. The intent here is to provide
* a last-ditch exit procedure that attempts to clean up a little.
*/
typedef void (*orte_errmgr_base_module_abort_fn_t)(int error_code, char *fmt, ...)
__opal_attribute_format_funcptr__(__printf__, 2, 3); /**
* Alert - abort peers
* This function is called when a process wants to abort one or more peer processes.
* For example, MPI_Abort(comm) will use this function to terminate peers in the
* communicator group before aborting itself.
*/
typedef int (*orte_errmgr_base_module_abort_peers_fn_t)(orte_process_name_t *procs,
orte_std_cntr_t num_procs,
int error_code);

这里呢,对 杀死进程 这一块的探索呢,就先到此了————这里已经知道,接下来的步骤就是遍历数组,杀死进程,
这里留下 疑问2: orte_errmgr 这个 orte_errmgr_base_module_2_3_0_t 对象是在哪里初始化的?它的函数在哪里赋值了?我猜是在初始化MPI_Init()的过程中

上一篇文章,还有一个 ompi_rte_abort 函数,在 rte.h 中的注释说明有提及:

 * (d) Error handling objects and operations
* 1. void ompi_rte_abort(int err_code, char *fmt, ...) - Abort the current
* process with the specified error code and message.
* 2. int ompi_rte_abort_peers(ompi_process_name_t *procs, size_t nprocs) -
* Abort the specified list of peers
* 3. OMPI_ERROR_LOG(rc) - print error message regarding the given return code

  也就是说,ompi_rte_abort 这个函数就是 abort 自身进程了。

那么,我们就把这2个函数的大概交代清楚了。   在 rte.h 这个头文件中,我们还找到了一个比较有价值的注释说明。这个将会留在下一篇文章中说明。

重复一下本文留下的疑点:

1.  ompi_comm_rank(comm)  这个函数

2.  orte_errmgr 这个 orte_errmgr_base_module_2_3_0_t 对象是在哪里初始化的?

OpenMPI源码剖析3:try_kill_peers 和 ompi_rte_abort 函数的更多相关文章

  1. OpenMPI源码剖析1:MPI_Init初探

    OpenMPI的底层实现: 我们知道,OpenMPI应用起来还是比较简单的,但是如果让我自己来实现一个MPI的并行计算,你会怎么设计呢?————这就涉及到比较底层的东西了. 回想起我们最简单的代码,通 ...

  2. c++ stl源码剖析学习笔记(一)uninitialized_copy()函数

    template <class InputIterator, class ForwardIterator>inline ForwardIterator uninitialized_copy ...

  3. OpenMPI源码剖析:网络通信原理(二) 如何选择网络协议?

    因为比较常用的是 TCP 协议,所以在 opal/mca/btl/tcp/btl_tcp.h 头文件中找到对应的 struct mca_btl_tcp_component_t { mca_btl_ba ...

  4. OpenMPI源码剖析2:ompi_mpi_errors_are_fatal_comm_handler函数

    上一篇文章说道,初始化失败会有一个函数调用: ompi_mpi_errors_are_fatal_comm_handler(NULL, NULL, message); 所以这里简单地进入了 ompi_ ...

  5. STL源码剖析之list的sort函数实现

    SGI  STL的list的函数的实现源码大致如下: //list 不能使用sort函数,因为list的迭代器是bidirectional_iterator, 而sort //sort函数要求rand ...

  6. OpenMPI源码剖析:网络通信原理(一)

    MPI中的网络通信的原理,需要解决以下几个问题: 1. MPI使用什么网络协议进行通信? 2.中央数据库是存储在哪一台机器上? 3.集群中如果有一台机器挂掉了是否会影响其他机器? 参考: https: ...

  7. OpenMPI源码剖析4:rte.h 头文件的说明信息

    上一篇文章中说道,我们在 rte.h 中发现了有价值的说明: 我们一块一块来分析,首先看到第一块,关于 Process name Object: * (a) Process name objects ...

  8. 【Opencv 源码剖析】 一、 create函数

    1. inline Mat::Mat(int _rows, int _cols, int _type) : size(&rows) { initEmpty();//将data.cols.row ...

  9. jQuery之Deferred源码剖析

    一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...

随机推荐

  1. MYSQL命令简要笔记

    mysqldump "C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqldump.exe"    --host=localhost ...

  2. 一道关于js正则表达式的面试题

    这道面试题明显是要用到正则表达式来解决的,由于太久没有写正则表达式了,一时之间竟然写不出来,所以记录一下笔记,下面直接上代码: function parseUrl(str) { // 判断是否传入参数 ...

  3. Java分布式锁之数据库方式实现

    之前的文章<Java分布式锁实现>中列举了分布式锁的3种实现方式,分别是基于数据库实现,基于缓存实现和基于zookeeper实现.三种实现方式各有可取之处,本篇文章就详细讲解一下Java分 ...

  4. ckeditor + ckfinder + oss存储

    ckeditor 与 ckfinder 的整合方法 网上有很多,这里我也就不说了.  (主要是以前整合的现在忘记咋弄的了0.0) 我这里整合后直接使用js代码 <script type=&quo ...

  5. 献给初学者:小白该如何学习Linux操作系统

    一. 选择适合自己的Linux发行版 谈到linux的发行版别,太多了,可能谁也不能给出一个准确的数字,但是有一点是能够必定的,linux正在变得越来越盛行, 面临这么多的Linux 发行版,打算从别 ...

  6. LinkedList的源码分析(基于jdk1.8)

    1.初始化 public LinkedList() { } 并未开辟任何类似于数组一样的存储空间,那么链表是如何存储元素的呢? 2.Node类型 存储到链表中的元素会被封装为一个Node类型的结点.并 ...

  7. spark ---词频统计(二)

    利用python来操作spark的词频统计,现将过程分享如下: 1.新建项目:(这里是在已有的项目中创建的,可单独创建wordcount项目) ①新建txt文件: wordcount.txt (文件内 ...

  8. verilog中参数传递与参数定义中#的作用(二)

    一.module内部有效的定义 用parameter来定义一个标志符代表一个常量,称作符号常量,他可以提高程序的可读性和可维护性.parameter是参数型数据的关键字,在每一个赋值语句的右边都必须是 ...

  9. 由OpenResty粘合的企业Web架构

    前言:    2012年2月章亦春(agentzh)在Tech-Club的一次线下聚会上以<由Lua 粘合的Nginx生态环境>为主题做了演讲,分析了企业Web架构的趋势,即一个看起来完整 ...

  10. 无限滚动HTML UL结构

    http://framework7.taobao.org/docs/infinite-scroll.html#.VUjA7NOqqko