Я обнаружил, что не могу понять параметр "recvcounts" MPI_Gatherv - PullRequest
1 голос
/ 21 сентября 2011

MPI_Gatherv - это интерфейс MPI, подобный этому:

int MPI_Gatherv(
    void* sendbuf,
    int sendcount,
    MPI_Datatype sendtype,
    void* recvbuf,
    int *recvcounts,
    int *displs,
    MPI_Datatype recvtype,
    int root,
    MPI_Comm comm)

тип "recvcounts" - "int *", так что мы можем установить количество элементов, которые будут получены для каждого процесса соответственно; однако я обнаружил, что этого достичь невозможно:

когда recvcounts [i]

когда recvcounts [i]> sendcount, программа вылетает, сообщение об ошибке выглядит следующим образом:

Fatal error in PMPI_Gatherv: Message truncated, error stack:
PMPI_Gatherv(386).....: MPI_Gatherv failed(sbuf=0012FD34, scount=2, MPI_CHAR, rbuf=0012FCC8, rcnts=0012FB30, displs=0012F998, MPI_CHAR, root=0, MPI_COMM_WORLD) failed
MPIR_Gatherv_impl(199):
MPIR_Gatherv(103).....:
MPIR_Localcopy(332)...: Message truncated; 2 bytes received but buffer size is 1

То есть это означает, что корень должен получать фиксированное количество элементов от каждого процесса, а параметр recvcount не имеет смысла? Или я неправильно понял что-то?

вот мой код:

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

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

    int n, id;
    MPI_Comm_size(MPI_COMM_WORLD, &n);
    MPI_Comm_rank(MPI_COMM_WORLD, &id);

    char x[100], y[100];
    memset(x, '0' + id, sizeof(x));
    memset(y, '%', sizeof(y));
    int cnts[100], offs[100] = {0};
    for (int i = 0; i < n; i++)
    {
        cnts[i] = i + 1;
        if (i > 0)
        {
            offs[i] = offs[i - 1] + cnts[i - 1];
        }
    }
    MPI_Gatherv(x, 1, MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD);    // receive only 1 item from each process
    //MPI_Gatherv(x, 2, MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD);    // crash
    if (id == 0)
    {
        printf("Gatherv:\n");
        for (int i = 0; i < 100; i++)
        {
            printf("%c ", y[i]);
        }
        printf("\n");
    }

    MPI_Finalize();

    return 0;
}

1 Ответ

2 голосов
/ 28 сентября 2011

Как указывает @Molodih, sendcount = recvcount, sendtype = recvtype всегда будут работать; но когда вы начинаете создавать свои собственные типы MPI, у вас часто бывают разные типы отправки и получения, и поэтому recvcount может отличаться от sendcount.

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

Это основная причина, по которой типы и числа отправки и получения различаются в таких вещах, как sendrecv, collect / scatter или в любой другой операции, когда происходят и отправка, и получение.

В вашем случае collectv у каждого процесса может быть свой собственный sendcount, но массив recvcount [] должен быть списком всех этих подсчетов, чтобы получатель мог правильно разместить полученные данные. Если вы не знали эти значения раньше (каждый ранг знал только свой счет, cnts[id]), вы могли бы сначала сделать сбор:

MPI_Gather(&(cnts[id]), 1, MPI_INT, cnts, 1, MPI_INT, 0, MPI_COMM_WORLD):
for (int i = 1; i < n; i++) { 
    offs[i] = offs[i - 1] + cnts[i - 1];
}
MPI_Gatherv(x, cnts[id], MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD);   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...