传递并推入MPI_Reduce中的向量

时间:2017-07-14 11:48:12

标签: c++ mpi ms-mpi

我需要reduce节点从其他节点获取元素列表(存储在向量中)的副本。我定义了自己的缩减功能,但它不起作用。程序终止/崩溃。

这是代码:

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

using namespace std;

void pushTheElem(vector<int>* in, vector<int>* inout, int *len, MPI_Datatype *datatype)
{
    vector<int>::iterator it;
    for (it = in->begin(); it < in->end(); it++)
    {
        inout->push_back(*it);
    }
}

int main(int argc, char **argv)
{
    int numOfProc, procID;
    vector<int> vect, finalVect;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &numOfProc);
    MPI_Comm_rank(MPI_COMM_WORLD, &procID);

    MPI_Op myOp;
    MPI_Op_create((MPI_User_function*)pushTheElem, true, &myOp);

    for (int i = 0; i < 5; i++)
    {
        vect.push_back(procID);
    }

    MPI_Reduce(&vect, &finalVect, 5, MPI_INT, myOp, 0, MPI_COMM_WORLD);

    if (procID == 0)
    {
        vector<int>::iterator it;
        cout << "Final vector elements: " << endl;

        for (it = finalVect.begin(); it < finalVect.end(); it++)
            cout << *it << endl;
    }

    MPI_Finalize();
    return 0;
}

2 个答案:

答案 0 :(得分:4)

您似乎想收集所有流程中的所有元素。这是不是减少,它是一个聚集操作。缩减将相同长度的多个数组组合成这个特定长度的数组:

MPI_Reduce

情况并非如此,当组合两个数组时,会产生一个长度等于输入数组之和的数组。使用MPI,您不能简单地使用指针操作,就像您尝试在缩小操作中一样。您无法使用MPI发送指针,因为进程具有单独的地址空间。 MPI接口确实使用指针,但只使用包含已知类型和已知大小的数据区域。

您可以使用MPI_Gather轻松完成任务。

MPI_Gather

// vect.size() must be the same on every process, otherwise use MPI_Gatherv
// finalVect is only needed on the root.
if (procID == 0) finalVect.resize(numOfProc * vect.size());
MPI_Gather(vect.data(), 5, MPI_INT, finalVect.data(), 5, MPI_INT, 0, MPI_COMM_WORLD);

答案 1 :(得分:1)

我认为你不能用这种方式使用MPI传递向量。 MPI做了什么它需要第一个指针并将其解释为INT类型的数据blob和定义的长度。请考虑如何实现矢量。向量本身只是一个小的控制结构,指向堆上的某个数组。所以传递vector *你没有提供指向数据的指针,而是提供给这个控制结构,当你的程序试图将它用作向量时,它会导致未定义的行为。

您需要使用MPI操作原始数据。试试这个(没有测试,因为我手头没有MPI):

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

using namespace std;

void pushTheElem(int* in, int* inout, int *len, MPI_Datatype *datatype)
{
    for(inti=0;i<*len;++i){
      inout[i]=in[i];
    }
}

int main(int argc, char **argv)
{
    int numOfProc, procID;
    vector<int> vect, finalVect;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &numOfProc);
    MPI_Comm_rank(MPI_COMM_WORLD, &procID);

    MPI_Op myOp;
    MPI_Op_create((MPI_User_function*)pushTheElem, true, &myOp);

    for (int i = 0; i < 5; i++)
    {
        vect.push_back(procID);
    }
    finalVect.resize(vect.size());
    MPI_Reduce(vect.data(), finalVect.data(), 5, MPI_INT, myOp, 0, MPI_COMM_WORLD);

    if (procID == 0)
    {
        vector<int>::iterator it;
        cout << "Final vector elements: " << endl;

        for (it = finalVect.begin(); it < finalVect.end(); it++)
            cout << *it << endl;
    }

    MPI_Finalize();
    return 0;
}