【问题标题】:How to MPI Send and Recv Nested struct with Pointer Array of Struct?如何使用结构的指针数组 MPI 发送和接收嵌套结构?
【发布时间】:2022-01-05 06:35:25
【问题描述】:

下面是结构体声明和代码:

struct cell_struct {
    int x, y;
    bool isWater, isPort, isRock;
    struct port_struct port_data;
    struct ship_struct *ships_data[MAX_SHIPS_PER_CELL];
    int number_ships;
};

struct ship_struct {
    int route, totalHoursAtSea, hoursAtSeaThisJourney, id, numberPassengers, euclideanPlannedDistance;
    bool willMoveThisTimestep;
};

// Data associated with each port
struct port_struct {
    int shipsInPastHundredHours[10];
    int port_index, passengersShipped;
    double totalFeesCollected;
};

struct cell_struct *domain_test;

domain_test = (struct cell_struct *) malloc(
            sizeof(struct cell_struct) * (mpi_info->local_size_x + 2) * simulation_configuration->size_y);

使用以下发送和接收,我能够发送和接收 domain_test,但在发送和接收后无法从 domain_test 访问 ship_data。有什么帮助吗?

MPI_Send(&domain_test[mpi_info->local_size_x_end * simulation_configuration->size_y + i], sizeof(struct cell_struct), MPI_BYTE, 1, i, MPI_COMM_WORLD);

MPI_Recv(&domain_test[0],sizeof(struct cell_struct) * simulation_configuration->size_y, MPI_BYTE, 0, 0, MPI_COMM_WORLD, &status);


【问题讨论】:

  • 没有简单的方法。一种选择是创建派生数据类型,以便您可以一次性发送/接收,但这有点乏味。另一种选择是“内联”ships_data(例如声明struct ship_struct ships_data[MAX_SHIPS_PER_CELL];)。另一种选择是一次发送一个ships_data。最后但同样重要的是,您可以使用临时缓冲区和MPI_Pack()/MPI_Unpack() 您的数据,以便一次性发送/接收缓冲区。

标签: c mpi hpc


【解决方案1】:

您的代码中的主要问题是cell_struct 存储了一个静态数组指向船舶的指针,这意味着船舶本身的数据可能到处都是。如果你改为存储一个静态的船舶数组as suggested by Gilles in the comments,你有一块连续的内存需要发送。您甚至可以使用count=sizeof(cell_struct)type=MPI_BYTE then(就像您现在所做的那样)或@Gilles 指示的任何方法发送它。

您的代码的结果是,当分配给一个单元格时,船只现在被复制,而不仅仅是设置一个指针。如果船上的数据很少,这不是问题,如此处所示,但如果复制成本很高,则可能会使代码变慢。

【讨论】:

    【解决方案2】:

    对于系统之间复杂数据结构的传输,如果您不希望按照 Jonas 的建议将结构安排为一个连续的内存块,那么这就是某种形式的序列化发挥作用的地方。

    使用 C 编程语言,要使用序列化技术,您几乎会被模式优先所困扰,例如 Google 协议缓冲区(请参阅 C versionGoogle's page)。其他语言(如 Java 和 C#)内置了序列化,因此您可以选择代码优先或模式优先序列化。

    最简短的概述是:

    1. 编写描述数据结构的架构文件(GPB 的 .proto),就像在 C 中使用 struct{} 定义一样
    2. 使用提供的工具编译架构,以输出使用 struct{} 定义数据结构的 C 代码,以及一组可以将它们序列化/反序列化到线格式/从线格式中序列化/反序列化的函数
    3. 在您的项目中使用生成的 C 代码。您使用生成的结构体根据需要声明变量,并使用序列化/反序列化函数来生成/使用 MPI_BYTE 缓冲区,
    4. 您使用 MPI 发送/接收这些 MPI_BYTE 缓冲区

    这样做有一些基本优势:

    • 您的分布式系统可以是异构的。因此,例如,您不必在运行 Windows 10 64 位的 PC 上运行 64 位 C,而是在各处使用相同的编译器进行编译,您可以混合和匹配语言、机器类型、操作系统、编译器等;
    • 您可以将数据结构布置得合理,而不是为了在连续内存中存储而使它们更加模糊。

    我的猜测是,如果您为了发送/接收数据而重新安排内存以构建/解构连续内存,那么(从运行时长度的角度来看)序列化会更好GPB 等技术。

    【讨论】:

      猜你喜欢
      • 2016-09-18
      • 2011-07-04
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      • 2011-08-23
      • 2012-09-23
      • 2011-08-23
      • 1970-01-01
      相关资源
      最近更新 更多