MPI_Get читает только первый элемент массива из области общей памяти - PullRequest
0 голосов
/ 28 апреля 2018

Я пытаюсь получить доступ к области общей памяти, содержащей одномерный массив, используя функцию MPI_Get. Рассмотрим следующую программу:

#include <iostream>
#include <ctime>
#include <mpi.h>

void initVector(int* vec, int vecSize)
{
    srand(static_cast<unsigned>(time(NULL)));

    for (int i = 0; i < vecSize; i++)
        vec[i] = std::rand() % 10 + 1;
}

int main(int argc, char** argv)
{
    MPI_Init(&argc, &argv);

    int commSize{ 0 };
    MPI_Comm_size(MPI_COMM_WORLD, &commSize);

    int myRank{ 0 };
    MPI_Comm_rank(MPI_COMM_WORLD, &myRank);

    MPI_Comm MPI_COMM_SHARED{ 0 };
    MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, myRank, MPI_INFO_NULL, &MPI_COMM_SHARED);

    int nodeSize{ 0 };
    MPI_Comm_size(MPI_COMM_SHARED, &nodeSize);

    int nodeRank{ 0 };
    MPI_Comm_rank(MPI_COMM_SHARED, &nodeRank);

    int* masterInVector{ nullptr };
    MPI_Win vectorWinHandle{ 0 };
    MPI_Win_allocate_shared(commSize * sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_SHARED, &masterInVector, &vectorWinHandle);

    int* slaveInVector{ masterInVector };
    MPI_Aint winSizeVector{ 0 };
    int winDispVector{ 0 };

    if (nodeRank != 0)
    {
        MPI_Win_shared_query(vectorWinHandle, 0, &winSizeVector, &winDispVector, &slaveInVector);
    }

    if (nodeRank == 0)
    {
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, MPI_MODE_NOCHECK, vectorWinHandle);
        initVector(slaveInVector, commSize);
        MPI_Win_unlock(0, vectorWinHandle);
    }

    MPI_Barrier(MPI_COMM_WORLD);

    int vectorCell{ -1 };
    for (int i = 0; i < commSize; i++)
    {
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, MPI_MODE_NOCHECK, vectorWinHandle);
        MPI_Get(&vectorCell, 1, MPI_INT, 0, winSizeVector + (i * sizeof(int)), 1, MPI_INT, vectorWinHandle);
        MPI_Win_unlock(0, vectorWinHandle);
        std::cout << "[" << myRank << "]" << vectorCell << std::endl;
    }

    MPI_Finalize();
    return 0;
}

и выходное сообщение для 2 процессоров:

[0]2
[0]0
[1]-1
[1]-1

Ожидаемый выход для 2 процессоров (имейте в виду, что выходные значения генерируются случайным образом в функции initVector):

[0]2
[0]2
[1]7
[1]7

Первый процессор (myRank=0) во время первой итерации цикла for считывает соответствующее значение из общей памяти, а во время второй итерации читает значение 0 из второго элемента в массиве. Второй процессор (myRank=1) ничего не читает независимо от итерации (потому что vectorCell=-1). Есть идеи, в чем проблема?

1 Ответ

0 голосов
/ 30 апреля 2018

Проблема связана с параметром disp_unit функции MPI_Win_allocate_shared(...). Согласно спецификации :

Распространенными вариантами для disp_unit являются 1 (без масштабирования) и (в синтаксисе C) sizeof (тип) для окна, которое состоит из массива элементов типа type. [...]

Произошло несоответствие между параметрами disp_unit и target_disp функций MPI_Win_allocate_shared(...) и MPI_Get(...). Таким образом, код будет выглядеть так:

// ...
MPI_Win_allocate_shared(commSize * sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_SHARED, &masterInVector, &vectorWinHandle);
// ...
int vectorCell{ -1 };
for (int i = 0; i < commSize; i++)
{
    MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, MPI_MODE_NOCHECK, vectorWinHandle);
    MPI_Get(&vectorCell, 1, MPI_INT, 0, i, 1, MPI_INT, vectorWinHandle);
    MPI_Win_unlock(0, vectorWinHandle);
    std::cout << "[" << myRank << "]" << vectorCell << std::endl;
}
// ...

Если мы предположим, что disp_unit = 1, то эквивалентный код будет:

// ...
MPI_Win_allocate_shared(commSize * sizeof(int), 1, MPI_INFO_NULL, MPI_COMM_SHARED, &masterInVector, &vectorWinHandle);
// ...
int vectorCell{ -1 };
for (int i = 0; i < commSize; i++)
{
    MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, MPI_MODE_NOCHECK, vectorWinHandle);
    MPI_Get(&vectorCell, 1, MPI_INT, 0, i * sizeof(int), 1, MPI_INT, vectorWinHandle);
    MPI_Win_unlock(0, vectorWinHandle);
    std::cout << "[" << myRank << "]" << vectorCell << std::endl;
}
// ...
...