所以我很確定這是不可能的,但我想我會問。追查MPI_Reduce
使用MPICH。我想用一個用戶定義的簡化操作來對派生的結構類型進行一些減少操作。出於我的目的,我需要確切地知道MPI_Reduce內部發生了什麼,即Send/Recv調用的順序以及傳遞哪些信息的位置。
現在,根據代碼,MPI_Reduce的MPICH2實現總是對用戶定義的操作使用二叉樹算法,所以如果真的按下,我總是可以重新構建發生的事情,但我想知道是否有更好的方法。
所以我很確定這是不可能的,但我想我會問。追查MPI_Reduce
使用MPICH。我想用一個用戶定義的簡化操作來對派生的結構類型進行一些減少操作。出於我的目的,我需要確切地知道MPI_Reduce內部發生了什麼,即Send/Recv調用的順序以及傳遞哪些信息的位置。
現在,根據代碼,MPI_Reduce的MPICH2實現總是對用戶定義的操作使用二叉樹算法,所以如果真的按下,我總是可以重新構建發生的事情,但我想知道是否有更好的方法。
不幸的是沒有更好的方法來追蹤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_Send
和MPI_Recv
電話,而是使用低級別的MPICH2函數的調用,例如MPIC_Send_ft
和MPIC_Recv_ft
。這些不能被PMPI機制攔截。在這種情況下,您可以做的是從MPICH2源中提取代碼,並將內部呼叫替換爲調用MPI_Send
和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);
}
}
要添加到什麼赫里斯託斯說一下在MPICH中調試(它不再名爲MPICH2),如果你真的想使用MPICH調試日誌,你可以做一些非常手動的跟蹤。我不會推薦它,因爲它可能比你需要的更冗長,但如果你真的需要知道集體操作是如何在後端工作的,你可以查看關於調試的wiki page以找出你需要的東西。