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