Трассировка MPI_Reduce

Так что я почти уверен, что это невозможно, но я подумал, что все равно спрошу.

Работа с МПИК. Я хотел бы выполнить некоторые сокращения для производного типа структуры с помощью определяемой пользователем операции сокращения. Для моих целей мне нужно точно знать, что происходит внутри MPI_Reduce, то есть порядок вызовов Send/Recv и какая информация куда передается.

Теперь, согласно коду, реализация MPI_Reduce в MPICH2 всегда использует алгоритм биномиального дерева для определяемых пользователем операций, поэтому я всегда могу реконструировать то, что происходит, если действительно нажать, но мне было интересно, есть ли лучший способ.


person Father Deus    schedule 15.07.2013    source источник


Ответы (2)


К сожалению, нет лучшего способа проследить внутреннюю работу коллективных операций 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);
    }
}
person Hristo Iliev    schedule 16.07.2013

Чтобы добавить к тому, что Христо сказал об отладке в MPICH (он больше не называется MPICH2), вы можете выполнить некоторую ручную трассировку, если вы действительно хотите использовать журналы отладки MPICH. Я бы не рекомендовал его, так как он, вероятно, может быть намного более подробным, чем вам нужно, но если вам действительно нужно знать, как коллективные операции работают на бэкэнде, вы можете проверить вики-страница об отладке, чтобы понять, что вам нужно.

person Wesley Bland    schedule 16.07.2013