I need the MPI world communicator to be accessible in functions/class member functions. But by design/convention, MPI environments and communicators are always defined and initialized at the beginning of int main()
.
The only, simple solution I can think of using a global pointer to the communicator.
Does anybody know of a better way? Is it dangerous to use the global pointer solution?
This problem applies equally well to bare-bones MPI, and to Boost::MPI (which I use below)
Example of my proposed solution (untested):
//globals.h
extern boost::mpi::communicator * my_MPI_world_ptr;
and
//main.cpp
...
int main(int argc, char* argv[])
{
boost::mpi::environment my_boost_mpi_env(argc, argv);
boost::mpi::communicator my_MPI_world;
my_MPI_world_ptr = &my_MPI_world;
my_MPI_rank = my_MPI_world_ptr->rank();
size_MPI_WORLD = my_MPI_world_ptr->size();
my_class an_Object;
an_Object.member_function_that_uses__MPI_world();
...
}
Do you mean the actual MPI MPI_COMM_WORLD
communicator (or the Boost wrapper of it)? That is already global. If you are using a different communicator to separate communication from a library that you are writing, it would be better to avoid using a global variable for it at all. In that case, you might want to just pass it (or a pointer to it) around and store it in the classes that need it.
I don't like global pointers in general: who's responsible for deleting them? How do you make sure the pointer is not accessed before the object is created, or after the object is destroyed?
I'd be tempted to wrap the pointer and its access in a class. (Warning: The following hasn't seen a compiler so might have all sorts of issues, and I'm not familiar with MPI)
class CMPIwrapper
{
public:
CMPIwrapper(boost::mpi::communicator& myMPIworld):myMPIworld_(myMPIworld){}
rank_type GetRank()const
{
return( my_MPI_world_ptr->rank() );
}
private:
boost::mpi::communicator& myMPIworld_;
};
int main(int argc, char* argv[])
{
boost::mpi::environment my_boost_mpi_env(argc, argv);
boost::mpi::communicator my_MPI_world;
CMPIwrapper my_MPI_wrapper(my_MPI_world);
my_MPI_rank = CMPIwrapper.GetRank();
}
Your own objects that used to use the pointer could work in the same way: their constructor could be passed a reference to your boost::mpi::communicator, or if the set of operations on your boost::mpi::communicator are well defined, they could be passed a reference to the wrapper.