我正在编写一个MPI程序,并且我正在使用的一台特定机器上的MPI_Bcast功能非常慢。为了缩小问题范围,我有以下两个测试程序。第一个执行从进程0到其他操作的许多MPI_Send / MPI_Recv操作:
#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>
#define N 1000000000
int main(int argc, char** argv) {
int rank, size;
/* initialize MPI */
MPI_Init(&argc, &argv);
/* get the rank (process id) and size (number of processes) */
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
/* have process 0 do many sends */
if (rank == 0) {
int i, j;
for (i = 0; i < N; i++) {
for (j = 1; j < size; j++) {
if (MPI_Send(&i, 1, MPI_INT, j, 0, MPI_COMM_WORLD) != MPI_SUCCESS) {
printf("Error!\n");
exit(0);
}
}
}
}
/* have the rest receive that many values */
else {
int i;
for (i = 0; i < N; i++) {
int value;
if (MPI_Recv(&value, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE) != MPI_SUCCESS) {
printf("Error!\n");
exit(0);
}
}
}
/* quit MPI */
MPI_Finalize( );
return 0;
}
该程序仅需2.7秒左右即可运行4个进程。
下一个程序完全相同,只是它使用MPI_Bcast将进程0中的值发送到其他进程:
#include <stdlib.h>
#include <stdio.h>
#include <mpi.h>
#define N 1000000000
int main(int argc, char** argv) {
int rank, size;
/* initialize MPI */
MPI_Init(&argc, &argv);
/* get the rank (process id) and size (number of processes) */
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
/* have process 0 do many sends */
if (rank == 0) {
int i, j;
for (i = 0; i < N; i++) {
if (MPI_Bcast(&i, 1, MPI_INT, 0, MPI_COMM_WORLD) != MPI_SUCCESS) {
printf("FAIL\n");
exit(0);
}
}
}
/* have the rest receive that many values */
else {
int i;
for (i = 0; i < N; i++) {
if (MPI_Bcast(&i, 1, MPI_INT, 0, MPI_COMM_WORLD) != MPI_SUCCESS) {
printf("FAIL\n");
exit(0);
}
}
}
/* quit MPI */
MPI_Finalize( );
return 0;
}
两个程序的N值都相同,两个程序都没有从通信调用中返回错误。第二个程序应该至少快一点。但事实并非如此,它在大约34秒时慢得多 - 大约慢了12倍!
这个问题只能出现在一台机器上,而不是其他机器,即使它们运行相同的操作系统(Ubuntu)并且没有完全不同的硬件。另外,我在两者上都使用OpenMPI。
我真的把头发拉了出来,有没有人有想法?
感谢阅读!
答案 0 :(得分:2)
一些观察结果。
MPI_Bcast正在将结果接收到“&amp; i”缓冲区中。 MPI_Recv将结果接收到“&amp; value”。有没有理由做出决定?
Send / Recv模型自然会同步。 MPI_Send调用是阻塞和序列化的。调用MPI_Send时,匹配的MPI_Recv应始终就绪。
一般而言,随着工作规模的扩大,集体倾向于拥有更大的优势。
我使用IBM Platform MPI编译并运行程序。我将N值降低了100倍至1000万,以加快测试速度。我更改了MPI_Bcast以在“&amp; value”缓冲区中接收结果,而不是在“&amp; i”缓冲区中。我对每个案例进行了三次处理,并将时间平均化。时间是“时间”返回的“真实”值(这是必要的,因为队列是从mpirun命令远程运行的)。
共享内存有4个等级,Send / Recv模型需要6.5秒,Bcast模型需要7.6秒。
有32个等级(8个/节点x 4个节点,FDR InfiniBand),发送/接收模型花了79秒,Bcast模型用了22秒。
拥有128个等级(16个/节点x 8个节点,FDR Infiniband),发送/接收模型需要134秒,Bcast模型需要44秒。
鉴于N值减少100倍至10000000之后的这些时间,我将建议“2.7秒”时间是无操作。仔细检查一些实际工作是否完成。