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);