跟踪MPI_Reduce

时间:2013-07-15 22:18:33

标签: mpi reduce mpich

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

使用MPICH。我想使用用户定义的reduce操作对派生的struct类型执行一些约简。为了我的目的,我需要确切地知道MPI_Reduce中发生了什么,即发送/接收呼叫的顺序以及在哪里传递了哪些信息。

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

2 个答案:

答案 0 :(得分: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);
    }
}

答案 1 :(得分:0)

要添加Hristo所说的MPICH调试(它不再命名为MPICH2),如果你真的想使用MPICH调试日志,你可以做一些非常手动的跟踪。我不推荐它,因为它可能比你需要的更冗长,但如果你真的需要知道集合操作如何在后端工作,你可以查看wiki page调试以找出什么你需要。