【问题标题】:MPI derived datatype for Eigen Array特征数组的 MPI 派生数据类型
【发布时间】:2018-02-26 04:02:54
【问题描述】:

我正在做一个项目,我像这样使用本征数组创建了一个类

class Cartesian{
   public:
      double x() const { return r_(0); }
      double y() const { return r_(1); }
      double z() const { return r_(2); }
   private:
      Eigen::Array3d r_; 
 }

 Eigen::Array<Cartesian, Eigen::Dynamic, 1> Cart_Array(10); 

所以现在我想使用 MPI_Send 将 Cart_Array 从 Proc 0 发送到 Proc 1。最好的方法是什么?我想创建一个派生的 MPI 数据类型;例如,Cart_Type,然后将其发送为

 MPI_Send(&Cart_Array, 10, Cart_Type, 1, TAG, MPI_COMM_WORLD).

我知道如何使用 MPI_Type_create_struct 等为简单的事物创建 MPI 派生类型。但是对于我展示的案例,我不知道如何去做。请让我看看。如果可能的话,我想避免使用其他库,例如 Boost。

编辑:

我问这个问题是因为我想避免使用序列化方法。那是因为这是一个强调效率的大型计划的一部分。

【问题讨论】:

    标签: c++ types mpi eigen


    【解决方案1】:

    您应该执行以下操作。只需将一个或多个Cartesian 序列化为双精度向量,发送和接收这些双精度并反序列化。我希望它可以编译,因为我只是在没有 MPI 的机器上输入了它。我没有安装 Eigen,但你明白了。

    class Cartesian{
    public:
      double x() const { return r_(0); }
      double y() const { return r_(1); }
      double z() const { return r_(2); }
      std::vector<double> const& r() const { return r_; };
      Cartesian* operator=(std::vector<double> const& r) {r_ = r;} 
    private:
      std::vector<double> r_;
      //Eigen::Array3d r_; 
    };
    
    // Send vector of Cartesian
    void sendData(std::vector<Cartesian> const& v) {
      std::vector<double> data;
      for (auto const& i : v) {
        data.insert(data.end(), v.r().begin(), v.r().end());
      }
      MPI_Send(data.begin(), data.size(), MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
    }
    
    // Receive vector of Cartesian
    std::vector<Cartesian> recvData() {
    
      int n;
      MPI_Status status;
      MPI_Probe(0, 0, MPI_COMM_WORLD, &status); // Incoming?
      MPI_Get_count(&status, MPI_INT, &n); // Number of incoming
    
      std::vector<Cartesian> v;
      if (n>0) {
        std::vector<double>(n);
        MPI_Recv(n.begin(), n, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        v.resize(n/3);
        int i = 0;
        for (auto i : v) {
          i.r(*b.begin()+3*i);
          ++i;
        }
      }
      return v;
    
    }
    
    int main() {
    
      MPI_Init(NULL, NULL);
    
      int size, rank;
      MPI_Comm_size(MPI_COMM_WORLD, &size);
      MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    
      std::vector<Cartesian> data;
      if (rank == 0) {
        data.resize(1000);
        sendData(data);
      } else {
        data = recvData();
      }
    
      MPI_Finalize();
    
    }
    

    【讨论】:

    • 谢谢。我实际上在我以前的代码版本中使用了序列化,但它涉及复制和移动数据。我想使用派生数据类型来希望它可能更有效,因为我展示的代码是大型高性能计算程序的一部分。除了你没有它之外,你使用 std::vector 而不是 Eigen 的任何特殊原因?
    • 您使用的是什么网络结构?如果您不在 Infiniband 上,甚至不要开始考虑这条路线。另外,如果我是你,我会分析代码并找出,如果你没有优化 0.001%。我非常怀疑与网络和计算时间相比,您是否能够对序列化进行评估。
    • 我在几个平台上使用代码,其中一些使用 Infiniband。感谢您的帮助。
    猜你喜欢
    • 2012-02-11
    • 2012-02-03
    • 2014-12-03
    • 2014-08-08
    • 2017-05-27
    • 2012-04-01
    • 2012-11-27
    • 2018-10-11
    相关资源
    最近更新 更多