MPI_Bcast: преимущества эффективности? - PullRequest
5 голосов
/ 05 августа 2011

В MPI, MPI_Bcast - это просто удобная функция или есть преимущество в эффективности использования ее вместо того, чтобы просто зацикливаться на всех рангах и посылать одно и то же сообщение всем им?

Обоснование: поведение MPI_Bcast при отправке сообщения всем, включая root, мне неудобно, поэтому я бы предпочел не использовать его, если на то нет веской причины, или его можно сделать, чтобы не отправлять сообщение. сообщение для root.

Ответы [ 4 ]

8 голосов
/ 05 августа 2011

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

Например, MPI_Bcast в MPICH2 будет использовать другой алгоритм в зависимости отразмер сообщения .Для коротких сообщений используется двоичное дерево, чтобы минимизировать нагрузку и задержку обработки.Для длинных сообщений он реализуется как разброс двоичного дерева, за которым следует объединение.

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

4 голосов
/ 05 августа 2011

Коллективные коммуникации могут быть намного быстрее, чем ваши собственные. Все имплементации MPI тратят много времени, работая над этими процедурами, чтобы быть быстрыми.

Если вы обычно хотите выполнять вещи коллективного типа, но только для подмножества задач, то вы, вероятно, хотите создать свои собственные субкоммуникаторы и использовать BCAST и т. Д. На этих коммуникаторах.

3 голосов
/ 09 августа 2011

Ответ в том, что MPI_Bcast, вероятно, быстрее, чем цикл, в общем случае. В целом, коллективы MPI оптимизируются для широкого диапазона размеров сообщений, размеров сообщений и разметки конкретных рангов.

Тем не менее, может быть возможно превзойти коллектив при определенных размерах сообщений, размерах связи и разметке рангов. Например, цикл по неблокирующим вызовам точка-точка (например, ISend и Recv / IRecv) может быть быстрее ... но, вероятно, только при нескольких конкретных размерах сообщений, размерах связи и разметке рангов.

Если конкретному алгоритму, который вы кодируете, требуется шаблон Bcast (например, все ранги получают одинаковую полезную нагрузку данных от корня), то используйте коллектив Bcast. В общем, не стоит добавлять усложнения, выполняя собственные «коллективные замены».

Если есть какой-то другой шаблон сообщения, который нужен алгоритму, и Bcast только на частичном подборе ... тогда, возможно, стоит свернуть свой собственный ... но лично я установил эту планку довольно высоко.

3 голосов
/ 05 августа 2011

MPI_Bcast отправляет сообщение от одного процесса («root») всем другим по определению.Вероятно, это будет немного быстрее, чем просто зацикливание на всех процессах.Например, реализация mpich2 использует биномиальное дерево для распространения сообщения.

Если вы не хотите транслировать MPI_COMM_WORLD, но хотите определить подгруппы, вы можете сделать это следующим образом:

#include <stdio.h>
#include "mpi.h"

#define NPROCS 8

int main(int argc, char **argv)
{
    int rank, new_rank, sendbuf, recvbuf,
    ranks1[4]={0,1,2,3}, ranks2[4]={4,5,6,7};

    MPI_Group orig_group, new_group;
    MPI_Comm new_comm;

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    sendbuf = rank;

    /* Extract the original group handle */
    MPI_Comm_group(MPI_COMM_WORLD, &orig_group);

    /* Divide tasks into two groups based on rank */
    if (rank < NPROCS/2) {
        MPI_Group_incl(orig_group, NPROCS/2, ranks1, &new_group);
    } else {
        MPI_Group_incl(orig_group, NPROCS/2, ranks2, &new_group);
    }

    /* Create new communicator and then perform some comm
     * Here, MPI_Allreduce, but you can MPI_Bcast at will
     */
    MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm);
    MPI_Allreduce(&sendbuf, &recvbuf, 1, MPI_INT, MPI_SUM, new_comm);
    MPI_Group_rank (new_group, &new_rank);

    printf("rank= %d newrank= %d recvbuf= %d\n", rank, new_rank, recvbuf); 

    MPI_Finalize();
} 

Что может привести к следующему выводу:

rank= 7 newrank= 3 recvbuf= 22
rank= 0 newrank= 0 recvbuf= 6 
rank= 1 newrank= 1 recvbuf= 6 
rank= 2 newrank= 2 recvbuf= 6 
rank= 6 newrank= 2 recvbuf= 22
rank= 3 newrank= 3 recvbuf= 6
rank= 4 newrank= 0 recvbuf= 22
rank= 5 newrank= 1 recvbuf= 22
...