我想在MPI程序中使用共享数组,这样在一个进程完成其工作后,它会将其排名放入该数组并通过将其发送给其他人而无需等待来“更新”它。我尝试将MPI_Bcast作为“root”参数运行进程的等级(而不是0),但是当我从每个进程显示数组时,它只显示本地发生的更改(发送的其他等级不在数组中)
int array[10];
array[rank] = rank;
MPI_Bcast(array,10,MPI_INT,rank,MPI_COMM_WORLD);
printf("%d, %d - ",array[0],array[1]); //displays: 0, 26872 - 32678, 1
感谢您的帮助。
答案 0 :(得分:2)
在MPI程序的主体中键入int array[10];
不会生成共享阵列。每个进程都处理自己的数组版本。 MPI_Bcast()
被设计为给定进程root
将其数组版本广播到所有其他进程的方式。因此,所有其他进程上的数组的初始版本将被删除。
MPI_Bcast()
是一个集体操作:传播者的每个进程都必须使用相同的MPI_Bcast()
来调用root
。计数和类型可以不同,但根发送的数据量必须等于所有进程接收的数量。
解决问题的两个选项:
MPI_Allgather()
。请参阅these schemes:MPI_Allgather()
可用于在本地进程修改后同步全局数组。全局数组不是“共享”的,因为每个进程在内存中使用不同的空间,但在调用MPI_Allgather()
后,不同进程的值将相似。您正在寻找一个真正的共享数组。可以通过调用MPI_Win_allocate_shared()
来分配这样的数组。请参阅第407页的version 3.1 of the MPI standard,第11.2.3节“分配共享内存的窗口”。特别是,如果使用群集的多个节点运行程序,则必须注意以下警告:
用户有责任确保通信器comm代表一组进程,这些进程可以创建可由组中所有进程访问的共享内存段。
您可以找到MPI_Win_allocate_shared()
there
在下面的示例中,我将假设您对第一个选项感兴趣。它由mpicc main.c -o main
编译并由mpirun -np 42 main
运行。
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
int size, rank;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
int* array=malloc(size*sizeof(int));
if(array==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
//modifying the local portion of the array
array[rank]=rank;
//gather content from each process and broadcast it to all processes
MPI_Allgather(&array[rank],1,MPI_INT,array,1,MPI_INT,MPI_COMM_WORLD);
//each process has its own copy of the array, but the values are the same.
int i,j;
for(i=0;i<size;i++){
if(i==rank){
printf("rank %d got ",rank);
for(j=0;j<size;j++){
printf("%d ",array[j]);
}
printf("\n");
}
MPI_Barrier(MPI_COMM_WORLD);
}
free(array);
MPI_Finalize();
return 0;
}