如何在MPI中使用共享的全局数据集?

时间:2013-09-21 20:36:38

标签: c++ openmpi

我是MPI的初学者。我有一个大数组gmat的数字(类型为double,尺寸为1x14000000),它是预先计算并存储在二进制文件中的。它将在内存中使用大约100 MB(14000000 x8字节/ 1024/1024)。我想写一个MPI代码,它将对这个数组进行一些计算(例如,将gmat的所有元素乘以进程的等级数)。此数组gmat本身在运行时保持不变。 代码应该是这样的

#include <iostream>
#include "mpi.h"
double* gmat;
long int imax;

int main(int argc, char* argv[])
{
void performcomputation(int rank); // this function performs the computation and will be called by all processes

imax=atoi(argv[1]); // user inputs the length of gmat 

MPI::Init();
rank = MPI::COMM_WORLD.Get_rank();
size = MPI::COMM_WORLD.Get_size(); //i will use -np 16 = 4 processors x 4 cores

if rank==0 // read the gmat array using one of the processes
{
gmat = new double[imax];
// read values of gmat from a file
// next line is supposed to broadcast values of gmat to all processes which will use it
MPI::COMM_WORLD.Bcast(&gmat,imax,MPI::DOUBLE,1);     
}

MPI::COMM_WORLD.Barrier();
performcomputation(rank);  
MPI::Finalize();  

return 0;
} 

void performcomputation(int rank)
{
int i;
for (i=0;i <imax; i++)
cout << "the new value is" << gmat[i]*rank << endl; 
}    

我的问题是当我使用16个进程(-np 16)运行此代码时,所有这些进程的gmat是否相同?我的意思是,代码是否会在内存中使用16 x 100 MB来存储每个进程的gmat,还是只使用100 MB,因为我已经将gmat定义为全局?我不希望不同的进程分别从文件中读取gmat,因为读取这么多数字需要时间。有什么更好的方法呢?感谢。

1 个答案:

答案 0 :(得分:1)

首先,请不要使用MPI C ++绑定。这些在MPI-2.2中被弃用,然后在MPI-3.0中被删除,因此不再是规范的一部分,这意味着未来的MPI实现甚至不需要提供C ++绑定,如果他们这样做,它们可能会以界面的方式发散。

那就是说,你的代码包含一个非常常见的错误:

if rank==0 // read the gmat array using one of the processes
{
   gmat = new double[imax];
   // read values of gmat from a file
   // next line is supposed to broadcast values of gmat to all processes which will use it
   MPI::COMM_WORLD.Bcast(&gmat,imax,MPI::DOUBLE,1);     
}

这不起作用,因为这里有四个错误。首先,gmat仅在0级分配,而在其他级别中未分配,这不是您想要的。其次,您给Bcast指针gmat的地址而不是它所指向的数据的地址(即您不应该使用&运算符)。您还从排名0广播,但将1作为广播根参数。但最重要的错误是MPI_BCAST是一个集体通信调用,所有排名需要使用相同的root参数值来调用它才能完成成功。正确的代码(使用C绑定而不是C ++绑定)是:

gmat = new double[imax];

if (rank == 0)
{
   // read values of gmat from a file
}
MPI_Bcast(gmat, imax, MPI_DOUBLE, 0, MPI_COMM_WORLD);
//        ^^^^                   ^^^
//        no &                root == 0

每个排名都有自己的gmat副本。最初所有值都不同(例如,随机或全零,取决于内存分配器)。在广播之后,所有副本将与等级0的gmat副本相同。在调用performcomputation()后,每个副本将再次不同,因为每个等级将gmat的元素与不同的号码。您的问题的答案是:代码将在每个等级中使用100 MiB,因此总共16 x 100 MiB。

MPI处理分布式内存 - 进程不共享变量,无论它们是本地变量还是全局变量。共享数据的唯一方法是使用MPI调用,如点对点通信(例如MPI_SEND / MPI_RECV),集体调用(例如MPI_BCAST)或单方面通信(例如MPI_PUT / MPI_GET)。