C++ 中的 MPI_Send MPI_Recv 段错误
Posted
技术标签:
【中文标题】C++ 中的 MPI_Send MPI_Recv 段错误【英文标题】:MPI_Send MPI_Recv segfault in C++ 【发布时间】:2013-12-31 20:43:36 【问题描述】:我用 MPI 编写了一个简单的程序,它在处理器之间发送和接收消息,但运行时出现分段错误。
这是我的全部代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <strings.h>
#include <sstream>
#include<mpi.h>
using namespace std;
class Case
public:
int value;
std::stringstream sta;
;
int main(int argc, char **argv)
int rank,size;
MPI::Init(argc,argv);
rank=MPI::COMM_WORLD.Get_rank();
size=MPI::COMM_WORLD.Get_size();
if(rank==0)
Case *s=new Case();
s->value=1;
s->sta<<"test";
cout<<"\nInside send before copy value :"<<s->value;
fflush(stdout);
cout<<"\nInside send before copy data :"<<s->sta.str();
fflush(stdout);
Case scpy;
scpy.value=s->value;
scpy.sta<<(s->sta).rdbuf();
cout<<"\nInside send after copy value :"<<scpy.value;
cout<<"\nInside send after copy value :"<<scpy.sta.str();
MPI::COMM_WORLD.Send(&scpy,sizeof(Case),MPI::BYTE,1,23);
MPI::COMM_WORLD.Barrier();
if(rank==1)
Case r;
MPI::COMM_WORLD.Recv(&r,sizeof(Case),MPI::BYTE,0,23);
cout<<"\nRecieve value"<<r.value;
fflush(stdout);
cout<<"\nRecieve data"<<r.sta;
fflush(stdout);
MPI::Finalize();
return 0;
我收到以下错误消息,但我无法弄清楚这个程序有什么问题。 谁能解释一下?
Inside send before copy value :1
Inside send before copy data :test
Inside send after copy value :1
Recieve value1
Recieve data0xbfa5d6b4[localhost:03706] *** Process received signal ***
[localhost:03706] Signal: Segmentation fault (11)
[localhost:03706] Signal code: Address not mapped (1)
[localhost:03706] Failing at address: 0x8e1a210
[localhost:03706] [ 0] [0xe6940c]
[localhost:03706] [ 1] /usr/lib/libstdc++.so.6(_ZNSt18basic_stringstreamIcSt11char_traitsIcESaIcEED1Ev+0xc6) [0x6a425f6]
[localhost:03706] [ 2] ./a.out(_ZN4CaseD1Ev+0x14) [0x8052d8e]
[localhost:03706] [ 3] ./a.out(main+0x2f9) [0x804f90d]
[localhost:03706] [ 4] /lib/libc.so.6(__libc_start_main+0xe6) [0x897e36]
[localhost:03706] [ 5] ./a.out() [0x804f581]
[localhost:03706] *** End of error message ***
--------------------------------------------------------------------------
mpirun noticed that process rank 1 with PID 3706 on node localhost.localdomain exited on signal 11 (Segmentation fault).
--------------------------------------------------------------------------
【问题讨论】:
【参考方案1】:问题
我认为问题在于:
MPI::COMM_WORLD.Send(&scpy,sizeof(Case),MPI::BYTE,1,23);
将 Case 结构的副本发送给接收者,但它正在发送字节的原始副本,这不是很有用。 std::stringstream 类将包含一个指向用于存储字符串的实际内存的指针,因此此代码将:
-
向接收者发送一个指针(包含对接收者无意义的地址)
不发送字符串的实际内容。
接收器在尝试取消引用无效指针时会出现段错误。
修复 1
解决此问题的一种方法是自己发送字符数据。
在这种方法中,您将发送一条指向 std::stringstream::str()::c_str() 且长度为 std::stringstream::str()::size()*sizeof(char) 的消息。
修复 2
似乎更适合您尝试使用 MPI 和字符串的方式的另一种方法是使用 Boost 库。 Boost 包含用于 MPI 的函数,可自动为您序列化数据。
on the boost website 提供了有关 Boost 和 MPI 的有用教程。 以下是该教程中执行类似任务的示例代码:
#include <boost/mpi.hpp>
#include <iostream>
#include <string>
#include <boost/serialization/string.hpp>
namespace mpi = boost::mpi;
int main(int argc, char* argv[])
mpi::environment env(argc, argv);
mpi::communicator world;
if (world.rank() == 0)
world.send(1, 0, std::string("Hello"));
std::string msg;
world.recv(1, 1, msg);
std::cout << msg << "!" << std::endl;
else
std::string msg;
world.recv(0, 0, msg);
std::cout << msg << ", ";
std::cout.flush();
world.send(0, 1, std::string("world"));
return 0;
【讨论】:
以上是关于C++ 中的 MPI_Send MPI_Recv 段错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 MPI_Send 和 MPI_Recv 未正确接收矩阵
是否需要在对应的 MPI_Recv 之前调用 MPI_Send
使用 MPI_Send 和 MPI_Recv 实现 MPI_Scatter 的问题