1

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

与 MPICH 合作。我想使用用户定义的归约操作对派生结构类型执行一些归约。出于我的目的,我需要确切地知道 MPI_Reduce 内部发生了什么,即 Send/Recv 调用的顺序以及哪些信息在哪里传递。

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

4

2 回答 2

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是不是使用对低级 MPICH2 函数的调用MPI_Send而是MPI_Recv使用对低级 MPICH2 函数的调用来实现的,例如MPIC_Send_ftand MPIC_Recv_ft。这些不能使用 PMPI 机制拦截。在这种情况下,您可以做的是从 MPICH2 源代码中提取代码并将内部调用替换为对MPI_Sendand的调用MPI_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);
    }
}
于 2013-07-16T11:59:56.197 回答
0

为了补充 Hristo 关于在 MPICH 中调试的内容(它不再命名为 MPICH2),如果您真的想使用 MPICH 调试日志,您可以进行一些非常手动的跟踪。我不推荐它,因为它可能比你需要的更冗长,但如果你真的需要知道集体操作在后端是如何工作的,你可以查看关于调试的wiki 页面以确定你需要什么。

于 2013-07-16T14:09:52.463 回答