В boost::mpi
некоторые коллективные операции, такие как уменьшение , требуют передачи операции в подпрограмму. Я не уверен, какой именно должен быть тип этой операции.
Следующий минимальный пример компилируется без предупреждений.
#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;
}
Однако при выполнении более 1 задач происходит сбой
$ 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(....)
, т. е. оба варианта callable . Таким образом, в обоих случаях работает код, подобный следующему.
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 )