首页 > 解决方案 > 使用 MPI_Bcast(...) 广播动态分配的二维数组

问题描述

我必须使用 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();
}

标签: mpi

解决方案


问题在于线路

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 *)64 位中 8 的大小。

如果你想要一个长的解释。

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 arrayend pointer不同的。如果您现在查看每个malloc增量为 0x20(大于4*size(int)=10)的地址,然后突然减 0x2650 !

连续malloc分配内存,但不保证内存是相邻分配的。

因此,您无法发送 using MPI_Bcast((int **)&(array[0][0]),size*size,MPI_INT,0,MPI_COMM_WORLD);,因为&(array[0][0])to &之间的数据(array[0][0])+(size*size-1)*sizeof(int)实际上并不包含您要发送的数据。

然而,malloc分配一块连续的内存

所以你可以发送MPI_Bcast((int **)&(array[i][0]),size,MPI_INT,0,MPI_COMM_WORLD);

要彻底

设置发送和接收是有成本的,发送也是有成本的。所以 MPI_"something" 调用越少越好。

所以你的矩阵应该真正分配一个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();
}

推荐阅读