MPI收集/减少操作混乱?

sc_*_*ray 5 c++ boost mpi boost-mpi

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;
}
Run Code Online (Sandbox Code Playgroud)

减少的例子如下:

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

if(world.rank() == 0){
  //gather or reduce operation
  //Output
}else{
  //gather or reduce operation
}
Run Code Online (Sandbox Code Playgroud)

我在这里无法理解的是if中的集体操作与其他中的什么不同?参数数量有所不同,但我不太清楚逻辑是如何工作的.

谢谢

Hri*_*iev 8

MPI有两种类型的集体操作 - 一种具有指定的"根"过程,另一些则没有.广播指定根的操作(根进程将相同的数据发送到所有进程),分散(根进程将其数据分散到所有进程),收集(根进程从所有进程收集数据)和减少(根进程从所有进程收集数据)同时减少它).在MPI标准中,这些操作通常具有类似于以下的形式:

MPI_SCATTER(sendbuf, sendcount, sendtype,
            recvbuf, recvcount, recvtype, root, comm)
Run Code Online (Sandbox Code Playgroud)

该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用户认为这个丑陋,但还有其他人不同意我的看法.我想......这取决于.