【问题标题】:Sending from all processor to root, using MPI_Send and MPI_Recv.使用 MPI_Send 和 MPI_Recv 从所有处理器发送到根。
【发布时间】:2018-09-10 01:29:57
【问题描述】:

我无法从所有处理器收集一些数据到根目录,这是我想要做的一个示例:

我在每个处理器中有几对(实际上它们是边缘),理想情况下希望将它们发送到根,或者如果我无法发送它们对应的索引(一个数字而不是对。

例如:

Processor 0: sends {(0,5), (1,6)} to root, or it sould send {5,17}
Processor 1: sends {(2,3)} to root, or it sould send {14}
Processor 2: sends {} to root, or it sould send {}
Processor 3: sends {(4,0)} to root, or it sould send {20}

我想知道存储对或数字并发送和接收它们的最佳方式是什么。理想情况下,我更喜欢将它们存储在二维向量中,因为从一开始我不知道我需要多少空间,然后在二维向量中再次接收它们。我知道这可能不可能或可能非常复杂。

这是我正在寻找但不知道如何在 MPI 中实现的过程的伪代码。

vector<vector<int > >allSelectedEdges;
vector<vector<int > >selectedEdgesLocal; 
int edgeCount=0;   
if(my_rank!=0){                          
        for(int i = 0; i < rows; ++i)
            for(int j = 0; j < nVertex; ++j)
                if (some conditions)
                {
                    vector<int> tempEdge;
                    tempEdge.push_back(displs[my_rank]+i);
                    tempEdge.push_back(j);
                    selectedEdgesLocal.push_back(tempEdge);
                    edgeCount++;
                }
        }
        "send selectedEdgesLocal to root"
}else
{
      "root recieve sselectedEdgesLocal and store in allSelectedEdges"
}

我也考虑过 MPI_Gatherv,但似乎没有帮助。从here得到这个想法

vector<vector<int > >selectedEdgesLocal; 
int edgeCount=0;                            
for(int i = 0; i < rows; ++i)
    for(int j = 0; j < nVertex; ++j)
        if (some conditions)
        {
            vector<int> tempEdge;
            tempEdge.push_back(displs[my_rank]+i);
            tempEdge.push_back(j);
            selectedEdgesLocal.push_back(tempEdge);
            edgeCount++;
         }
int NumdgesToAdd;
MPI_Reduce(&edgeCount, &NumdgesToAdd, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

vector<vector<int > > allSelectedEdges(NumdgesToAdd);

int rcounts[comm_size];
int rdisp[comm_size];
int sumE=0;
for(int i=0; i<comm_size; ++i) {
    rcounts[i] = edgeCount;
    rdisp[i]=sumE;
    sumE+=edgeCount;
}

MPI_Gatherv(&selectedEdgesLocal.front(), rcounts[my_rank], MPI_INT, &allSelectedEdges.front(), rcounts, rdisp, MPI_INT, 0, MPI_COMM_WORLD);

【问题讨论】:

  • 你首先需要收集所有的root rank上的edgeCount,然后你可以分配allSelectedEdges并构建rcountsrdisp
  • 您知道要从每个进程发送到根的最大值计数吗?例如,是“最多 2 个”还是“最多 10 个”,还是不限数量?
  • @JohnZwinck 每个处理器都有一些行矩阵(图),计数可以达到每个处理器中的项目数。
  • @GillesGouaillardet 你的意思类似于我解释的第二个解决方案?为什么根排名应该知道所有 edgeCount?
  • rcountsrdisp 仅与根级别相关,因此由于每个级别都有自己的edgeCount,因此根级别应该知道所有这些。

标签: c++ mpi distributed-computing sendmessage 2d-vector


【解决方案1】:

您应该为此使用 Gather。问题是每个进程都有不同数量的值要发送到根。因此,您可以确定要发送的最大值数,并让每个进程发送那么多值(例如,未使用的值是 NAN),或者按照 Gilles Gouaillardet 在评论中建议的操作,并使用两个步骤:

  1. 让每个进程计算它需要发送的值的数量。将这些计数作为rcounts 收集到根目录。
  2. 使用 Gather 收集值——现在根进程知道rcounts,它可以轻松地将rdisp 计算为rcounts 的累积和。

“使用固定的最大数量的值并用 NAN 填充未使用的插槽”更简单,并且在数据总量较小的情况下效果很好。如果数据总量很大,每个进程发送的值的数量差异很大,那么两步法可能效率更高。

【讨论】:

  • 注意你可以直接MPI_Gather(..., recvbuf=rcounts, ...),所以根秩只需要计算rdisp
【解决方案2】:

我更新我的代码如下,它现在可以工作了。

vector <int> selectedEdgesIndicesLocal;

    int edgeCount=0;
    for(int i = 0; i < rows; ++i)
        for(int j = 0; j < nVertex; ++j)
            if (some condistions)
            {
                int index=...;
                selectedEdgesIndicesLocal.push_back(index);
                edgeCount++;
            }

    int NumEdgesToAdd;
    MPI_Reduce(&edgeCount, &NumEdgesToAdd, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

    int *edgeCountsInRoot;
    if (my_rank == 0)edgeCountsInRoot = (int *)malloc(comm_size * sizeof(int));
    MPI_Gather(&edgeCount, 1, MPI_INT, edgeCountsInRoot, 1, MPI_INT, 0,MPI_COMM_WORLD);

    int *allSelectedIndicesEdges;
    if (my_rank == 0)allSelectedIndicesEdges = (int *)malloc(NumEdgesToAdd * sizeof(int));

    int * edgeCounts, *edgeDisp;

    cout<<edgeCount<<endl;
    if (my_rank==0) {
        edgeCounts= (int *)malloc(comm_size * sizeof(int));
        edgeDisp= (int *)malloc(comm_size * sizeof(int));
        int edgeSum=0;
        for(int i=0; i<comm_size; ++i) {
            edgeCounts[i] = edgeCountsInRoot[i];
            edgeDisp[i]=edgeSum;
            edgeSum+=edgeCountsInRoot[i];
        }
    }
    MPI_Gatherv(&selectedEdgesIndicesLocal.front(), edgeCount, MPI_INT, &allSelectedIndicesEdges[0], edgeCounts,edgeDisp, MPI_INT, 0, MPI_COMM_WORLD);

【讨论】:

    猜你喜欢
    • 2015-05-18
    • 2018-09-11
    • 2011-11-11
    • 2016-09-02
    • 1970-01-01
    • 2014-04-17
    • 2011-01-24
    • 1970-01-01
    • 2020-03-23
    相关资源
    最近更新 更多