MPI_Recv/MPI_Send overhead

MPI_Recv/MPI_Send overhead

本文关键字:MPI overhead Send Recv      更新时间:2023-10-16

我正在开发一个C++应用程序,其中我使用 MPI C 绑定通过网络发送和接收数据。我明白发送

const int VECTOR_SIZE = 1e6;
std::vector<int> vector(VECTOR_SIZE, 0.0);

通过

// Version A
MPI_Send(const_cast<int *>(vector.data()), vector.size(), MPI_INT, 1, 0, MPI_COMM_WORLD);

// Version B
for (const auto &element : vector)
    MPI_Send(const_cast<int *>(&element), 1, MPI_INT, 1, 0, MPI_COMM_WORLD);

由于MPI_Send引入的延迟。但是,如果我想发送内存中不连续的数据结构(例如std::list<int>),我不能使用版本 A,而必须求助于版本 B 或将列表的内容复制到连续容器(例如std::vector<int>)并使用版本 A。由于我想避免额外的副本,我想知道 MPI 中是否有任何选项/其他函数可以有效地使用版本 B(或至少是类似的、类似循环的结构),而不会在每次调用MPI_Send时产生延迟?

通过std::list元素逐个单步发送确实会导致大量的通信开销。

MPI 规范/库被设计为独立于语言。 这就是为什么它使用与语言无关的 MPI 数据类型。 结果是它只能从连续缓冲区(这是大多数语言提供的功能)发送,而不能从列表等更复杂的数据结构发送。

为了避免逐个发送的通信开销,有两种替代方法:

  • 将所有列表元素复制到std::vector并发送向量。 但是,这会产生一个内存过度,并使发送完全顺序化(在此期间,某些 MPI 节点可能处于空闲状态)。

  • 或者遍历您的列表,构建较小的向量/缓冲区并发送这些较小的块(最终将它们调度到多个目标节点? 此方法的优点是通过流水线效应更好地利用 I/O 延迟和并行性。 但是,您必须进行一些实验才能找到中间块的最佳大小。