MPI_Send 使用不同节点执行时卡住
MPI_Send getting stuck when executing with different nodes
我有一个非常简单的 MPI 程序,其中节点 0 向节点 1 发送一个字符,但是每当我使用两台或多台不同的机器时,发送和接收就会卡住。当我只在一台机器上使用多个进程时,程序运行良好。貌似是通讯问题,但是我怎么也想不通.....
代码如下:
int main(int argc, char *argv[]) {
int numtasks, rank, tag = 1;
char inmsg, outmsg = 'x';
MPI_Status stat;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if ( rank == 0 ) {
MPI_Send(&outmsg, 1, MPI_CHAR, 1, tag, MPI_COMM_WORLD);
}
else if ( rank == 1 ) {
MPI_Recv(&inmsg, 1, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &stat);
}
MPI_Finalize();
}
另外,这里有一些重要的注意事项:
- 我在 Google Compute Engine 中使用 2 个虚拟机集群:mpi-test-uaiw 和 mpi-test-130b ;
- 我已经在两个虚拟机之间配置了无密码ssh,也就是说,从mpi-test-uaiw我可以直接输入ssh mpi-test-130b 并且工作正常(反之亦然);
- 使用 MPI 的简单 "Hello World" 适用于此集群,但它不包含任何发送或接收操作;
- 防火墙已停用。
如有任何帮助,我们将不胜感激。谢谢!
我找到了解决问题的方法:
我使用 MPICH,运行 我的程序使用 mpirun。从表面上看,问题在于 mpich 使用了错误的网络接口。每个节点有两个接口:lo和ens4。从我在其他帖子中看到的,似乎 lo 用于将数据从一个节点传输到自身,而 ens4 用于与其他节点。我使用以下 ping 命令验证了这一点:
$ ifconfig -a
:显示可用的接口;
- 来自 mpi-test-uaiw:
$ ping -I lo mpi-test-130b
-> 失败
- 来自 mpi-test-uaiw:
$ ping -I ens4 mpi-test-130b
-> 成功
- 来自 mpi-test-uaiw:
$ ping -I lo mpi-test-uaiw
-> 成功
- 来自 mpi-test-uaiw:
$ ping -I ens4 mpi-test-uaiw
-> 失败
可能的解决方案之一是使用 mpirun --mca btl_tcp_if_include ens4 确保 mpirun 使用 ens4 接口与其他节点通信。但这对我不起作用,因为 MPICH 无法识别 --mca 参数。因此,我做了以下操作:
- 删除了我用来安装 MPICH 的包(在两个节点中):
$ sudo apt-get remove libcr-dev mpich mpich-doc
;
- 安装了 OpenMPI(在两个节点中):
$ sudo apt install openmpi-bin openmpi-doc libopenmpi-dev
;
通过安装 OpenMPI,我的代码可以正常工作。希望对遇到同样问题的人有所帮助!
我有一个非常简单的 MPI 程序,其中节点 0 向节点 1 发送一个字符,但是每当我使用两台或多台不同的机器时,发送和接收就会卡住。当我只在一台机器上使用多个进程时,程序运行良好。貌似是通讯问题,但是我怎么也想不通.....
代码如下:
int main(int argc, char *argv[]) {
int numtasks, rank, tag = 1;
char inmsg, outmsg = 'x';
MPI_Status stat;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if ( rank == 0 ) {
MPI_Send(&outmsg, 1, MPI_CHAR, 1, tag, MPI_COMM_WORLD);
}
else if ( rank == 1 ) {
MPI_Recv(&inmsg, 1, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &stat);
}
MPI_Finalize();
}
另外,这里有一些重要的注意事项:
- 我在 Google Compute Engine 中使用 2 个虚拟机集群:mpi-test-uaiw 和 mpi-test-130b ;
- 我已经在两个虚拟机之间配置了无密码ssh,也就是说,从mpi-test-uaiw我可以直接输入ssh mpi-test-130b 并且工作正常(反之亦然);
- 使用 MPI 的简单 "Hello World" 适用于此集群,但它不包含任何发送或接收操作;
- 防火墙已停用。
如有任何帮助,我们将不胜感激。谢谢!
我找到了解决问题的方法:
我使用 MPICH,运行 我的程序使用 mpirun。从表面上看,问题在于 mpich 使用了错误的网络接口。每个节点有两个接口:lo和ens4。从我在其他帖子中看到的,似乎 lo 用于将数据从一个节点传输到自身,而 ens4 用于与其他节点。我使用以下 ping 命令验证了这一点:
$ ifconfig -a
:显示可用的接口;- 来自 mpi-test-uaiw:
$ ping -I lo mpi-test-130b
-> 失败 - 来自 mpi-test-uaiw:
$ ping -I ens4 mpi-test-130b
-> 成功 - 来自 mpi-test-uaiw:
$ ping -I lo mpi-test-uaiw
-> 成功 - 来自 mpi-test-uaiw:
$ ping -I ens4 mpi-test-uaiw
-> 失败
可能的解决方案之一是使用 mpirun --mca btl_tcp_if_include ens4 确保 mpirun 使用 ens4 接口与其他节点通信。但这对我不起作用,因为 MPICH 无法识别 --mca 参数。因此,我做了以下操作:
- 删除了我用来安装 MPICH 的包(在两个节点中):
$ sudo apt-get remove libcr-dev mpich mpich-doc
; - 安装了 OpenMPI(在两个节点中):
$ sudo apt install openmpi-bin openmpi-doc libopenmpi-dev
;
通过安装 OpenMPI,我的代码可以正常工作。希望对遇到同样问题的人有所帮助!