C++ 在MPI_Reduce中传递并推入向量

C++ 在MPI_Reduce中传递并推入向量,c++,mpi,ms-mpi,C++,Mpi,Ms Mpi,我需要缩减节点从其他节点获取元素列表(存储在向量中)的副本。我定义了自己的归约函数,但它不起作用。程序终止/崩溃 代码如下: #include <iostream> #include "mpi.h" #include <vector> using namespace std; void pushTheElem(vector<int>* in, vector<int>* inout, int *len, MPI_Datatype *datatyp

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

代码如下:

#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;
}
#包括
#包括“mpi.h”
#包括
使用名称空间std;
void pushTheElem(向量*in,向量*inout,int*len,MPI_数据类型*数据类型)
{
向量::迭代器;
对于(it=in->begin();itend();it++)
{
inout->推回(*it);
}
}
int main(int argc,字符**argv)
{
int numoproc,procID;
向量向量,最终向量;
MPI_Init(&argc,&argv);
MPI通信大小(MPI通信世界和numOfProc);
MPI通信等级(MPI通信世界和procID);
MPI_Op myOp;
MPI_Op_create((MPI_User_函数*)pushTheElem、true和myOp);
对于(int i=0;i<5;i++)
{
向量推回(procID);
}
MPI_Reduce(矢量、最终、5、MPI_INT、myOp、0、MPI_COMM_WORLD);
如果(procID==0)
{
向量::迭代器;

cout我不认为可以用MPI这种方式传递向量。MPI做什么?它使用第一个指针并将其解释为INT类型和定义长度的数据块。请想想向量是如何实现的。向量本身只是一个指向堆上某个数组的小控制结构。因此,传递向量*并不提供p指向数据,但指向此控制结构,当程序尝试将其用作向量时,这将导致未定义的行为

您需要使用MPI对原始数据进行操作。请尝试以下操作(由于我手头没有MPI,因此未测试):

#包括
#包括“mpi.h”
#包括
使用名称空间std;
void pushTheElem(int*in,int*inout,int*len,MPI_数据类型*数据类型)
{

对于(inti=0;i我不认为可以用MPI这种方式传递向量。MPI是做什么的?它使用第一个指针并将其解释为INT类型和定义长度的数据块。请想想向量是如何实现的。向量本身只是一个指向堆上某个数组的小控制结构。所以传递向量*不提供指针指向数据,但指向此控制结构,当程序试图将其用作向量时,这会导致未定义的行为

您需要使用MPI对原始数据进行操作。请尝试以下操作(由于我手头没有MPI,因此未测试):

#包括
#包括“mpi.h”
#包括
使用名称空间std;
void pushTheElem(int*in,int*inout,int*len,MPI_数据类型*数据类型)
{

对于(inti=0;i,您似乎希望收集所有进程中的所有元素。这不是一个缩减,而是一个聚集操作。缩减将相同长度的多个数组组合为一个特定长度的数组:

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

您可以使用
MPI\u-Gather
轻松完成任务


您似乎希望收集所有进程中的所有元素。这不是缩减,而是一个聚集操作。缩减将相同长度的多个数组合并为此特定长度的数组:

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

您可以使用
MPI\u-Gather
轻松完成任务


请提供有关崩溃的更多详细信息。至少应该发生某种异常…程序的输出是什么?这是我得到的:作业中止:[ranks]消息。[0]进程在未调用finalize的情况下退出。[1]终止。---错误分析------testMPI.exe过早结束,可能已崩溃。退出代码0xc0000005。我在用2个进程运行程序时得到了该代码。首先,您需要在列组上初始化finalVect0@GillesGouaillardet谢谢你的评论。下面由K.Kirsz编辑的代码有效,但有一个问题是我作为通信员写的下面是他的代码。请看一看。请提供有关崩溃的更多详细信息。应该至少发生了某种异常…程序的输出是什么?这是我得到的:作业中止:[ranks]消息。[0]进程在未调用finalize的情况下退出。[1]终止。---错误分析------testMPI.exe过早结束,可能已崩溃。退出代码0xc0000005。我在用2个进程运行程序时得到了该代码。首先,您需要在列组上初始化finalVect0@GillesGouaillardet谢谢你的评论。下面由K.Kirsz编辑的代码有效,但有一个问题是我作为通信员写的下面是他的代码。你能看一下吗。非常感谢,现在我了解了它的工作原理。代码不会产生任何错误。唯一的问题是finalVect将始终只包含从上一个处理过程中获得的元素。pushTheElem中的循环覆盖finalVect中已有的内容。@Jack exp是什么ected行为?如果使用2个MPI任务运行,您能指定FinalEvent中的预期值吗?我基本上希望输出包含从两个进程收集的元素。@Zulan向我澄清,我应该使用的是MPI_Gather,它为我提供了正确的输出。谢谢。非常感谢,现在我了解了它的工作原理。代码确实如此不会产生任何错误。唯一的问题是finalVect始终只包含从fr获得的元素
#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;
}
// 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);