使用Boost MPI如何传递用户定义的结构体

4
我正在尝试使用boost::mpi::send()调用发送名为ABC的用户定义结构体。 给定的结构体包含一个名为“data”的向量,其大小在运行时确定。结构体ABC的对象由主节点发送到从节点。 但是从节点需要知道向量“data”的大小,以便在从节点上有足够的缓冲区来接收此数据。 我可以通过先发送大小并在接收struct ABC对象之前在从节点上初始化足够的缓冲区来解决这个问题。但是这违背了使用STL容器的初衷。 是否有更好的方法来处理这个问题?任何建议都将不胜感激。 下面是描述我的程序意图的示例代码。由于上述原因,此代码在运行时失败。
struct ABC
{
 double cur_stock_price;
 double strike_price;
 double risk_free_rate;
 double option_price;
 std::vector <char> data;
};

namespace boost
{
 namespace serialization
 {
   template<class Archive>
   void serialize (Archive &ar,
                   struct ABC &abc,
                   unsigned int version)
   {
     ar & abc.cur_stock_price;
     ar & abc.strike_price;
     ar & abc.risk_free_rate;
     ar & abc.option_price;
     ar & bopr.data;
   }
 }
}

BOOST_IS_MPI_DATATYPE (ABC);

int main(int argc, char* argv[])
{
 mpi::environment env (argc, argv);
 mpi::communicator world;

 if (world.rank () == 0)
 {
   ABC abc_obj;
  abc.cur_stock_price = 1.0;
  abc.strike_price = 5.0;
  abc.risk_free_rate = 2.5;
  abc.option_price = 3.0;
  abc_obj.data.push_back ('a');
  abc_obj.data.push_back ('b');

   world.send ( 1, ANY_TAG, abc_obj;);
   std::cout << "Rank 0 OK!" << std::endl;
 }

else if (world.rank () == 1)
{
   ABC abc_obj;

  // Fails here because abc_obj is not big enough
   world.recv (0,ANY_TAG, abc_obj;);
   std::cout << "Rank 1 OK!" << std::endl;

   for (int i = 0; i < abc_obj;.data.size(); i++)
     std::cout << i << "=" << abc_obj.data[i] << std::endl;
 }

 MPI_Finalize();
 return 0;
}
2个回答

3
您不应该在消息中发送vector对象本身,因为接收方只需要其内容,而且vector的内部状态在接收后可能会混乱(在发送端有效的内存地址可能在接收端无效)。
相反,您需要执行以下操作:
  1. 定义一个单独的结构体,包含四个双精度浮点数和一个简单的字符数组。
  2. 每当需要发送时,创建此新结构体的临时变量,并使用要发送的vector的内容填充字符数组。
  3. 定义一个临时MPI数据类型,与此特定结构体对象的大小匹配。
  4. 将临时结构体作为此临时数据类型的实例发送。
  5. 在适当大的接收缓冲区中接收它(或提前发送大小)
  6. 根据字符数组的内容重建ABC结构。
至少,这是您需要使用原始C++和MPI执行的操作。我不熟悉boost,所以不知道它是否可以使这些步骤更容易。

感谢suszterpatt的回复。 Boost只增加了启用向量使用的好处。 我目前正在使用类似于您推荐的东西。 但这不是优化的。我很想知道是否可以使用boost序列化和MPI库进行优化。 - lava
你所说的“未优化”是什么意思?你想要优化哪个部分,以何种方式进行优化? - suszterpatt
可以发送的数据量受接收缓冲区大小的限制。为了避免这种情况,我必须发送我要发送的数据大小,以便为其分配缓冲区。我想知道是否有一种方法可以摆脱这两个限制。 - lava
那在理论上是不可能的。如果接收进程想要分配足够的内存来接收消息,那么它在接收之前需要知道消息的大小。由于您的消息大小是可变的,在编译时无法获得这些信息,因此您将不得不失去其中一个条件。您可以发送一个包含有效负载大小的前置消息,或者使用类似我在这里描述的方法。 - suszterpatt

0

BOOST_IS_MPI_DATATYPE 仅适用于固定长度的数据。您的数组长度不是固定的,这就是为什么它失败的原因。


请删除该宏所在的行,程序就可以正常运行了。 - baol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接