MPI_Gatherv неравный 2D-массив

Я хочу расширить этот пример с помощью Джонатан Дурси для неравного двумерного массива с использованием MPI_Scatterv и MPI_Gatherv. По сути, у меня есть 4 локальных процесса, каждый из которых содержит массив разных размеров:

Процесс = 0

|00000| 
|00000| 
|00000|

Процесс = 1

|1111| 
|1111| 
|1111|

Процесс = 2

|22222|
|22222|

Процесс = 3

|33333| 
|33333|

Я собрал их в мастер-процесс и рассчитывал получить:

Мастер = 0

|000001111|
|000001111|
|000001111|
|222223333|
|222223333|

Однако ниже показано, что я получил из своего кода.

Основной процесс

|000001111|
|100000111|
|110000011|
|222223333|
|322222333|

Я думаю, что с моим MPI_Type_vector что-то не так. Любые предложения, чтобы исправить это.

Ниже мой код:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <mpi.h>

int main(int argc, char **argv)
{
    int rank, size;        // rank of current process and no. of processes
    int domain_x, domain_y;
    int global_x, global_y;
    int topx = 2, topy = 2;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0)
    {
        domain_x = 5;
        domain_y = 3;
    }

    if (rank == 1)
    {
        domain_x = 4;
        domain_y = 3;
    }

    if (rank == 2)
    {
        domain_x = 5;
        domain_y = 2;
    }

    if (rank == 3)
    {
        domain_x = 4;
        domain_y = 2;
    }

    global_x = 9;
    global_y = 5;

    int *glob_data = new int[global_x*global_y];

    // Initialize local data   
    int *local_data = new int[domain_x*domain_y]; 
    for (int i = 0; i < domain_x; ++i)
    {
        for (int j = 0; j < domain_y; ++j)
        {
            local_data[j*domain_x+i] = rank;
        }
    }

    for (int p=0; p<size; p++) {
        if (p == rank) {
            printf("rank = %d\n", rank);
            for (int j=0; j<domain_y; j++) {
                for (int i=0; i<domain_x; i++) {
                    printf("%3d ",(int)local_data[j*domain_x+i]);
                }
                printf("\n");
            }
            printf("\n");
        }
        MPI_Barrier(MPI_COMM_WORLD);
    }


    MPI_Datatype blocktype, blocktype2;
    MPI_Type_vector(domain_y, domain_x, topx*domain_x, MPI_INT, &blocktype2);
    MPI_Type_create_resized(blocktype2, 0, sizeof(int), &blocktype);
    MPI_Type_commit(&blocktype);

    int *displs = new int[topx*topy];
    int *counts = new int[topx*topy];
    for (int j=0; j<topy; j++) {
        for (int i=0; i<topx; i++) {
            displs[j*topx+i] = j*global_x*domain_y + i*domain_x;
            counts [j*topx+i] = 1;
        }
    }

    MPI_Gatherv(local_data, domain_x*domain_y, MPI_INT, glob_data, counts, displs, blocktype, 0, MPI_COMM_WORLD);

    if (rank == 0)
    {
        printf("Master process = %d\n", rank);
        for (int j=0; j<global_y; j++) {
            for (int i=0; i<global_x; i++) {
                printf("%d  ", glob_data[j*global_x+i]);
            }
            printf("\n");
        }
    }

    MPI_Type_free(&blocktype);
    MPI_Type_free(&blocktype2);
    MPI_Finalize();

    return 0;
}

person PLe    schedule 06.06.2016    source источник
comment
Примечание: этот вопрос был связан с тем самым ответом, на который вы ссылались в своем посте. Хотя технически это дубликат, еще несколько замечаний о вашем коде: 1) Ваш третий аргумент MPI_Type_vector неверен, он должен быть global_x. 2) подписи типов в коллективе должны совпадать. Отличаться могут только смещения. 3) Инструмент проверки правильности MPI MUST может помочь вам отладить такие вопросы. Это даст вам полезное и конкретное сообщение об ошибке в вашем случае.   -  person Zulan    schedule 07.06.2016
comment
Блоки, которые вы получаете, перекрываются, потому что приемник использует один и тот же тип данных для всех четырех блоков. ДОЛЖЕН действительно помочь в обнаружении таких случаев: он выдает такие ошибки, как Два коллективных вызова используют пары (тип данных, количество), которые охватывают сигнатуры типов разной длины! и создает графики, такие как i.imgur.com/YpZ9D3s.png (оба из вашей программы)   -  person Hristo Iliev    schedule 07.06.2016
comment
@Зулан. Я согласен, что третий аргумент в MPI_Type_vector должен быть global_x. Но это не решает проблему. Христо прав, использовались одни и те же blocktype из ранга 0, и это вызвало проблему. MUST будет полезен в этом случае. Спасибо.   -  person PLe    schedule 07.06.2016
comment
@Hristo: Хороший график. Я проверю это, чтобы найти решение.   -  person PLe    schedule 07.06.2016
comment
@PLe, ты смотрел на дубликат? ДОЛЖЕН показать вам проблему, но решение сложное...   -  person Zulan    schedule 07.06.2016
comment
@Zulan: я посмотрел на это, очень похоже на мою проблему. Да, решение намного сложнее, чем равномерный случай. Поиграю с ним, чтобы посмотреть, смогу ли я немного упростить. Спасибо.   -  person PLe    schedule 08.06.2016