【问题标题】:Vector Usage in MPI(C++)MPI(C++) 中的向量使用
【发布时间】:2011-02-02 12:42:08
【问题描述】:

我是 MPI 编程的新手,仍然在学习,在通过定义结构创建派生数据类型之前我是成功的。现在我想在我的结构中包含 Vector,并希望通过 Process 发送数据。例如:

struct Structure{

//Constructor 
Structure(): X(nodes),mass(nodes),ac(nodes) {

//code to calculate the mass and accelerations
}
//Destructor
Structure() {}

//Variables
double radius;
double volume;
vector<double> mass;
vector<double> area;

//and some other variables

//Methods to calculate some physical properties

现在使用 MPI,我想跨进程发送结构中的数据。我可以创建包含的 MPI_type_struct 向量并发送数据吗?

我尝试通过论坛阅读,但我无法从那里给出的回复中获得清晰的画面。希望我能有一个清晰的想法或方法来发送数据

PS:我可以单独发送数据,但如果我们认为域非常大(比如 10000*10000),则使用 MPI_Send/Recieve 发送数据会产生开销

【问题讨论】:

    标签: c++ vector parallel-processing mpi


    【解决方案1】:

    在 MPI 中定义结构很痛苦。我认为更简单的方法是使用保证 STL 向量具有连续分配内存的事实。也就是说,您可以通过获取指向第一个元素的指针来将它们视为 C 数组。

    std::vector<float> data;
    // ... add elements to your vector ...
    MPI_Send(&data.front(), data.size(), MPI_FLOAT, 0, 1, MPI_COMM_WORLD);
    

    【讨论】:

    • 感谢您的快速响应,这里的问题是我想一次发送整个结构,而不是发送向量和其他数据类型的单个变量,从而减少进程之间的通信开销......和我要发送 10 个向量进行通信 ....因此会导致计算时间变慢,从而降低效率
    • @lsk1985,好的,我对 MPI 的经验还不够,无法提供太多帮助。对不起。我会小心避免在进程之间发送指针(而不是它们指向的数据)。
    • 如果你有一个指针数组,创建一个 MPI_Type_hindexed,它是一行块,位移以字节表示。它只需要一点地址算法。
    【解决方案2】:

    我在这里描述了我对类似问题的解决方案:

    Message Passing Arbitrary Object Graphs?

    请记住,您可以从先前定义的自定义 MPI 数据类型创建自定义 MPI 数据类型。例如,您可以定义一个 Struct 来描述结构的单个实例的布局和内容,然后定义一个来自这些 Struct 数据类型的向量,用于整个对象向量。哎呀,如果你有几个这样的向量,你可以创建第三层抽象,从 Structs 的向量创建一个 HIndexed 数据类型,然后用一条消息将它们全部发送。

    在我上面链接的帖子中,您将找到各种自定义 MPI 数据类型描述的链接,这应该有助于您确定正确的方法。

    【讨论】:

    • 感谢您的链接以及您如何解决问题的想法
    【解决方案3】:

    我做的事情和你一样,我知道我的处理器架构是同质的。通过使用Boost serialization,我避免了大量的字节交换和大量的 MPI 打包和解包。

    发送:

      ostringstream oss;
      {
        binary_oarchive oa(oss);
        oa << BOOST_SERIALIZATION_NVP(myStruct);
      }
    
      MPI::COMM_WORLD.Send(oss.str().c_str(),
                           oss.str().size(),
                           MPI::Datatype(MPI_BYTE),
                           MpiLibWrapper::DEST_PROC_RANK,
                           MpiLibWrapper::MY_STRUCT_TAG);
    

    接收:

        vector<char> incomingBuffer(MAX_BUFFER_SIZE);
    
        MPI::COMM_WORLD.Recv(&incomingBuffer[0], incomingBuffer.size(),
                             MPI::Datatype(MPI_BYTE),
                             MpiLibWrapper::SRC_PROC_RANK,
                             MpiLibWrapper::MY_STRUCT_TAG,
                             msgStatus);
        if (MpiLibWrapper::ErrorOccurred(msgStatus.Get_error(),
                                         info.logging)) {
          break;
        }
        incomingBuffer.resize(msgStatus.Get_count(MPI::Datatype(MPI_BYTE)));
    
        if (incomingBuffer.size() > 0) {
          // Shockingly, this does not result in a memory allocation.
          istringstream iss(string(&incomingBuffer[0], incomingBuffer.size()));
    
          binary_iarchive ia(iss);
    
          ia >> BOOST_SERIALIZATION_NVP(myStruct);
        }
    

    【讨论】:

    • 我对Boost序列化一无所知,可能我需要花一些时间了解它,看看它是否解决了我遇到的问题。谢谢您的建议
    【解决方案4】:

    嗯...仅当您保证所有参与机器上的数据布局完全相同时,才能将 C/C++ 结构作为数据流发送。一般来说,这是行不通的。另外,为了代码的清晰和显示意图,有些人认为发送打包为 MPI 派生数据类型的结构是 +1。

    【讨论】:

      【解决方案5】:

      我当然不是 MPI 数据结构专家,但我认为这做不到。原因是基本上你有一个结构,其中包含指向要发送的数据的指针。所有 MPI 数据类型函数都假定您要发送的数据位于内存的连续区域中。如果向量的最大大小是固定的,你可以这样做

      double radius;
      double volume;
      int mass_size;
      int area_size;
      double mass[MASS_MAXLEN];
      double area[AREA_MAXLEN];
      

      然后只发送已填写的元素。

      或者,您可以在发送之前将数据自己打包到一个数组中并发送该数组。您必须进行一些分析,看看这是否比单独发送更快。

      【讨论】:

      • 是的,我需要尝试看看发送单个向量是否更简单,感谢您的建议
      • "所有 MPI 数据类型函数都假定您要发送的数据位于内存的连续区域中。" - 虽然这是真的,但您可以定义代表任意内存布局的自定义 MPI 数据类型(请参阅我的答案)。因此,您可以从指针定义数据类型,然后将消息作为该数据类型的单个实例发送,从而获得所需的结果。
      猜你喜欢
      • 2013-09-20
      • 2012-10-23
      • 2012-11-24
      • 2014-03-10
      • 1970-01-01
      • 2021-01-20
      • 2016-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多