无法使用MPI_Send和MPI_Recv发送std :: vector

9
我试图使用 MPI 的 send 和 recv 函数发送 std:vector,但是我一无所获。我遇到了像以下这样的错误:

Fatal error in MPI_Recv: Invalid buffer pointer, error stack:
MPI_Recv(186): MPI_Recv(buf=(nil), count=2, MPI_INT, src=0, tag=0, MPI_COMM_WORLD, status=0x7fff9e5e0c80) failed
MPI_Recv(124): Null buffer pointer

我尝试了多种组合。 A)就像发送数组时所用的那样。
 std::vector<uint32_t> m_image_data2; // definition of  m_image_data2
     m_image_data2.push_back(1);
     m_image_data2.push_back(2);
     m_image_data2.push_back(3);
     m_image_data2.push_back(4);
     m_image_data2.push_back(5);

MPI_Send( &m_image_data2[0], 2, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Send( &m_image_data2[2], 2, MPI_INT, 1, 0, MPI_COMM_WORLD);

MPI_Recv( &m_image_data2[0], 2, MPI_INT, 0, 0, MPI_COMM_WORLD, &status );

B)没有 []
MPI_Send( &m_image_data2, 2, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Send( &m_image_data2 + 2, 2, MPI_INT, 1, 0, MPI_COMM_WORLD);

MPI_Recv( &m_image_data2, 2, MPI_INT, 0, 0, MPI_COMM_WORLD, &status );

C) 使用类似于at()的向量方法。
MPI_Send( &m_image_data2.at(0), 2, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Send( &m_image_data2.at(2), 2, MPI_INT, 1, 0, MPI_COMM_WORLD);

MPI_Recv( &m_image_data2.at(0), 2, MPI_INT, 0, 0, MPI_COMM_WORLD, &status );

我正在考虑在主节点将向量转换为int [],然后再在工作节点中将其转换回向量,但这会造成不必要的开销。
有人知道如何解决吗?

请发布完整的代码示例。正如您在下面评论的那样,您的错误与MPI无关,而与您省略显示的代码有关,但是没有人会知道! - mabraham
2个回答

13

没有更完整的示例,我不知道发生了什么事情,但似乎你在发送和接收消息时出现了不匹配(或者你没有正确初始化接收向量)。

以下类似的示例就足够了:

std::vector<uint32_t> m_image_data2;

if (rank==0) {
  m_image_data2.push_back(1);
  m_image_data2.push_back(2);
  m_image_data2.push_back(3);
  m_image_data2.push_back(4);
  m_image_data2.push_back(5);
  // send 5 ints at once
  MPI_Send( &m_image_data2[0], 5, MPI_INT, 1, 0, MPI_COMM_WORLD);
}
else {
  // make space for 5 ints
  m_image_data2.resize(5);
  // receive 5 ints
  MPI_Recv(&m_image_data2[0], 5, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
}

1
我会稍微改进一下,使用向量的size(),即MPI_Send(&m_image_data2[0],m_image_data2.size(),...)。为了清晰地移动复杂数据类型,您还可以研究MPI中的自定义数据类型功能。这很棘手,但您可以发送结构体。此外,传输未知大小的数据也需要您发送向量的大小,以便接收方有机会分配内存。您可以查看Boost MPI http://www.boost.org/doc/html/mpi.html。 - aselle
真的吗!太好了,它起作用了! 我漏掉了这一行代码: m_image_data2.resize(5); - Abdullah
3
不需要使用 &m_image_data2[0] 来获取 std::vector 的数据,可以使用 .data() 函数来实现;即 &m_image_data2[0] == m_image_data2.data() - wolfPack88
2
@wolfPack88 std::vector.data() 是 C++11 的特性,可能不适用于 OP,但是这确实是一种更简洁的方式。 - ipapadop
我认为早在2010年,Intel和GCC就已经拥有了它,而这之前它还没有成为标准的一部分。不过也可以理解。 - wolfPack88

4
考虑一下Boost::MPI,它通过Boost::Serialization明确地支持例如std::vector
当然,Boost::MPI并不支持MPI 3.0的所有功能,而是支持MPI 1.3(可能还包括MPI 2.2的一个子集,但绝对不包括RMA),所以它并不是一个完美的解决方案。然而,如果您只使用MPI-1中引入的常见功能,那么它应该是可以的。

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