c ++:MPI通信器作为全局变量

时间:2012-03-30 14:05:27

标签: c++ global-variables mpi boost-mpi

我需要在函数/类成员函数中访问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();
   ...
}

3 个答案:

答案 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)

  1. 对于boost mpi,默认构造(即空初始化器)通信器对应MPI_COMM_WORLD,因此您可以简单地定义另一个

    mpi::communicator world;
    

    在你的函数中使用它就好像它是你在外面定义的一样。

  2. 构建MPI_INIT时会调用
  3. mpi::environment。因此,只要将其放在主程序的开头,就可以在其他地方自由定义全局mpi::communicator。没有必要使用指针。 (实际上你甚至可以在其他地方放置MPI_INIT,见下文)。

  4. 对于简单的MPI,我已经测试过除了main之外的其他地方调用MPI_INIT也是允许的。例如,您可以在头文件

    中为全局worker定义以下包装器
        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初始化和完成。