探针似乎会消耗CPU。

11

我的MPI程序由一个主进程和一堆从进程组成。主进程将命令交给从进程处理。从进程收到命令后,会通过调用system()函数来执行命令。当从进程等待命令时,它们会消耗各自CPU的100%。看起来Probe()函数在一个紧密的循环中,但这只是猜测。你认为可能是什么原因导致的,我该怎么解决?

下面是等待命令的从进程代码。同时观察日志和top命令表明,当从进程占用CPU资源时,它们位于这个函数内部。

MpiMessage
Mpi::BlockingRecv() {
  LOG(8, "BlockingRecv");

  MpiMessage result;
  MPI::Status status;

  MPI::COMM_WORLD.Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, status);
  result.source = status.Get_source();
  result.tag = status.Get_tag();

  int num_elems = status.Get_count(MPI_CHAR);
  char buf[num_elems + 1];
  MPI::COMM_WORLD.Recv(
     buf, num_elems, MPI_CHAR, result.source, result.tag
  );
  result.data = buf;
  LOG(7, "BlockingRecv about to return (%d, %d)", result.source, result.tag);
  return result;
}

1
请注意,在使用OpenFabrics互连系统(InfiniBand或iWARP)上调用fork()函数时可能出现分段错误的情况。 - Hristo Iliev
2个回答

15

是的,大多数MPI实现为了性能考虑,在阻塞操作上进行忙等待。这个假设是MPI作业是我们在处理器上关心的唯一事情;如果任务因通信而被阻塞,最好的做法是不断地检查该通信以减少延迟,以便在消息到达和移交给MPI任务之间几乎没有延迟。这通常意味着即使没有做任何“真正”的工作,CPU也会保持100%的速度。

对于大多数MPI用户来说,这可能是最好的默认行为,但并不总是你想要的。通常,MPI实现允许关闭它; 在OpenMPI中,您可以使用MCA参数关闭此行为,

mpirun -np N --mca mpi_yield_when_idle 1 ./a.out

谢谢!事实上,我运行的进程比处理器还多。 - Ben Kovitz

4
听起来有三种等待MPI消息的方法:
  1. 积极的忙等待。这将尽可能快地将消息传递到接收代码中。某个处理器仅在检查传入消息。如果您将所有处理器都置于此状态,则系统的其余部分会变得非常缓慢。MPI默认使用积极模式。
  2. 退化的忙等待。这将在繁忙等待时向其他进程让出。如果您要求的进程数多于您拥有的处理器数,则MPI会切换到退化模式。您还可以使用MCA参数强制使用积极或退化模式。
  3. 轮询。即使是退化的忙等待仍然是忙等待,并且每个正在等待的进程将保持一个处理器的占用率为100%。如果您的系统上有其他任务不希望与之竞争,您可以在阻塞接收之前循环调用MPI_Iprobe()进行睡眠调用。我发现100毫秒的睡眠对我的任务响应足够,当工作者处于空闲状态时,它仍可以使CPU使用率最小化。
我进行了一些搜索,并发现如果您没有将处理器与其他任务共享,则需要繁忙等待。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接