c ++: MPI-коммуникатор как глобальная переменная - PullRequest
3 голосов
/ 30 марта 2012

Мне нужно, чтобы мировой коммуникатор 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 ]

2 голосов
/ 30 марта 2012

Мне вообще не нравятся глобальные указатели: кто отвечает за их удаление?Как вы убедитесь, что указатель не доступен до создания объекта или после уничтожения объекта?

У меня возникнет соблазн обернуть указатель и его доступ в класс.(Предупреждение: следующее не видел компилятор, поэтому может иметь все виды проблем, и я не знаком с 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 :: communator, или, если набор операций на вашем boost :: mpi :: коммуникаторе хорошо определен, им можно передать ссылку на оболочку.

1 голос
/ 30 марта 2012

Вы имеете в виду настоящий коммуникатор MPI MPI_COMM_WORLD (или его Boost-оболочку)?Это уже глобально.Если вы используете другой коммуникатор для отделения связи от библиотеки, которую вы пишете, было бы лучше вообще не использовать для нее глобальную переменную.В этом случае вы можете просто передать его (или указатель на него) и сохранить в нужных ему классах.

0 голосов
/ 12 ноября 2015
  1. Для boost mpi построенный по умолчанию (т.е. пустой инициализатор) коммуникатор соответствует MPI_COMM_WORLD, так что вы можете просто определить другой

    mpi::communicator world;
    

    внутри вашей функции используйте ее так, как если бы вы определили ее снаружи.

  2. MPI_INIT вызывается при построении mpi::environment. Так что, пока это находится в начале вашей основной программы, вы можете определять глобальный mpi::communicator где-то еще. Нет необходимости использовать указатель. (На самом деле вы можете даже разместить MPI_INIT где-нибудь еще, см. Ниже).

  3. Для обычного MPI, я проверил, что также разрешен вызов 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.

...