使用 MPI/OpenMP 的具有派生数据类型(嵌套类对象)容器的 C++ 程序

Posted

技术标签:

【中文标题】使用 MPI/OpenMP 的具有派生数据类型(嵌套类对象)容器的 C++ 程序【英文标题】:C++ program with derived data type (nested class object) container using MPI/OpenMP 【发布时间】:2018-04-03 23:25:40 【问题描述】:

我用 C++11 开发了一个程序,我想加快性能。

我会用一个简单的例子来展示程序的结构(不完整)。

   //main.cpp
   #include "a.h"
   int main()
   
     std::vector<a> a_container;
     for (auto i=0; i< 10K; i++)
     
       a a_obj;
       a_container.push_back(a_obj);
     

     for(time = 1; time< long_time; time++)
     
       //i used openmp here already
       for (auto i=0; i< 10K; i++)
       
         a_container[i].dosomething();
       
       for (auto i=0; i< 10K; i++)
       
         a_container[i].update();
       
     
     return 1;
   
   //a.cpp
   //a.h
   #include "b.h"
   class a
   
     int d;
     b b_obj;
     int dosomething();
   
   //b.cpp
   //b.h

   class b
   
      int c;
      double d;
      int dosomething();
   

所以为了加快程序,我想同时使用 MPI 和 OpenMP,主要用于循环(可能高达 100 万~10 亿个实例)。

类对象 a 和 b 都包含复杂的成员变量(标准和其他容器等)和函数。

通过使用 OpenMP,我可以利用一个具有所有内核/线程的 HPC 节点。但是如果我想使用 MPI,我需要将所有实例分发到许多节点。

我还没有找到一个好的解决方案,我现在最接近的是; http://mpi-forum.org/docs/mpi-2.2/mpi22-report/node83.htm#Node83 和https://blogs.cisco.com/performance/how-to-send-cxx-stl-objects-in-mpi 请提供一些建议。谢谢。

【问题讨论】:

【参考方案1】:

通过 MPI 发送不可复制的对象与通过任何其他字节传输发送它们相同:您必须进行序列化。如果有帮助,您可以使用stringstream 在任一端保存缓冲区。

但是,您很可能根本不应该这样做。 创建您的对象所需的数据(例如、循环边界和初始值)可能比用于持续计算的形式更小更简单。改为发送它,您可以并行创建复杂的对象并减少通信。 (如果参数是静态已知的,则无需发送任何内容:每个进程都可以开始处理已知的初始化。)

【讨论】:

感谢您的想法。根据您的第二个选项,我现在有了一个通用的解决方案。为了利用多个节点,我可以使用 MPI 在节点之间进行通信。因为大多数成员变量都可以在本地读取或计算,所以我只需要传递某种索引来控制节点和对象实例。有了这个,我需要一个并行输入/输出 (PIO) 方案来允许所有节点都可以读取和写入数据。困难的部分是所有实例都会在时间步内与其他实例进行通信,因此通信是不可避免的,但可以是简单的结构(字符串流等)。

以上是关于使用 MPI/OpenMP 的具有派生数据类型(嵌套类对象)容器的 C++ 程序的主要内容,如果未能解决你的问题,请参考以下文章

OpenMP 和 MPI 混合程序

OpenMP 和 MPI 交互

确保混合 MPI / OpenMP 在不同的内核上运行每个 OpenMP 线程

LSF 中的混合 MPI/OpenMP

基于 MPI/OpenMP 混合编程的大规模多体(N-Body)问题仿真实验

大数据系列9:mpi4py高性能计算