【发布时间】:2015-09-29 06:00:40
【问题描述】:
我在代码中多次调用了 MPI_Sendrecv_replace。但是该函数的行为非常奇怪。在第一个循环(5000 次迭代)中,MPI_Sendrecv_replace 总共花费大约 30 秒。但是,在第二个循环中,该函数只使用了 1 秒。我很好奇原因是因为我想优化代码。该代码使用 32 个处理器运行。机器是一个节点,4个Intel(R) Xeon(R) CPU E5-4620 v2。
我的部分代码在这里:
for (ishot=1;ishot<=nshots;ishot+=SHOTINC){
...
for (nt=1;nt<=NT;nt++){
...
MPI_Sendrecv_replace(&bufferlef_to_rig[1][1],NY*fdo3,MPI_FLOAT,INDEX[1],TAG1,INDEX[2],TAG1,MPI_COMM_WORLD,&status);
...
}
for (nt=1;nt<=NT;nt++){
...
MPI_Sendrecv_replace(&bufferlef_to_rig[1][1],NY*fdo3,MPI_FLOAT,INDEX[1],TAG1,INDEX[2],TAG1,MPI_COMM_WORLD,&status);
...
}
}
我使用 MPI_Wtime 来计算 MPI_Sendrecv_replace 花费的时间。
【问题讨论】:
-
当您完成基本相同的阻塞通信操作的时间差别很大时,原因通常不是通信本身花费的时间或多或少;这是阻塞花费或多或少的时间。您所看到的很有可能是负载不平衡,或者某些通信伙伴不同步。您是否看到 MPI 任务的 sendrecv 时间有所不同?
-
在循环之前放一个
MPI_Barrier(MPI_COMM_WORLD);,看看是否有任何改变。 -
由于学校放假没有回复,抱歉。正如@HristoIliev 所说,如果我在第一个循环中在
MPI_Sendrecv_replace之前添加MPI_Barrier,则MPI_Barrier的时间成本约为30 秒,而MPI_Sendrecv_replace几乎不需要时间。但是这种情况只发生在第一个循环中,即当我在第二个循环中添加MPI_Barrier时没有变化。我忘记提及的一件事是 NY*fdo3*MPI_FLOAT 的大小约为 16Kbytes。是负载不平衡的问题吗? -
也许您遇到了负载不平衡的情况,导致不同的 MPI 等级在时间上不同步。因为
MPI_Sendrecv_replace操作正在同步,并且您可能有一个循环依赖链,所以由于负载不平衡而导致的延迟将传播和累积。使用像 Vampir(商业软件)这样的 MPI 跟踪工具来评估是否是这种情况。
标签: c linux performance mpi