我需要在函数/类成员函数中访问MPI世界通信器。但是根据设计/惯例,MPI环境和通信器总是在int main()
的开头定义和初始化。
我能想到的唯一,简单的解决方案是使用指向通信器的全局指针。
有人知道更好的方法吗?使用全局指针解决方案是危险的吗?
此问题同样适用于裸机MPI和Boost :: MPI(我在下面使用)
我建议的解决方案示例(未经测试):
//globals.h
extern boost::mpi::communicator * my_MPI_world_ptr;
和
//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();
...
}
答案 0 :(得分:2)
我不喜欢一般的全球指针:谁负责删除它们?如何在创建对象之前或在对象被销毁之后确保不访问指针?
我很想把指针及其访问权限包装在一个类中。 (警告:以下没有见过编译器所以可能有各种各样的问题,而且我不熟悉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();
}
以前使用指针的对象可以以相同的方式工作:它们的构造函数可以传递给你的boost :: mpi :: communicator,或者你的boost :: mpi ::通信器定义良好,可以传递给包装器的引用。
答案 1 :(得分:1)
你的意思是实际的MPI MPI_COMM_WORLD
通信器(或它的Boost包装器)?这已经是全球性的。如果您使用不同的通信器将通信与正在编写的库分开,那么最好避免使用全局变量。在这种情况下,您可能只想传递它(或指向它的指针)并将其存储在需要它的类中。
答案 2 :(得分:0)
对于boost mpi,默认构造(即空初始化器)通信器对应MPI_COMM_WORLD
,因此您可以简单地定义另一个
mpi::communicator world;
在你的函数中使用它就好像它是你在外面定义的一样。
MPI_INIT
时会调用 mpi::environment
。因此,只要将其放在主程序的开头,就可以在其他地方自由定义全局mpi::communicator
。没有必要使用指针。 (实际上你甚至可以在其他地方放置MPI_INIT
,见下文)。
对于简单的MPI,我已经测试过除了main之外的其他地方调用MPI_INIT
也是允许的。例如,您可以在头文件
class MpiWorker_t
{
public:
int NumberOfWorkers, WorkerId, NameLen;
char HostName[MPI_MAX_PROCESSOR_NAME];
MpiWorker_t()
{
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD,&NumberOfWorkers);
MPI_Comm_rank(MPI_COMM_WORLD,&WorkerId);
MPI_Get_processor_name(HostName, &NameLen);
}
~MpiWorker_t()
{
MPI_Finalize();
}
}
extern MpiWorker_t GlobalWorker;
并在源文件中,在main()
以外的任何位置定义全局实例:
MpiWorker_t GlobalWorker;
在任何MPI
函数调用之前和之后,全局变量的构造和销毁应该能够处理MPI
初始化和完成。