boost mpi集体操作中的操作类型



boost::mpi中,一些集体操作,如reduce,需要将一个操作传递到例程。我不确定这次手术的具体类型。

以下最小示例编译时没有警告。

#include <iostream>
#include <boost/mpi/collectives.hpp>
int mysum(int a, int b) { return a + b; }
int main()
{
boost::mpi::environment env;
boost::mpi::communicator world;
int data = world.rank() + 1;
int data_reduced;
boost::mpi::reduce(world, data, data_reduced, mysum, 0);
if (world.rank() == 0)
std::cout << data_reduced << std::endl;
return 0;
}

但是,运行一个以上的任务会导致崩溃

$ mpirun -n 2 ./mpi
munmap_chunk(): invalid pointer
...

按照如下方式修改代码可以使程序在没有崩溃的情况下运行。

#include <iostream>
#include <boost/mpi/collectives.hpp>
struct mysum {
int operator()(int a, int b) { return a + b; }
};
int main()
{
boost::mpi::environment env;
boost::mpi::communicator world;
int data = world.rank() + 1;
int data_reduced;
boost::mpi::reduce(world, data, data_reduced, mysum{}, 0);
if (world.rank() == 0)
std::cout << data_reduced << std::endl;
return 0;
}

(我知道这相当于std::plus,该程序只是一个例子(

$ mpirun -n 2 ./mpi
3

有什么不同,为什么第二个版本有效?

编辑

这个问题也出现了,因为mysum的两个变体都可以称为mysum(....),即两者都是可调用的。因此,在这两种情况下,像下面这样的代码都有效。

template <class Callable, class ArgType>
auto dosomething(ArgType a, ArgType b, Callable&& L) { return L(a, b); }
auto x = dosomething(mysum, 1, 2);

(这本质上等同于std::invoke(

看起来这正是boost::mpi所期望的!

如果你模仿boost/mpi/operations.h,你的用户定义的归约算子可以写成这样的

template<typename T>
struct mysum
{
typedef T first_argument_type;
typedef T second_argument_type;
typedef T result_type;
const T& operator()(const T& x, const T& y) const
{
return x + y;
}
};

然后您的reduce调用将看起来像

boost::mpi::reduce(world, data, data_reduced, std::plus<int>(), 0);

最重要的是,即使mysum是传递给普通CMPI_Op_create()的正确内容,这也不是boost::mpi所期望的。

最新更新