MPI_Gatherv неравен 2D масив

Искам да разширя този пример с Джонатан Дурси за неравен 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
Забележка: това Q беше свързано от самия отговор, който посочихте в публикацията си. Въпреки че технически това е дубликат, още няколко забележки относно вашия код: 1) Третият ви аргумент за MPI_Type_vector е грешен, трябва да бъде global_x. 2) Подписите на типовете в колектива трябва да съвпадат. Само преместванията могат да се различават. 3) Инструментът за проверка на коректността на MPI ТРЯБВА може да ви помогне да отстраните грешки такива въпроси. Ще ви даде полезно и конкретно съобщение за грешка във вашия случай.   -  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
@Христо: Хубава графика. Ще го проверя, за да намеря решение.   -  person PLe    schedule 07.06.2016
comment
@PLe, погледна ли дубликата? ТРЯБВА да ви покаже проблема, но решението е сложно...   -  person Zulan    schedule 07.06.2016
comment
@Zulan: Погледнах го, много подобно на моя проблем. Да, решението е много по-сложно от униформения случай. Ще си поиграя с него, за да видя дали мога да го опростя малко. Благодаря.   -  person PLe    schedule 08.06.2016