object - MPI_Gather 对象向量
问题描述
我正在编写一个用于并行排序的 mpich 程序。我需要使用 mpi_gather 接口,但它不支持传递对象向量。所以我使用boost_serialization。
执行
我使用boost_serialization来序列化向量。
std::string serial_str;
boost::iostreams::back_insert_device<std::string> inserter(serial_str);
boost::iostreams::stream<boost::iostreams::back_insert_device<std::string>> s(inserter);
boost::archive::binary_oarchive send_ar(s);
//samples is the vector<object>
send_ar << samples;
s.flush();
int len = serial_str.size();
然后,我使用mpi_gather将所有serial_str发送到根进程(data_recv)。
char *data_recv = NULL;
if(myid == 0){
data_recv = (char*)malloc(sizeof(char) * (len_all+1));
data_recv[len_all] = '\0';
}
MPI_Gather((void*)serial_str.data(), len, MPI_BYTE, data_recv, len, MPI_BYTE, 0, MPI_COMM_WORLD);
最后,我反序列化 data_recv 中的数据。
boost::iostreams::basic_array_source<char> device(data_recv,len_all);
boost::iostreams::stream<boost::iostreams::basic_array_source<char>> s(device);
boost::archive::binary_iarchive recv_ar(s);
std::vector<mdata> recv_vec;
recv_ar >> recv_vec;
我的实现基于How to send a set object in MPI_Send
问题
我无法正确反序列化 data_recv 中的数据。我打印了data_recv,然后我发现data_recv中的数据在mpi_gather之后格式不正确。第二个存档覆盖了第一个。(以粗体标记)
序列化::归档
XylvXe-M X 00000000000000000000000000002595 DDDDFFFFCCCCBBBB111133332222DDDD333388888888FFFF2222 serialization::archive 000000000000000000023D0 EEEE7777EEEE44447777BBBB8888AAAA0000AAAAAAAAFFFF1111
XylvXe-M X 00000000000000000000000000002595 DDDDFFFFCCCCBBBB111133332222DDDD333388888888FFFF2222O@f&!O,tb X 000000000000000000000000000023D0 EEEE7777EEEE44447777BBBB8888AAAA0000AAAAAAAAFFFF1111
正确的格式应该是:(没有重叠,所以我可以反序列化)
序列化::归档
XylvXe-M X 00000000000000000000000000002595 DDDDFFFFCCCCBBBB111133332222DDDD333388888888FFFF2222O@f&!O,tb X 000000000000000000000000000023D0 EEEE7777EEEE44447777BBBB8888AAAA0000AAAAAAAAFFFF1111
序列化::归档
XylvXe-M X 00000000000000000000000000002595 DDDDFFFFCCCCBBBB111133332222DDDD333388888888FFFF2222O@f&!O,tb X 000000000000000000000000000023D0 EEEE7777EEEE44447777BBBB8888AAAA0000AAAAAAAAFFFF1111
问题
为什么会这样?是因为 mpi_gather 与 c++ 对象不兼容吗?如果有人可以帮助我,它将解决我的大问题。谢谢!
代码
//processor rank, and total number of processors
int myid, world_size;
//for timing used by root processor
double startwtime = 0.0, endwtime;
//init MPI World
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
//get the processor name
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name,&name_len);
//read local data
std::vector<mdata> mdatas;
string data_path = "/home/jiang/mpi_data";
readAsciiData(data_path, mdatas);
cout <<"rank: "<<myid <<" mdata_vector.size(): "<<mdatas.size()<<endl;
//local sort according ASCII order
std::sort(mdatas.begin(), mdatas.end());
//regular sample
std::vector<mdata> samples;
for(int i=0; i<mdatas.size(); i=i+mdatas.size()/world_size){
samples.push_back(mdatas[i]);
}
//gather the regular samples
//passing data in byte stream by using boost serialization
std::string serial_str;
boost::iostreams::back_insert_device<std::string> inserter(serial_str);
boost::iostreams::stream<boost::iostreams::back_insert_device<std::string>> s(inserter);
boost::archive::binary_oarchive send_ar(s);
send_ar << samples;
s.flush();
int len = serial_str.size();
//int len = s.str().size();
int *pivot_lens = NULL;
if(myid == 0){
pivot_lens = (int*)malloc(sizeof(int) * world_size);
}
cout <<serial_str <<endl;
//first, gathering the lens and calculate the sum
cout << "rank " << myid << " on "<< processor_name << " is sending len: "<< len << endl;
MPI_Gather(&len, 1, MPI_INT, pivot_lens, 1, MPI_INT, 0, MPI_COMM_WORLD);
//calculate the sum of lens
int len_all = 0;
if(myid == 0){
for(int i=0;i<world_size;i++){
len_all = len_all + pivot_lens[i];
//cout << pivot_lens[i] << endl;
}
cout << "len_all:" << len_all << endl;
free(pivot_lens);
}
//then, gathering string of bytes from all the processes
char *data_recv = NULL;
if(myid == 0){
data_recv = (char*)malloc(sizeof(char) * (len_all+1));
data_recv[len_all] = '\0';
}
MPI_Gather((void*)serial_str.data(), len, MPI_BYTE, data_recv, len, MPI_BYTE, 0, MPI_COMM_WORLD);
// cout << serial_str <<endl;
if(myid == 0){
//deconstructe from byte of string to vector<mdata>
boost::iostreams::basic_array_source<char> device(data_recv,len_all);
boost::iostreams::stream<boost::iostreams::basic_array_source<char>> s(device);
boost::archive::binary_iarchive recv_ar(s);
std::vector<mdata> recv_vec;
recv_ar >> recv_vec;
int count =0;
for(int i=0;i<len_all;i++){
cout<<data_recv[i];
count ++;
}
cout <<endl <<count ;
cout <<endl;
//cout << "rank " << myid << " gets the samples: " << recv_vec.size()<<endl;
iterateForTest(myid, recv_vec);
free(data_recv);
}
MPI_Finalize();
return 0;
解决方案
推荐阅读
- r - 在 Shiny 中获取 R 对象
- ios - 离子自定义字体
- c++ - 在 C++ 中拆分字符串
- maven - Azure Cosmos Java SDK 版本 4.10.0 在尝试连接到数据库时抛出 NoSuchMethodError
- java - json 对象的 JsonPath 返回结果与 json 字符串不同
- c - GNU Linker map:跟踪动态库中符号的来源
- javascript - chrome.tabCapture.capture() 自动静音我的标签声音并且录制的视频没有声音
- android - 安全异常:<
> 从 uid xxx 调用 setPrimaryClip 时不允许执行 READ_CLIPBOARD - php - 如何在没有 jetstream 和 Inertia 的 laravel 8 中安装 vue js?
- sql - 选择查询中不匹配的查询