MPI_Bcast一个动态的2Darrays
我试图将带有bcast的动态二维数组传递给所有级别。 我有以下代码。
#include #include int main(int argc, char **argv) { float **array; int rank,size,i,j; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_size(MPI_COMM_WORLD,&size); if(rank==0) { array = (float **)malloc(10*sizeof(float)); for(i=0;i<10;i++) array[i] = (float *)malloc(10*sizeof(float)); for(i=0;i<10;i++) for(j=0;j<10;j++) array[i][j]=i+j; } MPI_Bcast(array,10*10,MPI_FLOAT,0,MPI_COMM_WORLD); MPI_Finalize(); }
由于某种原因,我无法理解我得到分段错误。 谁知道问题是什么?
array
应该是100而不是10,因为每行分配10个浮点数。 JackN的答案有代码来做到这一点。
但是,在除0级以外的任何进程上,指向数组的指针将为null
。 您需要在所有进程上初始化数组,然后在根上填充数组。
你可以将malloc代码移出if (rank ==0)
块,它应该按你的预期工作。
这里有三个问题 – 一个涉及分配,一个涉及分配的位置,一个涉及MPI如何工作,而其他答案都没有完全触及所有这些问题。
第一个也是最严重的问题是事情的分配。 正如@davidb正确指出的那样,因为它只是在任务零上分配内存,所以其他任务没有内存来接收广播。
至于C中的2d分配,你的代码几乎完全正确。 在这段代码中:
array = (float **)malloc(10*sizeof(float)); for(i=0;i<10;i++) array[i] = (float *)malloc(10*sizeof(float));
唯一真正的问题是第一个malloc应该是10个浮点指针 ,而不是浮点数:
array = (float **)malloc(10*sizeof(float *)); for(i=0;i<10;i++) array[i] = (float *)malloc(10*sizeof(float));
@eznme指出了这一点。 第一种方式可能实际上取决于您正在编译/链接的内存模型等,并且几乎肯定会在32位操作系统/机器上工作 - 但仅仅因为它的工作并不总是意味着它是正确的:)
现在,最后一个问题是你在C中声明了一个非常好的2d数组,但这不是MPI所期望的。 当你打这个电话
MPI_Bcast(array,10*10,MPI_FLOAT,0,MPI_COMM_WORLD);
你告诉MPI发送array
指向的100 个连续浮点数。 您注意到库例程无法知道数组是否是指向2d或3d或12d数组的起点的指针,或者各个维度是什么; 它不知道它是否必须遵循指针,如果确实如此,它将不知道要跟随多少。
因此,您希望向100个连续的浮点数发送浮点指针 - 并且以正常的C方式分配伪多维数组(*),您不一定拥有它。 你不一定知道第二行距离这个布局的第一行有多远 - 甚至在哪个方向。 所以你真正想做的是这样的事情:
int malloc2dfloat(float ***array, int n, int m) { /* allocate the n*m contiguous items */ float *p = (float *)malloc(n*m*sizeof(float)); if (!p) return -1; /* allocate the row pointers into the memory */ (*array) = (float **)malloc(n*sizeof(float*)); if (!(*array)) { free(p); return -1; } /* set up the pointers into the contiguous memory */ for (int i=0; i
这样,只有这样,才能保证内存是连续的。 那你可以做
float **array; /* ... */ malloc2dfloat(&array, 10, 10); if (rank == 0) { for(i=0;i<10;i++) for(j=0;j<10;j++) array[i][j]=i+j; } MPI_Bcast(&(array[0][0]), 10*10, MPI_FLOAT, 0, MPI_COMM_WORLD);
请注意,对于任意数据排列,您仍然可以通过定义MPI数据类型来执行Bcast
,该数据类型描述了2d数组如何在内存中实际布局; 但这更简单,更接近你真正想要的东西。
(*)这里真正的问题是C和C派生的语言没有真正的多维数组作为第一类对象 - 这对于系统编程语言来说很好,但在进行科学编程时却无可救药。
数组应为100,而不是10。
array = (float **)malloc(100*sizeof(float));
您可能想要将第一个malloc更改为
malloc(10*sizeof(void*))
因为数组存储指针和存储浮点数而不是整数:
array[i][j]=1.0;
如果你想分配一个10 * 10的数组,你的代码:
array = (float **)malloc(10*sizeof(float))
应该
array = (float **)malloc(10*sizeof(float*))