OpenMPI源码剖析3:try_kill_peers 和 ompi_rte_abort 函数

接着上一篇的疑问,我们说道,会执行 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 对象是在哪里初始化的?

 

转载于:https://www.cnblogs.com/HelloGreen/p/8757349.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值