在 MPI_Reduce 中传递和推入向量
Passing and pushing into a vector in MPI_Reduce
我需要缩减节点从其他节点获取元素列表的副本(存储在向量中)。我定义了自己的还原函数,但它不起作用。节目terminates/crashes。
这是代码:
#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 传递向量。 MPI 的作用是获取第一个指针并将其解释为 INT 类型和定义长度的数据块。请思考 vector 是如何实现的。 vector 本身只是一个小的控制结构,指向堆上的某个数组。因此,传递 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;
}
您似乎想从所有进程中收集所有元素。这不是缩减,而是聚集操作。缩减将多个相同长度的数组合并为一个特定长度的数组:
情况并非如此,当组合两个数组时会产生一个长度等于输入数组之和的数组。使用 MPI,您不能像在缩减操作中那样简单地使用指针进行操作。您不能使用 MPI 发送指针,因为进程有单独的地址 space。 MPI 接口确实使用指针,但仅使用包含已知类型和已知大小的数据区域。
您可以使用 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);
我需要缩减节点从其他节点获取元素列表的副本(存储在向量中)。我定义了自己的还原函数,但它不起作用。节目terminates/crashes。
这是代码:
#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 传递向量。 MPI 的作用是获取第一个指针并将其解释为 INT 类型和定义长度的数据块。请思考 vector 是如何实现的。 vector 本身只是一个小的控制结构,指向堆上的某个数组。因此,传递 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;
}
您似乎想从所有进程中收集所有元素。这不是缩减,而是聚集操作。缩减将多个相同长度的数组合并为一个特定长度的数组:
情况并非如此,当组合两个数组时会产生一个长度等于输入数组之和的数组。使用 MPI,您不能像在缩减操作中那样简单地使用指针进行操作。您不能使用 MPI 发送指针,因为进程有单独的地址 space。 MPI 接口确实使用指针,但仅使用包含已知类型和已知大小的数据区域。
您可以使用 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);