简体   繁体   English

在C中的MPI中,如何创建结构的结构并将其发送到多个进程

[英]in MPI in c how to create a struct of structs and send it to multiple process

so I have this struct 所以我有这个结构

typedef struct{
     float x;
     float y;
     int centroid;
}point;

And I also have this struct 我也有这个结构

typedef struct{
     int csize;//the current size
     int tsize;//the total size
     point * data;//the data carried
}ArrayList;

These second struct forms a dynamically growing array in C (Functions for dynamic growth is implemented and working fine). 这些第二个结构在C中形成一个动态增长的数组(实现动态增长的功能并正常工作)。 how exactly do I create a struct of that and send it using MPI in c? 我如何确切地创建一个结构并在C中使用MPI发送它? I looked at other posts like struct serialization in C and transfer over MPI and others but I could't find a solution to my problem. 我看过其他文章,例如C中的struct序列化以及通过MPI和其他文件的传输,但是我找不到解决问题的方法。

I'd appreciate some help. 我将不胜感激。

Best, Gedo 最好,盖多

EDIT- the possible duplicate does NOT solve my question, my question is pertaining a struct containing a pointer to an array of structs which is dynamically growing. 编辑-可能的重复项不能解决我的问题,我的问题是关于一个包含指向动态增长的结构体数组的指针的结构体。 the duplicate question pertains having an array of native types in a struct. 重复的问题涉及在结构中具有一组本机类型。

Manually serializing the array of structs to a buffer and sending the buffer is a terrible idea, as it introduces another memory copy on both the send and receive side. 手动将结构数组序列化到缓冲区并发送缓冲区是一个糟糕的主意,因为它在发送和接收端都引入了另一个内存副本。

Sending an array of MPI structures is no different than an array of any other object; 发送MPI结构的数组与其他任何对象的数组没有什么不同。 you just have to create a structure type - there are many examples here and elsewhere - making sure to calculate offsets and sizes as there may be padding inserted in your structs. 您只需要创建一个结构类型- 这里其他地方很多 示例 -确保计算偏移量和大小,因为结构中可能插入了填充。 Then just pass an array of them: 然后只需传递它们的数组即可:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "mpi.h"

typedef struct{
    float x;
    float y;
    int centroid;
} point;

typedef struct{
    int csize;//the current size
    int tsize;//the total size
    point * data;//the data carried
} ArrayList;


int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);

    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    assert( size >= 2 );
    const int npts_avail=20;
    point points[npts_avail];

    ArrayList list;
    list.data = points;

    if (rank == 0) {
        int npts_used=10;
        list.csize = npts_used;
        list.tsize = npts_avail;
        for (int i=0; i<list.csize; i++) {
            points[i].x = 1.*i;
            points[i].y = -2.*i;
            points[i].centroid = i;
        }
    }

    const int nfields=3;
    MPI_Aint disps[nfields];
    int blocklens[] = {1,1,1};
    MPI_Datatype types[] = {MPI_FLOAT, MPI_FLOAT, MPI_INT};

    disps[0] = offsetof( point, x );
    disps[1] = offsetof( point, y );
    disps[2] = offsetof( point, centroid );

    MPI_Datatype istruct, pstruct;
    MPI_Type_create_struct(nfields, blocklens, disps, types, &istruct );
    MPI_Type_create_resized( istruct, 0, (char *)&(points[1]) - (char *)(&points[0]), &pstruct );
    MPI_Type_commit(&pstruct);

    if (rank == 0) {
        MPI_Send( &(list.csize), 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
        MPI_Send( &(list.tsize), 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
        MPI_Send( list.data, list.csize, pstruct, 1, 0, MPI_COMM_WORLD);
    } else if (rank == 1) {
        MPI_Recv( &(list.csize), 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Recv( &(list.tsize), 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        MPI_Recv( list.data, list.csize, pstruct, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    }

    if (rank == 1) {
        printf("Received: \n");
        for (int i=0; i<list.csize; i++) {
            printf(" (%f, %f): %d\n", points[i].x, points[i].y, points[i].centroid);
        }
    }

    MPI_Finalize();
}

Running gives the expected output: 运行给出预期的输出:

$ mpirun -np 2 ./structs
Received:
 (0.000000, -0.000000): 0
 (1.000000, -2.000000): 1
 (2.000000, -4.000000): 2
 (3.000000, -6.000000): 3
 (4.000000, -8.000000): 4
 (5.000000, -10.000000): 5
 (6.000000, -12.000000): 6
 (7.000000, -14.000000): 7
 (8.000000, -16.000000): 8
 (9.000000, -18.000000): 9

Note that you could construct an MPI struct of ArrayList, as well, and use that - except that the displacement of data may have to be changed every time you resend (on the sending side), and on the receiving side it can't even be determined until you know the amount of data you'll need to receive. 请注意,您也可以构造一个ArrayList的MPI结构,并使用它-除了每次重新发送时(在发送方)必须更改数据的位移,而在接收方甚至不能更改数据的位移。确定,直到您知道需要接收的数据量。 So best are to send the sizes first (in two messages, as I have here, or better yet, to send it as one message of two ints), and then send the array of structs as shown. 最好的方法是先发送大小(按两条消息发送,如我在此处所示,或者更好的是,将其作为两个整数的一条消息发送),然后发送结构数组,如图所示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM