Отправить функцию в процессы MPI

В настоящее время я пишу системное программное обеспечение для распределенных систем, а затем я намерен оценить некоторые вещи для параллельного управления. Я полагался в своих системах выполнения на модель программирования задач, как в стандарте OpenMP3.0, но для другой категории машин с MPI.

Для этого я создаю несколько MPI-процессов (по одному на машину) и запускаю на нем несколько потоков. Существует один главный процесс, который отвечает за создание новых задач для других процессов, и ему необходимо отправить некоторую работу для выполнения. Каждая задача содержит указатель на функцию (необходимая работа) и набор аргументов, передаваемых этой функции. Что-то вроде этого:

    class Task
    {
      public:
        typdef struct
        {
          // ... Storing and packing arguments
        } args_t;
        Task();
        ~Task();
        void exec()
        {
          // Executing the function pointed by "func_ptr"
          // with the specified arguments in "args"
          func_ptr( args );
        }
      private:
        void (*func_ptr)(args_t);
        args_t args;
    };

Для передачи аргументов я буду использовать функции MPI_Type_create_struct. Однако теперь моя проблема: как отправить функцию другому процессу MPI? Если я отправлю функцию указателя, она больше не будет действительна в адресном пространстве получателя процесса MPI. Поскольку я не могу знать количество различных типов задач, которые у меня будут, это добавляет еще одну трудность, потому что я не могу создать соответствующую карту и просто отправить уникальный идентификатор в процесс MPI. У вас есть идеи, как решить мою проблему?

Спасибо !


person Adrien Roussel    schedule 16.07.2018    source источник
comment
Как вы можете не знать количество различных типов задач в любое время? Ваш анализ ограничений в значительной степени соответствует действительности. То, что вы хотите, в значительной степени невозможно, за исключением действительно хакерских хаков.   -  person Zulan    schedule 16.07.2018
comment
Ну, на самом деле я могу знать, сколько типов у меня будет во время исполнения. И, собственно говоря, я ищу прием, позволяющий обойти эти ограничения. Возможно, трюк для запуска одной подпрограммы в процессе MPI вместо отправки функции или указателя на функцию. Однако я понятия не имею о целесообразности этого, и, может быть, кто-то уже сталкивался с подобной проблемой?   -  person Adrien Roussel    schedule 17.07.2018
comment
Общение функций через MPI неслыханно. Но вы определенно можете создать и завершить набор процессов из набора запущенных процессов, используя MPI_Comm_spawn и MPI_Comm_spawn_multiple , если это то, что вы имели в виду, запуская «подпрограмму».   -  person ggulgulia    schedule 17.07.2018
comment
Если все ваши MPI-задачи выполняют один и тот же двоичный файл, все подпрограммы должны быть сопоставлены с одним и тем же адресом, поэтому отправка указателя может сработать. Если все подпрограммы находятся в адресном пространстве всех задач MPI, то вы можете передать имя подпрограммы (например, строку с завершающим нулем) и использовать dlsym(), чтобы найти ее адрес.   -  person Gilles Gouaillardet    schedule 17.07.2018
comment
Если вы делаете что-то очень динамичное, хакерский вариант — сгенерировать динамическую библиотеку на лету, передать ее в виде двоичных данных, а затем использовать dlopen() и dlsym() для получения имени функции.   -  person Gilles Gouaillardet    schedule 17.07.2018
comment
Я хочу избежать чего-то очень динамичного. У меня есть только один исполняемый файл, который я запускаю с одного вычислительного узла. Из этого исполняемого файла я привязываю один процесс MPI к каждому вычислительному узлу (и генерирую второй уровень параллелизма с помощью pthread, что помогает мне создать один поток на ядро ​​процессора). Идея состоит в том, чтобы разрешить межузловые связи с MPI, но один процесс рассматривается как главный процесс и должен отправлять работу другим процессам, то есть набор задач, который содержит указатели на функции и данные. Я проверю страницы документации dlsym, если их можно использовать в этом случае. Спасибо за ответ !   -  person Adrien Roussel    schedule 17.07.2018


Ответы (1)


По предложению Gilles Gouillardet я попытался решить эту проблему с помощью функций dlopen() и dlsym(). Я попробовал небольшую программу, чтобы найти указатель на функцию helloWorld:

    #include <dlfcn.h>
    #include <iostream>

    void helloWorld(void)
    {
      std::cout << "Hello World !" << std::endl;
    }

    int main(int argc, char** argv)
    {
        void *handle;
        void (*task)(void);
        char* error;
        handle = dlopen(NULL, RTLD_LAZY);
        if(!handle)
        {
          fprintf(stderr, "dlopen error: %s\n", dlerror());
          exit(EXIT_FAILURE);
        }
        dlerror();

        *(void **) (&task) = dlsym(handle, "helloWorld");
        if( (error = dlerror()) != NULL)
        {
          fprintf(stderr, "dlsym error: %s\n", dlerror());
          exit(EXIT_FAILURE);
        }
        dlclose(handle);

      return EXIT_SUCCESS;
    }

Однако функция dlsym не может найти функцию helloWorld и возвращает сообщение об ошибке:

    dlsym error: (null)

Я не пытаюсь найти решение этой проблемы сейчас, но я ищу его. Если у кого-то есть опыт работы с функцией dlsymp, пожалуйста, поделитесь своим опытом со мной.

РЕДАКТИРОВАТЬ: я передал «NULL» в dlopen благодаря справочной странице dlopen (https://linux.die.net/man/3/dlsym), в котором указано:

Функция dlopen() загружает файл динамической библиотеки, названный строковым именем файла, заканчивающимся нулем, и возвращает непрозрачный «дескриптор» для динамической библиотеки. Если имя файла равно NULL, то возвращаемый дескриптор относится к основной программе.

person Adrien Roussel    schedule 17.07.2018
comment
Попробуйте объявить helloWorld как extern "C" void helloWorld, чтобы избежать искажения имени. - person G.M.; 17.07.2018
comment
Так что на самом деле extern C был частью решения, спасибо G.M! Вторая часть заключается в том, что я не компилировал свою программу со следующими параметрами: › -Wl, --export-dynamic - person Adrien Roussel; 17.07.2018