MPI: MPI_recv 和 MPI_ANY_SOURCE 无法接收来自某些进程的消息
MPI: MPI_recv with MPI_ANY_SOURCE can not receive messages from some processes
我想实现一个系统,其中有一个接收者和多个发送者。每个发送方不断向接收方发送数据。接收者等待接收数据并处理它。这是玩具示例。
#include <iostream>
#include <cstdlib>
#include <mpi.h>
using namespace std;
int main(int argc, char *argv[]) {
int _mpi_numWorkers, _mpi_rank;
// Initialize openMPI
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &_mpi_numWorkers);
MPI_Comm_rank(MPI_COMM_WORLD, &_mpi_rank);
MPI_Barrier(MPI_COMM_WORLD);
float *send_data = (float *)malloc(360 * 5000 * sizeof(float));
MPI_Status receive_status;
if (_mpi_rank == 0) {
while (1) {
MPI_Recv(send_data, 360 * 5000, MPI_FLOAT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &receive_status);
cout << "Receive from " << receive_status.MPI_SOURCE << endl;
}
} else {
while (1){
MPI_Send(send_data, 360 * 5000, MPI_FLOAT, 0, 0, MPI_COMM_WORLD);
//sleep(1);
}
}
// Terminate
MPI_Finalize();
return 0;
}
问题是 MPI_recv 最多只能接收来自两个进程的消息,无论我将其设置为 运行(不休眠时)有多少个进程。我已经在一台机器上和多台机器上测试了这段代码:
单机机箱
我运行这段代码通过以下命令:
mpiexec -n 5 ./test_mpi
然后,接收方只接收等级为 1 和 2 的发送方。
多机案例
我运行4个发送者和1个接收者在5台同类物理机上。它们都连接到 100Mbps 交换机。在这种情况下,接收方也只接收来自发送方子集的数据。我使用 tcpdump 检查数据包,发现有些发件人甚至没有发送消息。 (那些发件人在 MPI_send 处被阻止,但没有增加 tcp 序列,也没有重新传输。)
对于这两种情况,如果我让每个发送方休眠一段时间(降低发送速率),接收方可以从更多发送方接收数据。
有人可以帮我理解为什么会这样吗?
环境
使用 openmpi-1.6 进行 Debian 测试
编辑 2/4/16
我在代码中包含 <cstdlib>
以防止任何编译问题。
MPI 在这方面没有公平性保证,参见示例
http://www.mcs.anl.gov/research/projects/mpi/tutorial/gropp/node92.html#Node92
这意味着从 MPI 的角度来看,您所看到的完全 "legal"。在我提供的 link 中再翻一页,有一个片段据称可以帮助解决该问题。简而言之,您必须手动为每个可能的发件人发出(异步)接收,然后以您看起来 "fair" 的方式处理它们。
http://www.mcs.anl.gov/research/projects/mpi/tutorial/gropp/node93.html#Node93
我想实现一个系统,其中有一个接收者和多个发送者。每个发送方不断向接收方发送数据。接收者等待接收数据并处理它。这是玩具示例。
#include <iostream>
#include <cstdlib>
#include <mpi.h>
using namespace std;
int main(int argc, char *argv[]) {
int _mpi_numWorkers, _mpi_rank;
// Initialize openMPI
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &_mpi_numWorkers);
MPI_Comm_rank(MPI_COMM_WORLD, &_mpi_rank);
MPI_Barrier(MPI_COMM_WORLD);
float *send_data = (float *)malloc(360 * 5000 * sizeof(float));
MPI_Status receive_status;
if (_mpi_rank == 0) {
while (1) {
MPI_Recv(send_data, 360 * 5000, MPI_FLOAT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &receive_status);
cout << "Receive from " << receive_status.MPI_SOURCE << endl;
}
} else {
while (1){
MPI_Send(send_data, 360 * 5000, MPI_FLOAT, 0, 0, MPI_COMM_WORLD);
//sleep(1);
}
}
// Terminate
MPI_Finalize();
return 0;
}
问题是 MPI_recv 最多只能接收来自两个进程的消息,无论我将其设置为 运行(不休眠时)有多少个进程。我已经在一台机器上和多台机器上测试了这段代码:
单机机箱
我运行这段代码通过以下命令:
mpiexec -n 5 ./test_mpi
然后,接收方只接收等级为 1 和 2 的发送方。
多机案例
我运行4个发送者和1个接收者在5台同类物理机上。它们都连接到 100Mbps 交换机。在这种情况下,接收方也只接收来自发送方子集的数据。我使用 tcpdump 检查数据包,发现有些发件人甚至没有发送消息。 (那些发件人在 MPI_send 处被阻止,但没有增加 tcp 序列,也没有重新传输。)
对于这两种情况,如果我让每个发送方休眠一段时间(降低发送速率),接收方可以从更多发送方接收数据。
有人可以帮我理解为什么会这样吗?
环境
使用 openmpi-1.6 进行 Debian 测试
编辑 2/4/16
我在代码中包含 <cstdlib>
以防止任何编译问题。
MPI 在这方面没有公平性保证,参见示例
http://www.mcs.anl.gov/research/projects/mpi/tutorial/gropp/node92.html#Node92
这意味着从 MPI 的角度来看,您所看到的完全 "legal"。在我提供的 link 中再翻一页,有一个片段据称可以帮助解决该问题。简而言之,您必须手动为每个可能的发件人发出(异步)接收,然后以您看起来 "fair" 的方式处理它们。
http://www.mcs.anl.gov/research/projects/mpi/tutorial/gropp/node93.html#Node93