混合OpenMP / MPI矩阵乘法

时间:2014-04-14 09:50:55

标签: mpi openmp

我想通过传统的方式进行矩阵乘法,这是块,一个产生线程的MPI任务,我的问题是如何定义发送以及何时从OpenMP接收结果。如果任何人能帮助我,即使是简单的样本也会很棒。

1 个答案:

答案 0 :(得分:0)

您可以通过不同的方式解决此问题。一种是将第一个矩阵分解为行组,并将一个组发送到每个等级。从那里,使用OpenMP来并行化乘法。最后,将结果重新组合成单​​个矩阵。使用此方法,您可以使用MPI_Send将组发送到每个等级。假设等级0具有完整矩阵,您将使用类似:

的东西
float A[ndim1*ndim2];
float B[ndim2*ndim3];
float C[ndim1*ndim3];

nrows=ndim1/nranks;

for (int i=1;i++;i<nranks)
{
  startrow=nrows*i;
  nelems=nrows*ndim2;
  if (i==nranks-1)  // Better ways to do this, but this is a simple example
  {
    nelems+=(ndim1%nranks)*ndim2;
  }
  MPI_Send[&A[startrow], nelems, MPI_FLOAT, i, 0, MPI_COMM_WORLD);
}

请注意,这从排名1开始,不需要从排名0发送到自己。但我们也有0级在矩阵的一部分上工作。

要在每个等级中接收,请使用

nelems=nrows*ndim2;
if (myrank==nranks-1)
{
  nelems=(ndim1%nranks)*ndim2;
}
MPI_Recv(localA, nelems, MPI_FLOAT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

您只需要将A的第一个箭头直接复制到localA。您还需要将整个B阵列发送到每个等级以及所需的维度(除非这些值已经来自其他方法)。

一旦所有数据都在每个排名中,使用OpenMP拆分行以一次处理一行。

#pragma omp parallel for private(iA,iB,iC)
for (int i=0;i<localnrows;i++)
{
  for (int j=0;j<ndim3;j++)
  {
    for (int k=0;k<ndim2;k++)
    {
      iA=i*ndim3+k;
      iB=k*ndim2+j;
      iC=i*ndim2+j;
      localC[iC]=localA[iA]*B[iB];
    }
  }
}

然后将localC数组传递回排名0,类似于传递localA的方式,交换MPI_Send和MPI_Recv。