2013-07-15 39 views
1

所以我很确定这是不可能的,但我想我会问。追查MPI_Reduce

使用MPICH。我想用一个用户定义的简化操作来对派生的结构类型进行一些减少操作。出于我的目的,我需要确切地知道MPI_Reduce内部发生了什么,即Send/Recv调用的顺序以及传递哪些信息的位置。

现在,根据代码,MPI_Reduce的MPICH2实现总是对用户定义的操作使用二叉树算法,所以如果真的按下,我总是可以重新构建发生的事情,但我想知道是否有更好的方法。

回答

3

不幸的是没有更好的方法来追踪MPI集体操作的内部工作。 MPI中的标准跟踪接口基于PMPI范例:所有MPI_*调用实现为实际MPI函数的弱别名。实际功能可在PMPI_*名称下找到(PMPI_*调用可能是真正的实现或别名)。这允许跟踪器库声明他们自己的MPI_*函数,该函数在调用之前和之后生成跟踪事件时调用PMPI_*。例如:

int MPI_Reduce(void *sendbuf, void *recvbuf, int count, 
       MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) 
{ 
    int result; 

    trace_event_start("MPI_Reduce"); 
    result = PMPI_Reduce(sendbuf, recvbuf, count, datatype, op, root, comm); 
    trace_event_end("MPI_Reduce"); 

    return result; 
} 

当这个代码与程序的其他部分联系起来,以MPI_Reduce所有呼叫都通过调用跟踪的版本替换(因为MPI_Reduce原是弱别名,连接器将不抱怨被重新定义的符号)。

现在你的情况,真正的问题是,MPI_Reduce实现不使用到MPI_SendMPI_Recv电话,而是使用低级别的MPICH2函数的调用,例如MPIC_Send_ftMPIC_Recv_ft。这些不能被PMPI机制拦截。在这种情况下,您可以做的是从MPICH2源中提取代码,并将内部呼叫替换为调用MPI_SendMPI_Recv,然后跟踪得到的实现。

我已经完成了上面描述的过程,除了有一点麻烦之外,它对于Open MPI来说工作得非常好 - 一旦您提供了自己的MPI函数实现,例如, MPI_Reduce,它不再是弱的别名,并且跟踪库的链接可能会产生重复的符号错误。在这种情况下,我会简单地命名我的实现MyMPI_Reduce并将#define MPI_Reduce MyMPI_Reduce放在那些必须跟踪的源文件的开头。我对MPICH2并不熟悉,但是从源代码中我可以看出,它允许用户实现插入并且使其更容易(例如,不需要使用预处理器)。

一两件事:MPICH2有几个执行减少,至少在3.0版本中,它使用简单的启发式逻辑选择他们中的一个在运行时:

if ((count*type_size > MPIR_PARAM_REDUCE_SHORT_MSG_SIZE) && 
    (HANDLE_GET_KIND(op) == HANDLE_KIND_BUILTIN) && (count >= pof2)) { 
    /* do a reduce-scatter followed by gather to root. */ 
    mpi_errno = MPIR_Reduce_redscat_gather(sendbuf, recvbuf, count, datatype, op, root, comm_ptr, errflag); 
    if (mpi_errno) { 
     /* for communication errors, just record the error but continue */ 
     *errflag = TRUE; 
     MPIU_ERR_SET(mpi_errno, MPI_ERR_OTHER, "**fail"); 
     MPIU_ERR_ADD(mpi_errno_ret, mpi_errno); 
    } 
} 
else { 
    /* use a binomial tree algorithm */ 
    mpi_errno = MPIR_Reduce_binomial(sendbuf, recvbuf, count, datatype, op, root, comm_ptr, errflag); 
    if (mpi_errno) { 
     /* for communication errors, just record the error but continue */ 
     *errflag = TRUE; 
     MPIU_ERR_SET(mpi_errno, MPI_ERR_OTHER, "**fail"); 
     MPIU_ERR_ADD(mpi_errno_ret, mpi_errno); 
    } 
} 
0

要添加到什么赫里斯托斯说一下在MPICH中调试(它不再名为MPICH2),如果你真的想使用MPICH调试日志,你可以做一些非常手动的跟踪。我不会推荐它,因为它可能比你需要的更冗长,但如果你真的需要知道集体操作是如何在后端工作的,你可以查看关于调试的wiki page以找出你需要的东西。