Неправильно ли вызывать MPI_Bcast несколько раз? - PullRequest
0 голосов
/ 08 мая 2019

Я пытаюсь реализовать умножение матрицы на вектор с использованием MPI (то есть матрица nxn, умноженная на вектор nx1).

Изначально я решил использовать несколько вызовов MPI_Bcast (прежде чем я заметилMPI_AllGather ...) и я наткнулся на какое-то странное поведение.По-видимому, данные могут быть получены независимо от того, какой ранг передан вызову MPI_Bcast.

Часть используемого кода (функции вызываются сразу после друг друга, поэтому отправка широковещательной рассылки происходит до получения широковещательной рассылки).Отпечатки предназначены только для целей отладки, где я знаю, что данные тестирования имеют длину 2:

class Processor
{
public:
    Processor(int rank, int communicatorSize);

private:
    void broadcastOwnVectorToOtherRanks();
    void receiveBroadcastsFromOtherRanks();
    //...

    int ownRank;
    int communicatorSize;
    std::vector<int> ownVectorPart;
    std::vector<int> totalVector;
    //...
};

void Processor::broadcastOwnVectorToOtherRanks()
{
    //ownVectorPart is correctly filled before this function call
    std::printf("Own data in vector %d %d\n", ownVectorPart[0], ownVectorPart[1]);
    MPI_Bcast(ownVectorPart.data(), ownVectorPart.size(), MPI_INT, ownRank, MPI_COMM_WORLD);
}

void Processor::receiveBroadcastsFromOtherCommunicators()
{
    for (int rank = 0; rank < communicatorSize; ++rank)
    {
        if (rank == ownRank)
        {
            totalVector.insert(totalVector.end(), ownVectorPart.begin(), ownVectorPart.end());
        }
        else
        {
            std::vector<int> buffer(ownVectorPart.size());
            MPI_Bcast(buffer.data(), ownVectorPart.size(), MPI_INT, rank, MPI_COMM_WORLD);
            std::printf("Received from process with rank %d: %d %d\n", rank, buffer[0], buffer[1]);
            totalVector.insert(totalVector.end(), buffer.begin(), buffer.end());
        }
    }
}

Результат (отсортирован по рангу):

[0] Own data in vector 0 1
[0] Received from communicator 1: 6 7
[0] Received from communicator 2: 4 5
[0] Received from communicator 3: 2 3
[1] Own data in vector 2 3
[1] Received from communicator 0: 0 1
[1] Received from communicator 2: 4 5
[1] Received from communicator 3: 6 7
[2] Own data in vector 4 5
[2] Received from communicator 0: 0 1
[2] Received from communicator 1: 2 3
[2] Received from communicator 3: 6 7
[3] Own data in vector 6 7
[3] Received from communicator 0: 4 5
[3] Received from communicator 1: 2 3
[3] Received from communicator 2: 0 1

Как видите,в процессе с рангом 0 и 3 полученные данные отличаются от отправленных данных.Например, процесс с рангом 0 получил данные с рангом 3, хотя он ожидает данные от процесса 1.

Мне кажется, что ранг не учитывается при получении широковещательных данных и MPIприсваивает данные в том виде, в каком они получены, независимо от того, были ли они ожидаемыми или нет.

Почему MPI_Bcast получает данные от процесса с рангом 3, когда в качестве аргумента передается ранг 1?Вызывает ли MPI_Bcast несколько раз одновременно неопределенное поведение?Или в моем коде есть ошибка?

1 Ответ

0 голосов
/ 23 мая 2019

Цитирование стандарта MPI 3.1 (раздел 5.12):

Все процессы должны вызывать коллективные операции (блокирующие и неблокирующие) в том же порядке на коммуникатор. В частности, когда процесс вызывает коллективная операция, все остальные процессы в коммуникаторе должны в конце концов, вызовите ту же коллективную операцию, и нет другая коллективная работа с тем же коммуникатором между ними.

Объедините это с разделом 5.4:

Если comm является внутрикоммуникатором, MPI_BCAST передает сообщение от процесс с корнем ранга для всех процессов группы, сам включен. Он вызывается всеми членами группы, использующими один и тот же аргументы для comm и root.

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

Я считаю, что MPI_Allgather больше подходит для общения, которое вам, кажется, нужно. Он собирает одинаковое количество данных от всех процессов и копирует их в каждый процесс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...