Как реализован барьер в системах передачи сообщений?

Я понимаю, что один главный процесс отправляет сообщение всем другим процессам. Все остальные процессы в ответ отправляют сообщение главному процессу. Будет ли этого достаточно для работы барьера? Если нет, то что еще нужно?


person MetallicPriest    schedule 07.02.2014    source источник
comment
Будет ли этого достаточно для работы барьера? -- Это работает? Ты пытался? С какими проблемами вы сталкиваетесь? Если нет, то что еще нужно? -- Ты расскажи нам.   -  person Shoe    schedule 07.02.2014
comment
Для каждого полученного сообщения о завершении (которое клиенты отправляют с последующей блокировкой) мастер запускает что-то вроде: if(++atomic_variable >= n) release();   -  person Damon    schedule 07.02.2014


Ответы (2)


Давайте посмотрим на реализацию барьера в OpenMPI. Хотя другие реализации могут немного отличаться, общий шаблон связи должен быть идентичным.

Прежде всего следует отметить, что барьер MPI не требует затрат на установку: процесс, достигший вызова MPI_Barrier, будет блокироваться до тех пор, пока все остальные члены группы также не вызовут MPI_Barrier. Обратите внимание, что MPI не требует от них достижения одного и того же вызова, а только любого вызова MPI_Barrier. Следовательно, поскольку общее количество узлов в группе уже известно каждому процессу, для инициализации вызова не требуется распределять дополнительное состояние.

Теперь давайте посмотрим на код:

/*
 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
 *                         University Research and Technology
 *                         Corporation.  All rights reserved.
 * Copyright (c) 2004-2005 The University of Tennessee and The University
 *                         of Tennessee Research Foundation.  All rights
 *                         reserved.
 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, 
 *                         University of Stuttgart.  All rights reserved.
 * Copyright (c) 2004-2005 The Regents of the University of California.
 *                         All rights reserved.
 * Copyright (c) 2012      Oak Ridge National Labs.  All rights reserved.
 * [...]
 */

[...]

/*
 *  barrier_intra_lin
 *
 *  Function:   - barrier using O(N) algorithm
 *  Accepts:    - same as MPI_Barrier()
 *  Returns:    - MPI_SUCCESS or error code
 */
int
mca_coll_basic_barrier_intra_lin(struct ompi_communicator_t *comm,
                                 mca_coll_base_module_t *module)
{
    int i;
    int err;
    int size = ompi_comm_size(comm);
    int rank = ompi_comm_rank(comm);

Сначала все узлы (кроме узла с рангом 0, корневого узла) отправляют уведомление о достижении барьера корневому узлу:

    /* All non-root send & receive zero-length message. */

    if (rank > 0) {
        err =
            MCA_PML_CALL(send
                         (NULL, 0, MPI_BYTE, 0, MCA_COLL_BASE_TAG_BARRIER,
                          MCA_PML_BASE_SEND_STANDARD, comm));
        if (MPI_SUCCESS != err) {
            return err;
        }

После этого они блокируются в ожидании уведомления от рута:

        err =
            MCA_PML_CALL(recv
                         (NULL, 0, MPI_BYTE, 0, MCA_COLL_BASE_TAG_BARRIER,
                          comm, MPI_STATUS_IGNORE));
        if (MPI_SUCCESS != err) {
            return err;
        }
    }

Корневой узел реализует другую сторону связи. Сначала он блокируется, пока не получит n-1 уведомлений (по одному от каждого узла в группе, кроме него самого, поскольку он уже находится внутри вызова барьера):

else {
        for (i = 1; i < size; ++i) {
            err = MCA_PML_CALL(recv(NULL, 0, MPI_BYTE, MPI_ANY_SOURCE,
                                    MCA_COLL_BASE_TAG_BARRIER,
                                    comm, MPI_STATUS_IGNORE));
            if (MPI_SUCCESS != err) {
                return err;
            }
        }

Как только все уведомления получены, он отправляет сообщения, которых ожидает каждый узел, сигнализируя о том, что все достигли барьера, после чего он покидает сам вызов барьера:

        for (i = 1; i < size; ++i) {
            err =
                MCA_PML_CALL(send
                             (NULL, 0, MPI_BYTE, i,
                              MCA_COLL_BASE_TAG_BARRIER,
                              MCA_PML_BASE_SEND_STANDARD, comm));
            if (MPI_SUCCESS != err) {
                return err;
            }
        }
    }

    /* All done */

    return MPI_SUCCESS;
}

Таким образом, схема связи сначала представляет собой n:1 от всех узлов к корню, а затем 1:n от корня обратно ко всем узлам. Чтобы не перегружать корневой узел запросами, OpenMPI позволяет использовать древовидный коммуникационный шаблон, но основная идея та же: все узлы уведомляют корень при входе в барьер, в то время как корень агрегирует результаты и информирует всех, как только они будут получены. готов продолжить.

person ComicSansMS    schedule 07.02.2014

Нет, этого недостаточно. Как только главный процесс отправил сообщение всем другим процессам, информируя их о том, что он достиг барьера, и все другие процессы ответили, что они тоже достигли барьера, только главный процесс знает, что все процессы достигли барьера. В этом сценарии было бы необходимо другое сообщение от мастера к другим процессам.

Я не претендую на реальную реализацию MPI-барьеров в какой-либо библиотеке, в частности, я не утверждаю, что описанная последовательность сообщений используется на практике, я просто говорю, что она несовершенна в теории.

person High Performance Mark    schedule 07.02.2014
comment
Смотрите, что мастер сначала получает, а затем отправляет. Я тоже упустил из виду условие (ранг › 0) во время моего первого чтения. - person Georg Bisseling; 03.11.2016