Трудно понять, разброс MPI и собрать в C - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь научиться использовать MPI. Ниже моя простая программа для тестирования MPI разброса и сбора. Я не понимаю, как это работает и почему это дает результат

1 2 3 4 4 5 6 7 8 9 10 11

вместо ожидаемого

1 2 3 4 5 6 7 8 9 10 11 12

Документация и все примеры, которые я могу найти, слишком сложны / плохо сформулированы, чтобы я мог их понять. Я просто хочу разбить массив по 3 процессам и добавить один к каждому значению в каждом процессе. В качестве альтернативы я был бы рад видеть, как двумерный массив отправлялся построчно каждому процессу, и каждая строка была обработана просто.

int main(int argc, char **argv) {
    int rank; // my process ID
    int size = 3; // number of processes/nodes
    MPI_Status status;
    MPI_Init(&argc, &argv); // start MPI
    MPI_Comm_size(MPI_COMM_WORLD, &size); // initialize MPI
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    unsigned char inData[12]; // data returned after being "processed"
    unsigned char outData[12]; // buffer for receiving data
    unsigned long datasize = 12; // size of data to process
    unsigned char testData[12]; // data to be processed

    if (rank == 0) {
        // initialize data
        for (int i = 0; i < datasize; i++) {
            testData[i] = i;
            outData[i] = 0;
            inData[i] = 0;
        }
    }

    // scatter the data to the processes
    // I am not clear about the numbers sent in and out
    MPI_Scatter(&testData, 12, MPI_UNSIGNED_CHAR, &outData, 
        12, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
    MPI_Barrier(MPI_COMM_WORLD);

    // process data
    for (int i = 0; i < 4; i++) { outData[i] = outData[i] + 1; }

    MPI_Barrier(MPI_COMM_WORLD);

    // gather processed data
    MPI_Gather(&outData, 12, MPI_UNSIGNED_CHAR, &inData, 
        12, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);

    //print processed data from root 
    if (rank == 0) {
        for (int i = 0; i < 12; i++) {
            printf("\n%d", inData[i]);
        }

        MPI_Finalize();
    }

    return 0;
}

1 Ответ

0 голосов
/ 06 сентября 2018

Хотя ваша основная ошибка - 12 вместо 4, давайте сделаем это шаг за шагом.

// int size = 3; // number of processes/nodes
int size;
...
MPI_Comm_size(MPI_COMM_WORLD, &size); // initialize MPI
assert(size == 3);

Нет смысла устанавливать size в 3. Это значение будет перезаписано на MPI_Comm_size фактическим количеством процессов. Это число определяется тем, как вы запускаете приложение MPI (например, mpirun -np 3).

//unsigned char outData[12]; // buffer for receiving data
unsigned char outData[4];

У нас есть 12 элементов и 3 процесса, по 4 элемента на процессы. Итак, 4 элемента достаточно для outData.

outData[i] = 0;
inData[i] = 0;

Нет смысла обнулять эти буферы, они будут перезаписаны.

// scatter the data to the processes
// I am not clear about the numbers sent in and out
MPI_Scatter(&testData, 4 /*12*/, MPI_UNSIGNED_CHAR, &outData,
    4 /*12*/, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);

У нас есть 4 элемента на процессы, поэтому число должно быть 4, а не 12.

MPI_Barrier(MPI_COMM_WORLD);

Вам здесь не нужны барьеры.

MPI_Gather(&outData, 4 /*12*/, MPI_UNSIGNED_CHAR, &inData, 
    4 /*12*/, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);

Та же история, 4 вместо 12.

MPI_Finalize();

Это должно вызываться всеми процессами.

...