Трансляция динамически распределенного 2d массива с использованием MPI_Bcast (...) - PullRequest
0 голосов
/ 16 сентября 2018

Я должен создать массив динамически, используя malloc, корневой процесс делает это, затем предполагается, что массивы будут транслироваться всем остальным процессам, которые его сейчас распечатают, фактически требуется, чтобы другие процессы изменили значение матрица самостоятельно. Моя главная проблема - я не могу транслировать весь массив всем процессам.

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

int main(int argc, char **argv)
{   
    int **array;
    int rank,size,i,j;

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

    size= 4;
    array = (int **)malloc(size*sizeof(int *));
    for(i=0;i<size;i++)
        array[i] = (int *)malloc(size*sizeof(int));
    if(rank==0)
    {
        int t= 0;
        for(i=0;i<size;i++)
        {
            for(j=0;j<size;j++){
                array[i][j]=t++;
                printf("%4d",array[i][j]);
            }
            printf("\n");
        }
        printf("size is %zu\n",sizeof(array));
    }
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Bcast(&size,1,MPI_INT,0,MPI_COMM_WORLD);
    printf("size %d proec %d\n",size,rank);

    MPI_Bcast((int **)&(array[0][0]),size*size,MPI_INT,0,MPI_COMM_WORLD);
    MPI_Barrier(MPI_COMM_WORLD);
    printf("process %d prainting matrix:\n",rank);

    for (i= 0; i <size;i++)
    {
        for(j= 0; j < size; j++)
            printf("%d [%d]\t",array[i][j],rank);
        printf("\n");
    }

    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Finalize();
}

1 Ответ

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

Проблема со строкой

MPI_Bcast((int **)&(array[0][0]),size*size,MPI_INT,0,MPI_COMM_WORLD);

Вы должны сделать

for(i=0;i<size;i++)
{
  MPI_Bcast((int **)&(array[i][0]),size,MPI_INT,0,MPI_COMM_WORLD);
}

Я не знаю, каково было ваше намерение, но sizeof(array) не возвращает размер массивано скорее размер (size_t *), который равен 8 в 64 битах.

Длинное объяснение, если вы хотите его.

MPI_Send или MPI_Bcast действительно отправляют кусок памяти.

Чтобы определить эти чанки, вы должны указать начало (первый аргумент MPI_Bcast или MPI_Send), затем длину (второй аргумент), а затем тип данных (третий аргумент).

В вашем примереон знает, что должен отправить с &(array[0][0]) на &(array[0][0])+(size*size-1)*sizeof(int)

Теперь, когда вы делаете

int main(int argc, char **argv)
{   
    int **array, * array_un;
    int rank,size,i,j;

    int **array
    size= 4;
    array = (int **)malloc(size*sizeof(int *));
    for(i=0;i<size;i++)
    {
        array[i] = (int *)malloc(size*sizeof(int));
        printf("Ox%X\n",(size_t)array[i]);
    }
    printf("end array=Ox%X\n",(size_t) &(array[size-1][size-1]));
    printf("end pointer=Ox%X\n",(size_t) array+(size*size-1)*sizeof(int));
}

, он выводит

Ox13B91A0
Ox13B91C0
Ox13B91E0
Ox13B6B90
end array  = Ox13B6B9C
end pointer= Ox13BB06C

Как вы видите end array иend pointer разные.Если вы теперь посмотрите на адрес каждого malloc, приращение будет 0x20 (что больше, чем 4*size(int)=10), а затем внезапно уменьшится на 0x2650!

Последовательное malloc выделит память без гарантии, что памятьрасположены рядом друг с другом.

Следовательно, вы не можете отправить, используя MPI_Bcast((int **)&(array[0][0]),size*size,MPI_INT,0,MPI_COMM_WORLD);, потому что данные между &(array[0][0]) до & (array[0][0])+(size*size-1)*sizeof(int) на самом деле не содержат данных, которые вы хотите отправить.

Однако один malloc выделяет кусок непрерывной памяти

, поэтому вы можете отправить MPI_Bcast((int **)&(array[i][0]),size,MPI_INT,0,MPI_COMM_WORLD);

To thout через

Настройка отправки иПолучение имеет стоимость, а отправка имеет стоимость.Таким образом, чем меньше MPI_ «чего-то» вы звоните, тем лучше.

Таким образом, ваша матрица должна быть действительно выделена одним malloc

Сравните ваш модифицированный код с этим кодом

#include <mpi.h>

int main(int argc, char **argv)
{   
    int *array;
    int rank,size,i,j;

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

    size= 4;
    array = (int *)malloc(size*size*sizeof(int));

    if(rank==0)
    {
        int t= 0;
        for(i=0;i<size;i++) { for(j=0;j<size;j++){ array[i*size+j]=t++; } }
    }

    MPI_Bcast(array,size*size,MPI_INT,0,MPI_COMM_WORLD);

    MPI_Barrier(MPI_COMM_WORLD);
    printf("process %d printing matrix:\n",rank);

    for (i= 0; i <size;i++)
    {
        for(j= 0; j < size; j++)
            printf("%d [%d]\t",array[i*size+j],rank);
        printf("\n");
    }
    MPI_Finalize();
}
...