6

boost 教程中有收集和减少操作的示例。收集的代码如下:

#include <boost/mpi.hpp>
#include <iostream>
#include <vector>
#include <cstdlib>
namespace mpi = boost::mpi;

int main(int argc, char* argv[])
{
  mpi::environment env(argc, argv);
  mpi::communicator world;

  std::srand(time(0) + world.rank());
  int my_number = std::rand();
  if (world.rank() == 0) {
    std::vector<int> all_numbers;
    gather(world, my_number, all_numbers, 0);
    for (int proc = 0; proc < world.size(); ++proc)
      std::cout << "Process #" << proc << " thought of "
                << all_numbers[proc] << std::endl;
  } else {
    gather(world, my_number, 0);
  }

  return 0;
}

而reduce的例子如下:

#include <boost/mpi.hpp>
#include <iostream>
#include <cstdlib>
namespace mpi = boost::mpi;

int main(int argc, char* argv[])
{
  mpi::environment env(argc, argv);
  mpi::communicator world;

  std::srand(time(0) + world.rank());
  int my_number = std::rand();

  if (world.rank() == 0) {
    int minimum;
    reduce(world, my_number, minimum, mpi::minimum<int>(), 0);
    std::cout << "The minimum value is " << minimum << std::endl;
  } else {
    reduce(world, my_number, mpi::minimum<int>(), 0);
  }

  return 0;
}

在这两个示例中,我们都有一个 if/else 条件,如下所示:

if(world.rank() == 0){
  //gather or reduce operation
  //Output
}else{
  //gather or reduce operation
}

我在这里无法理解的是 if 中的集体操作与 else 中的集体操作之间的区别?参数的数量有所不同,但我不太明白逻辑是如何运作的。

谢谢

4

2 回答 2

9

MPI 有两种类型的集体操作——一种具有指定的“根”进程,另一种没有。具有指定根的操作是广播(根进程向所有进程发送相同的数据)、分散(根进程将其数据分散到所有进程)、收集(根进程从所有进程收集数据)和缩减(根进程从所有进程收集数据)同时对其应用减少)。在 MPI 标准中,这些操作通常具有类似于以下内容的形式:

MPI_SCATTER(sendbuf, sendcount, sendtype,
            recvbuf, recvcount, recvtype, root, comm)

此 MPI 调用具有输入和输出参数,它必须在所有进程中使用,包括根进程,但输入参数 ( sendbuf, sendcount, sendtype) 仅在其等级等于的进程中有效,root并且在所有其他进程中被忽略。

MPI 是为可移植性而设计的,因此 MPI 调用的设计使得它们可以在 C 和 Fortran 77 中以相同的方式实现——这两种语言在设计 MPI 标准时都不支持函数重载或可选参数。(不)幸运的是,像 C++ 库这样的库boost::mpi通过提供有效隐藏未使用参数的那些调用的版本,在重载函数方面提供了 C++ 提供的自由。现在很明显,调用gather(world, my_number, 0)没有输出参数,因此它必须在不是操作根的进程中使用,而gather(world, my_number, all_numbers, 0)具有输出参数,因此只能在根中使用。这在编写代码时会造成一些不对称 - 你必须做一些事情if (world.rank() == root) { ... } else { ... }.

作为 MPI 的铁杆用户,我认为这很丑陋,但也有其他人不同意我的看法。我想……这取决于。

于 2012-07-11T20:36:02.540 回答
3

看看:

boost/mpi/collectives/gather.hpp

您将看到gather_impl 的不同实现,一种在参数列表中有“out”值,另一种没有。没有“输出”值的那个将其数据发送到根进程。所以在收集示例中:

gather(world, my_number, 0) 

实现一个 mpi 发送和

gather(world, my_number, all_numbers, 0) 

为根处理器实现本地副本,为其他处理器实现 mpi 接收。

于 2012-07-11T19:17:39.317 回答