10

我有一个 MPI 程序,它由一个主进程组成,它将命令传递给一堆从进程。收到命令后,从站只需调用 system() 即可。当从站等待命令时,它们会消耗 100% 的各自 CPU。Probe() 似乎处于一个紧密的循环中,但这只是一个猜测。你认为这可能是什么原因造成的,我能做些什么来解决它?

这是从进程中等待命令的代码。同时看日志和top命令表明,当slave在消耗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;
}
4

2 回答 2

14

是的; 大多数 MPI 实现,为了性能,阻塞操作忙等待。假设 MPI 作业是我们在处理器上唯一关心的事情,如果任务被阻塞等待通信,最好的办法是不断轮询该通信以减少延迟;这样在消息到达和移交给 MPI 任务之间几乎没有延迟。这通常意味着即使没有做任何“真正的”事情,CPU 也被固定在 100%。

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

mpirun -np N --mca mpi_yield_when_idle 1 ./a.out
于 2013-01-28T13:14:11.203 回答
4

听起来有三种方法可以等待 MPI 消息:

  1. 积极的忙等待。这将尽快将消息发送到您的接收代码中。一些处理器除了检查传入的消息之外什么都不做。如果您将所有处理器都置于这种状态,那么系统的其余部分将会非常缓慢。MPI 默认使用激进模式。
  2. 降级忙等待。这将在忙等待时让步给其他进程。如果您要求的进程数多于您拥有的处理器数,MPI 将切换到降级模式。您还可以使用MCA 参数强制进取或降级模式。
  3. 轮询。即使降级的忙等待仍然是一个忙等待,它会为每个正在等待的进程保持一个处理器固定在 100%。如果您的系统上有其他不想与之竞争的任务,您可以在调用阻塞接收之前通过 sleep 调用循环调用MPI_Iprobe()我发现 100 毫秒的睡眠对于我的任务来说已经足够响应了,并且当工作人员空闲时仍然保持 CPU 使用率最小。

我做了一些搜索,发现如果您不与其他任务共享您的处理器,那么您想要的是忙碌的等待。

于 2015-01-28T00:43:56.567 回答