Вопрос в MPI_Gather параллельного программирования - PullRequest
3 голосов
/ 19 декабря 2010

Я новичок, который вставляет в параллельное программирование. Для моего понимания я пытаюсь кодировать сам. Тогда я обнаружил, что я не понимаю в MPI_Gather. Давайте сначала посмотрим код, а потом объясню.

#include "mpi.h"
#include <stdio.h>
int main (int argc, char *argv[]) {
int size;
int rank;
int a[12];
int i;
int start,end;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if(rank==0)
{
    for(i=0;i<12;i++)
    {
        a[i] = 100;
    }
}

start = 12/size*rank;
end = 12/size*(rank+1);
for(i=start;i<end;i++)
{
    a[i] = rank;
    printf("rank %d set a[%d] equal to %d\n",rank,i,rank);
}
MPI_Gather(&a[start],12/size*rank,MPI_INT,a,12/size*rank,MPI_INT,0,MPI_COMM_WORLD);
if(rank==0)
{
    for(i=0;i<12;i++)
    {
        printf("%d    %d\n",i,a[i]);
    }
}
MPI_Finalize();
return 0;
}

Для этого кода моя цель - собрать значение в подмассиве, который генерируется в каждом процессе, и сохранить его в массиве a. Затем дайте процессу 0 распечатать его.

Прежде всего, я инициализирую все значение в массиве до 100

Затем я вычисляю начальный индекс и конечный индекс для каждого процесса (в этом случае номер процесса должен быть кратным 12)

Далее я присваиваю массиву значение, равное ему рангу

Далее я собираю это

Наконец, я печатаю его на экране

Вот выход для 3 процесса размером = 3

ранг 2 установить [8] равным 2

ранг 2 установить [9] равным 2

ранг 2 установить [10] равным 2

ранг 2 установить [11] равным 2

ранг 1 установить [4] равным 1

ранг 1 установить [5] равным 1

ранг 1 установить [6] равным 1

ранг 1 установить [7] равным 1

ранг 0 установить [0] равным 0

ранг 0 установить [1] равным 0

ранг 0 установить [2] равным 0

ранг 0 установить [3] равным 0

0 0

1 0

2 0

3 0

4 100

5 100

6 100

7 100

8 100

9 100

10 100

11 100

Как вы видите, сбор собирает только первую длину данных, как я могу это исправить.

Заранее спасибо.

Ответы [ 2 ]

7 голосов
/ 19 декабря 2010

Поздравляю, вы почти получили его с первой попытки.

Вам необходимо изменить MPI_Gather строку на

MPI_Gather(&a[start],12/size,MPI_INT,a,12/size,MPI_INT,0,MPI_COMM_WORLD);

Подпись для MPI_Gather

#include "mpi.h"
int MPI_Gather ( void *sendbuf, int sendcnt, MPI_Datatype sendtype, 
                void *recvbuf, int recvcount, MPI_Datatype recvtype, 
                int root, MPI_Comm comm )

Итак, вы правильно sendbuf, sendtype, recvbuf, recvtype, root и comm; проблема заключалась в подсчете. Вы хотите отправить не 12/size*rank, то есть start, целые числа; Вы хотите отправить 12/size, или просто end-start целых чисел, и получить столько же от каждого процесса.

MPI_Gather требует, чтобы каждый процесс отправлял одинаковое количество информации (если нет, вы хотите использовать MPI_Gatherv() вместо этого). В вашем случае, первому процессу было сказано отправить 0, второму - 4, а третьему - 8; стандарт не определяет, что делать в этом случае, и похоже, что в итоге ничего не было отправлено. (Или, конечно, не получено; вашему корневому процессу 0 было приказано отправить 0 int, поэтому он предположительно ожидал 0 intgs от любой другой задачи). Так что у вас осталось только то, что ранг 0 имел бы еще до сбора; 100 везде, кроме своих собственных значений, которые были 0.

Исправляя сбор, вы должны получить правильные результаты:

rank 0 set a[0] equal to 0
rank 0 set a[1] equal to 0
rank 0 set a[2] equal to 0
rank 0 set a[3] equal to 0
rank 1 set a[4] equal to 1
rank 1 set a[5] equal to 1
rank 1 set a[6] equal to 1
rank 1 set a[7] equal to 1
rank 2 set a[8] equal to 2
rank 2 set a[9] equal to 2
rank 2 set a[10] equal to 2
rank 2 set a[11] equal to 2
0    0
1    0
2    0
3    0
4    1
5    1
6    1
7    1
8    2
9    2
10    2
11    2
0 голосов
/ 26 декабря 2014

Плз, попробуйте этот код!

#include "mpi.h"
#include <stdio.h>
int main (int argc, char *argv[]) {
int size;
int rank;
int a[12] , b[12];
int i;
int start,end;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if(rank==0)
{
    for(i=0;i<12;i++)
    {
        a[i] = 100;
    }
}

start = 12/size*rank;
end = 12/size*(rank+1);
for(i=start;i<end;i++)
{
    a[i] = rank;
    printf("rank %d set a[%d] equal to %d\n",rank,i,rank);
}
MPI_Gather(&a[start],12/size,MPI_INT,b,12/size,MPI_INT,0,MPI_COMM_WORLD);
if(rank==0)
{
    for(i=0;i<12;i++)
    {
        printf("%d    %d\n",i,b[i]);
    }
}
MPI_Finalize();
return 0;
}
...