MPI_Recv/MPI_Send 开销
MPI_Recv/MPI_Send overhead
我正在开发一个 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 中是否有任何 options/other 函数允许有效使用版本 B(或在至少是一个类似的、类似循环的构造)而不会在每次调用 MPI_Send
时产生延迟?
通过您的 std::list
元素一个一个地步进和发送确实会导致显着的通信开销。
MPI specification/library is designed to be language independent. This is why it uses language agnostic MPI datatypes。结果是它只能从连续的缓冲区发送(这是大多数语言提供的功能),而不能从更复杂的数据结构(如列表)发送。
为了避免一个一个发送的通信开销,有两种选择:
将所有列表元素复制到 std::vector
中并发送向量。但是,这会造成内存溢出并使发送完全按顺序进行(并且在此期间某些 MPI 节点可能处于空闲状态)。
或遍历您的列表,构建更小的 vectors/buffers 并发送这些更小的块(最终将它们分派到多个目标节点?)。这种方法的好处是可以更好地利用中间块的 i/o latency and parallelism through a pipelining effect. You have however to experiment a little bit to find the optimal size。
我正在开发一个 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 中是否有任何 options/other 函数允许有效使用版本 B(或在至少是一个类似的、类似循环的构造)而不会在每次调用 MPI_Send
时产生延迟?
通过您的 std::list
元素一个一个地步进和发送确实会导致显着的通信开销。
MPI specification/library is designed to be language independent. This is why it uses language agnostic MPI datatypes。结果是它只能从连续的缓冲区发送(这是大多数语言提供的功能),而不能从更复杂的数据结构(如列表)发送。
为了避免一个一个发送的通信开销,有两种选择:
将所有列表元素复制到
std::vector
中并发送向量。但是,这会造成内存溢出并使发送完全按顺序进行(并且在此期间某些 MPI 节点可能处于空闲状态)。或遍历您的列表,构建更小的 vectors/buffers 并发送这些更小的块(最终将它们分派到多个目标节点?)。这种方法的好处是可以更好地利用中间块的 i/o latency and parallelism through a pipelining effect. You have however to experiment a little bit to find the optimal size。