C++ 如何发送和接收可变长度(取决于处理器)std::vector<;myStruct>;使用MPI
每个处理器上都有一个自定义结构向量。这些向量都是不同大小的。我正在努力从处理器0上的处理器1到N接收数据 我已尝试实施所附幻灯片第31-33页上的建议,其中发送和接收std::vector。我还实现了MPI_注册和MPI_注销 我正在osx上编译和运行这段代码C++ 如何发送和接收可变长度(取决于处理器)std::vector<;myStruct>;使用MPI,c++,struct,mpi,stdvector,C++,Struct,Mpi,Stdvector,每个处理器上都有一个自定义结构向量。这些向量都是不同大小的。我正在努力从处理器0上的处理器1到N接收数据 我已尝试实施所附幻灯片第31-33页上的建议,其中发送和接收std::vector。我还实现了MPI_注册和MPI_注销 我正在osx上编译和运行这段代码 #包括 #包括 #包括 #包括 #包括 #包括 结构蟹爪 { 蟹爪():com(),number(),weight(),crossing_count(),com0_id(){} ///////// 蟹爪( 向量c, int n, 双w,
#包括
#包括
#包括
#包括
#包括
#包括
结构蟹爪
{
蟹爪():com(),number(),weight(),crossing_count(),com0_id(){}
/////////
蟹爪(
向量c,
int n,
双w,
std::矢量cc,
整数id
):com(c)、数字(n)、重量(w)、交叉计数(cc)、com0_id(id){}
std::vector com=std::vector(3);
整数;
双倍重量;
标准::向量交叉计数=标准::向量(3);
int com0_id;
};
MPI\u数据类型寄存器\u MPI\u类型(蟹爪)//常量&)
{
constexpr std::size\t num\u members=5;
整数长度[num_成员]={3,1,1,3,1};
MPI维护偏移量[成员数]={
偏移量(蟹爪,com),//矢量(双倍)
偏移量(蟹爪,数字),//int
偏移量(蟹爪,重量),//双
偏移量(蟹爪,交叉计数),//向量(双精度)
偏移量(蟹爪,com0\U id)//int
};
MPI_数据类型[num_members]={MPI_DOUBLE,MPI_INT,MPI_DOUBLE,MPI_DOUBLE,MPI_INT};
MPI_数据类型;
MPI类型结构(成员数、长度、偏移量、类型和类型);
MPI_类型_提交(&Type);
返回类型;
}
作废注销器\u mpi\u类型(mpi\u数据类型)
{
无MPI类型(类型和类型);
}
int main(
int argc,
字符*argv[]
)
{
MPI_Init(&argc,&argv);
int mpi处理器;mpi通信大小(mpi通信世界和mpi处理器);
int mpi_my_id;mpi_Comm_rank(mpi_Comm_WORLD和mpi_my_id);
常量int mpi_主id=0;
向量h;双j=mpi\u my\u id;
对于(int i=0;i<(2*mpi_my_id+1);+i)
{
螃蟹爪h_1;
标准:向量h_-com(3,0.);
h_com[0]=((i+1)/20.*2*j)/(i+1);
h_com[1]=((i+1)/20.*2*j)/(i+1);
h_com[2]=((i+1)/20.*2*j)/(i+1);
j/=0.5;
标准:向量交叉计数(3,0);
h_1.com=h_com;
h_1.number=i*mpi_my_id+1;
h_1.重量=j*0.3;
h_1.交叉计数=交叉计数;
h_1.com0_id=mpi_my_id;
h、 推回(h_1);
}
MPI_屏障(MPI_通信世界);
/*为struct crab_claw创建一个类型*/
std::载体存储;
MPI_数据类型=寄存器_MPI_类型(h[0]);
如果(mpi\U我的\U id!=mpi\U主\U id)
{
int tag=mpi\u my\u id;
无符号长度=h.size();
const int destination=mpi_master_id;
MPI_发送(
&长度,
1.
MPI_未签名,
目的地,
标记+mpi处理器,
MPI_通讯世界
);
如果(长度!=0)
{
MPI_发送(
h、 数据(),
长度,
类型,
目的地,
mpi_我的id,
MPI_通讯世界
);
}
}
MPI_屏障(MPI_通信世界);
如果(mpi\U我的\U id==mpi\U主\U id)
{
对于(int j=0;j STD::尽管对MPI了解不多,但是这里显然有一个非常基本的误解:C++向量是什么,以及它们是如何工作的。不能不注意到,<代码>偏移量< /C> >对于<代码> STD::向量< /代码>以及一个普通的<代码>双< /代码>,完全是相同的。这是不对的。在<代码> STD::vector重复>,我不重复,在向量本身是“代码>结构代码< /代码>的一部分时,我不重复告诉你向量的实际值。C++没有这样的工作。这看起来是一个C C++库,没有关于C++类的线索,它们是如何工作的,它们是什么。嗨,山姆,我很感激你的回答。我确实是新T。o偏移量。但是在MPI和附加链接中,它被强调(我相信)偏移量指的是容器中元素的数量,这是我认为应该正确处理的。数组可能会解决问题,因为向量指向数组,并且在结构中传递向量会将指针埋得更深一层吗?如果您对我的无知/无能有其他评论的话关于我的代码结构到底有什么错误,我将不胜感激。@samvarshavchikt“附加链接”告诉您需要对std::vector
s执行什么操作。这与您在所示代码中执行的操作不同。您是否看到代码中的std::vector
s与链接中名为“处理std::vector”的一章之间的联系?您认为这两者之间可能有联系吗?所示代码的哪一部分实现了“附加链接”中该章中给出的说明?您似乎忽略了嵌套std::vector
对象的意义。您不能将std::vector
策略用于std::vector
,而std::vector
本身就很重要。在这种情况下,嵌套结构com
和交叉计数
似乎是硬编码的长度3,例如在寄存器中_
#include <mpi.h>
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <cstddef>
struct crab_claw
{
crab_claw() : com(), number(), weight(), crossing_count(), com0_id() {}
/////////
crab_claw(
std::vector<double> c,
int n,
double w,
std::vector<double> cc,
int id
) : com( c ), number( n ), weight( w ), crossing_count( cc ), com0_id( id ) {}
std::vector<double> com = std::vector<double>(3);
int number;
double weight;
std::vector<double> crossing_count = std::vector<double>(3);
int com0_id;
};
MPI_Datatype register_mpi_type(crab_claw)// const&)
{
constexpr std::size_t num_members = 5;
int lengths[num_members] = {3,1,1,3,1};
MPI_Aint offsets[num_members] = {
offsetof(crab_claw, com), //vector (of doubles)
offsetof(crab_claw, number), //int
offsetof(crab_claw, weight), //double
offsetof(crab_claw, crossing_count), //vector (of doubles)
offsetof(crab_claw, com0_id) //int
};
MPI_Datatype types[num_members] = { MPI_DOUBLE, MPI_INT, MPI_DOUBLE, MPI_DOUBLE, MPI_INT };
MPI_Datatype type;
MPI_Type_struct(num_members, lengths, offsets, types, &type);
MPI_Type_commit(&type);
return type;
}
void deregister_mpi_type(MPI_Datatype type)
{
MPI_Type_free(&type);
}
int main(
int argc,
char* argv[]
)
{
MPI_Init(&argc, &argv);
int mpi_nprocessors; MPI_Comm_size(MPI_COMM_WORLD, &mpi_nprocessors);
int mpi_my_id; MPI_Comm_rank(MPI_COMM_WORLD, &mpi_my_id);
const int mpi_master_id = 0;
std::vector<crab_claw> h; double j = mpi_my_id;
for(int i = 0; i < (2*mpi_my_id+1); ++i)
{
crab_claw h_1;
std::vector<double> h_com(3,0.);
h_com[0] = ((i+1)/20. * 2*j)/(i+1);
h_com[1] = ((i+1)/20. * 2*j)/(i+1);
h_com[2] = ((i+1)/20. * 2*j)/(i+1);
j /= 0.5;
std::vector<double> crossing_count(3,0.);
h_1.com = h_com;
h_1.number = i*mpi_my_id+1;
h_1.weight = j*0.3;
h_1.crossing_count = crossing_count;
h_1.com0_id = mpi_my_id;
h.push_back(h_1);
}
MPI_Barrier(MPI_COMM_WORLD);
/* create a type for struct crab_claw */
std::vector<crab_claw> storage;
MPI_Datatype type = register_mpi_type(h[0]);
if (mpi_my_id != mpi_master_id)
{
int tag = mpi_my_id;
unsigned length = h.size();
const int destination = mpi_master_id;
MPI_Send(
&length,
1,
MPI_UNSIGNED,
destination,
tag+mpi_nprocessors,
MPI_COMM_WORLD
);
if(length != 0)
{
MPI_Send(
h.data(),
length,
type,
destination,
mpi_my_id,
MPI_COMM_WORLD
);
}
}
MPI_Barrier(MPI_COMM_WORLD);
if (mpi_my_id == mpi_master_id)
{
for(int j = 0; j < mpi_nprocessors; ++j)
{
if(j == 0)
{
storage.insert(storage.end(), h.begin(), h.end());
std::cout << "inert insert" << '\n';
}
if(j > 0)
{
unsigned length;
MPI_Status s;
MPI_Recv(
&length,
1,
MPI_UNSIGNED,
j,
j+mpi_nprocessors,
MPI_COMM_WORLD,
&s
);
std::vector<crab_claw> rec;
//std::cout << "MPIMYID " << mpi_my_id << " LENGTH OF RECEIVED OBJ " << length << " j " << j << '\n';
if (length != 0)
{
h.resize(length);
MPI_Recv(
h.data(),
length,
type,
j,
j,
MPI_COMM_WORLD,
&s
);
std::cout << "SIZE() " << h.size() << " MY MPI ID " << mpi_my_id << " h[0].number " << h[0].weight << '\n';
//storage.insert(storage.end(), h.begin(), h.end());
} else
{
h.clear();
}
}
}
}
//std::cout << mpi_my_id << '\n';
MPI_Finalize();
return 0;
}