4

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

3 回答 3

2

您是指实际的 MPIMPI_COMM_WORLD通信器(或它的 Boost 包装器)吗?这已经是全球性的了。如果您使用不同的通信器将通信与您正在编写的库分开,最好完全避免使用全局变量。在这种情况下,您可能只想传递它(或指向它的指针)并将其存储在需要它的类中。

于 2012-03-30T17:31:23.450 回答
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::communicator 上的操作集很好定义后,它们可以传递给包装器的引用。

于 2012-03-30T14:29:36.813 回答
2
  1. 对于 boost mpi,默认构造的(即空初始化器)通信器对应于MPI_COMM_WORLD,因此您可以简单地定义另一个

    mpi::communicator world;
    

    在您的函数内部使用它,就好像它是您在外部定义的那样。

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

  3. 对于准系统 MPI,我已经测试过MPI_INIT除了 main 之外的其他地方调用也是允许的。例如,您可以在头文件中为全局工作者定义以下包装器,

        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

于 2015-11-12T15:52:23.750 回答