【问题标题】:how to make MPI_Send have processors send in order instead of randomly?如何让 MPI_Send 让处理器按顺序发送而不是随机发送?
【发布时间】:2015-06-20 16:07:23
【问题描述】:

我正在尝试在下面运行一个使用并行编程的程序。如果我们使用 4 个处理器,我希望它们包含总和 1+2=3、3+4=7、11 和 15。所以我希望 sumvector 按顺序包含 3、7、11 和 15。但是,由于 MPI_Send 的处理器以随机顺序发送,因此我不会将 sumvector 包含,例如 7、15、3、11。如何修改下面的代码以确保这一点?

#include<iostream>
#include<mpi.h>


using namespace std;

int main(int argc, char *argv[]){

    int mynode, totalnodes;
    int sum,startval,endval,accum;
    MPI_Status status;
    int master=3; 

    MPI_Init(&argc,&argv);
    MPI_Comm_size(MPI_COMM_WORLD, &totalnodes); // get totalnodes
    MPI_Comm_rank(MPI_COMM_WORLD, &mynode); // get mynode

    sum = 0; // zero sum for accumulation
    vector <int> sumvector;
    startval = 8*mynode/totalnodes+1;
    endval = 8*(mynode+1)/totalnodes;

    for(int i=startval;i<=endval;i=i+1)
        sum=sum+i;
        sumvector.push_back(sum);

    if(mynode!=master)
    {
        MPI_Send(&sum,1,MPI_INT,master,1,MPI_COMM_WORLD); //#9, p.92
    }
    else
    {
        for(int j=0;j<totalnodes;j=j+1){
            if (j!=master)
            {
                MPI_Recv(&accum,1,MPI_INT,j,1,MPI_COMM_WORLD, &status);
                printf("processor %d  received from %d\n",mynode, j);
                sum = sum + accum;
            }
        }
    }

使用多线程而不是 MPI 会更好吗?

【问题讨论】:

  • 您缺少一堆包含。并且函数声明必须在使用之前可用。
  • 当您发出完成计算的请求时,请包含您希望存放输出的位置。当它发送回复时,让它包含位置。当您收到回复时,不要只是将结果放在下一个可用的位置——将它放在回复中说它应该去的位置。

标签: c++ multithreading parallel-processing mpi


【解决方案1】:

我不确定您想做什么,但您当前的代码与以下代码等效(不打印从哪个等级收到的数字):

for(int i=startval;i<=endval;i=i+1)
    sum=sum+i;
sumvector.push_back(sum);

MPI_Reduce(mynode == master ? MPI_IN_PLACE : &sum, &sum, 1, MPI_INT,
           master, MPI_COMM_WORLD);

你要找的要么是这个(结果只由大师等级收集):

for(int i=startval;i<=endval;i=i+1)
    sum=sum+i;

sumvector.resize(totalnodes);

MPI_Gather(&sum, 1, MPI_INT, &sumvector[0], 1, MPI_INT,
           master, MPI_COMM_WORLD);

或者这个(结果被收集到所有等级):

for(int i=startval;i<=endval;i=i+1)
    sum=sum+i;

sumvector.resize(totalnodes);

MPI_Allgather(&sum, 1, MPI_INT, &sumvector[0], 1, MPI_INT, MPI_COMM_WORLD);

另外,下面的说法是完全错误的:

然而,由于 MPI_Send 的处理器以随机顺序发送,所以我不使用 sumvector 来包含 7、15、3、11。

MPI 点对点通信需要两件事才能成功:必须有一个执行MPI_Send发送方一个接收方 执行匹配的MPI_Recv。消息接收顺序可以通过简单地在循环中调用MPI_Recv 来强制执行,源排名增加,与您显示的代码完全相同。

【讨论】:

    【解决方案2】:

    有很多方法可以让您更简单地做到这一点。首先,您可以将值“收集”到主进程上的向量中:

    std::vector <int> sumvector, recvcounts, displs;
    startval = 8*mynode/totalnodes+1;
    endval = 8*(mynode+1)/totalnodes;
    
    for (int i=0; i<totalnodes; i++)
    {
        sumvector.push_back(0);
        recvcounts.push_back(1);
        displs.push_back(i);
    }
    
    int myval = startval + endval;
    MPI_Gatherv(&myval,
                1,
                MPI_INTEGER,
                &sumvector[0],
                &recvcounts[0],
                &displs[0],
                MPI_INTEGER,
                master,
                MPI_COMM_WORLD);
    

    这导致 sumvector 包含:

    node 0: (0, 0, 0, 0)
    node 1: (0, 0, 0, 0)
    node 2: (0, 0, 0, 0)
    node 3: (3, 7, 11, 15)
    

    您也可以考虑使用 MPI_Allreduce。流程如下:

    将所有向量元素初始化为0,

    for (int i=0; i<totalnodes; i++)
    {
        sumvector.push_back(0);
    }
    

    并将 mynode 的条目修改为您想要的值,

    sumvector[mynode] = startval + endval;
    

    在 MPI_Allreduce 之前,和向量包含:

    node 0: (3, 0, 0, 0)
    node 1: (0, 7, 0, 0)
    node 2: (0, 0, 11, 0)
    node 3: (0, 0, 0, 15)
    

    现在,当你对每个节点上的所有数组求和时,

    MPI_Allreduce(MPI_IN_PLACE, 
                  &sumvector[0], 
                  totalnodes, 
                  MPI_INTEGER, 
                  MPI_SUM, 
                  MPI_COMM_WORLD);
    

    它导致 sumvector 包含:

    node 0: (3, 7, 11, 15)
    node 1: (3, 7, 11, 15)
    node 2: (3, 7, 11, 15)
    node 3: (3, 7, 11, 15)
    

    在每个节点上。

    【讨论】:

    • 您为什么要使用带有多余零的 reduce-to-all 来重新实现“gather-to-all”操作?
    • 对我来说,就执行求和的位置而言,原始发帖人希望做什么并不完全清楚:即是在本地还是跨进程。我想用我的答案来涵盖这两个基础,但是,是的,当然可以在没有 reduce-to-all 的情况下实现预期的输出。
    猜你喜欢
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 2020-05-13
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 2023-03-30
    相关资源
    最近更新 更多