• 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 对象是在哪里初始化的?

  • 相关阅读:
    2012 金华 现场赛
    依据错误原理解决Hibernate执行出现No CurrentSessionContext configured!错误
    【python】a[::-1]翻转
    【算法】各种哈希算法
    【wireshark】打开后显示There are no interfaces on which a capture can be done
    【python】在python中调用mysql
    【mysql】执行mysql脚本
    【mysql】用navicat连接虚拟机mysql出现错误代码(10038)
    【python-mysql】在ubuntu下安装python-mysql环境
    【python】lamda表达式,map
  • 原文地址:https://www.cnblogs.com/HelloGreen/p/8757349.html
Copyright © 2020-2023  润新知