【问题标题】:Send a function to MPI processes向 MPI 进程发送函数
【发布时间】:2018-12-24 03:50:34
【问题描述】:

我目前正在为分布式系统编写运行时系统软件,然后我打算评估一些并行管理的东西。我的运行时系统依赖于 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 进程发送一个唯一的 ID。 你有什么想法可以解决我的问题吗?

谢谢!

【问题讨论】:

  • 你怎么能不知道“不同类型任务的数量”随时呢?您对局限性的分析非常中肯。你想要的几乎是不可行的,除非是真正的 hacky hack。
  • 嗯,其实我可以知道我在执行过程中会有多少种类型。而且,对于这个问题,实际上我正在寻找一种技巧,使我能够避免这些限制。也许,在 MPI 进程上启动一个“子程序”而不是发送函数或函数指针是一种技巧。但是,我不知道它的可行性,也许有人已经面临类似的问题?
  • 通过 MPI 通信功能是闻所未闻的。但是您绝对可以使用 MPI_Comm_spawnMPI_Comm_spawn_multiple 从一组正在运行的进程中创建和终止一组进程,如果这就是您启动“子程序”的意思
  • 如果您所有的 MPI 任务都运行相同的二进制文件,则所有子例程都应该映射到相同的地址,因此发送指针可能起作用。如果所有子例程都在所有 MPI 任务的地址空间中,那么您可以传递子例程名称(例如以空结尾的字符串)并使用 dlsym() 查找其地址。
  • 如果你做一些非常动态的事情,一个hacky选项是“动态”生成一个动态库,将它作为二进制数据传输,然后使用dlopen()dlsym()检索函数名.

标签: c++ pthreads mpi function-pointers send


【解决方案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 功能有任何经验,请与我分享您的经验。

编辑:我通过 dlopen 手册页 (https://linux.die.net/man/3/dlsym) 将“NULL”传递给 dlopen,其中指定:

函数 dlopen() 加载以 null 结尾的字符串文件名命名的动态库文件,并为动态库返回一个不透明的“句柄”。如果 filename 为 NULL,则返回的句柄是主程序的。

【讨论】:

  • 尝试将helloWorld 声明为extern "C" void helloWorld 以避免名称混淆。
  • 所以事实上,"extern "C" " 是解决方案的一部分,感谢 G.M!第二部分是我省略了使用以下选项编译我的程序: > -Wl,--export-dynamic
猜你喜欢
  • 2017-01-20
  • 2021-07-20
  • 1970-01-01
  • 1970-01-01
  • 2018-07-21
  • 1970-01-01
  • 1970-01-01
  • 2021-09-27
  • 2011-02-24
相关资源
最近更新 更多