在MPI和C中,如何将结构信息的结构发送到从进程并接收它们?

在MPI和C中,如何将结构信息的结构发送到从进程并接收它们?,c,struct,mpi,C,Struct,Mpi,如代码所示,我在c中有两个结构。在一些输入读取和初始化_pop(parent_pop)后,生成包含4个个体的parent_pop。然后我必须将每个个体发送到每个进程(4个进程),以评估并在每个进程上生成新个体(总共仍然是4个个体),然后在主进程中接收这4个新个体,形成一个称为child_pop的新群体。这是我的psudo程序。谢谢你的帮助。提前谢谢 typedef struct{ double *xreal; int **gene; double crowd_dist; } individual

如代码所示,我在c中有两个结构。在一些输入读取和初始化_pop(parent_pop)后,生成包含4个个体的parent_pop。然后我必须将每个个体发送到每个进程(4个进程),以评估并在每个进程上生成新个体(总共仍然是4个个体),然后在主进程中接收这4个新个体,形成一个称为child_pop的新群体。这是我的psudo程序。谢谢你的帮助。提前谢谢

typedef struct{
double *xreal;
int **gene;
double crowd_dist;
}
individual;

typedef struct
{
individual *ind;
}
population;



Here is the main program:
int main (int argc, char **argv)
{
population *parent_pop;
int i, my_id, num_procs;
MPI_Init(&argc, &argv);
// Find out process ID and process number //
MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
input_read();/*read input*/
initialize_pop (parent_pop);/*generate 4 individuals to form the parent_pop*/
MPI_Datatype MPI_individual;
int count = 3;
int blocklens[] = { 1, 1, 1 };
MPI_Aint disps[3];
MPI_Datatype old_types[] = { MPI_int, MPI_double, MPI_double };
disps[0] = offsetof(individual, *xreal);
disps[1] = offsetof(individual, **gene);
disps[2] = offsetof(individual, crowd_dist);
MPI_Type_struct(count, blocklens, disps, old_types, &MPI_individual);
MPI_Type_commit(&MPI_individual);

*********Part need help****************************
send each individual to each process;
*********Part need help****************************

evaluate(parent_pop);/*evaluate each individual in each process*/
genearte_new_pop(child_pop);/*generate 4 new individuals to form the child_pop*/

*********Part need help****************************
receive each individual information from the slave processes to get the child_pop in the master process
*********Part need help****************************

}

在这一点上,我决定对你的问题做出一个正式的回答,因为评论中有太多的内容让其他人无法理解

我认为您需要做的三件主要事情是(可能还有更多):

  • 在内存中连续分配
    int**gene
    ,以便能够通过MPI一次性发送
  • 确保为
    oldtypes
    声明的类型与
    单个结构的类型顺序相匹配
  • 确保计数正确反映数组中元素的实际数量(可能所有元素都应该是连续的,以便尽可能减少对您的影响)
  • 一旦您正确设置了
    MPI\u个人
    ,您应该能够使用
    MPI\u send
    MPI\u Recv
    对作为类型发送个人

    要扩展这些要点:

  • 在C语言中,当您有一个指向指针的指针(如
    int**gene
    )时,您首先为
    nRow
    指针分配内存,使其指向内存中每一行的整数。这个初始
    malloc
    gene[iRow]
    ,一个
    int*
    变量)的元素在内存中都是连续的。注意,这些元素最终实际指向的可能不是连续的;事实上,他们几乎可以肯定不是。然后,当您为每个行元素分配内存时(
    int*
    ),可由
    gene[iRow]访问,在内存中分配“代码> NCOL < /代码>整数,相邻行,行每行连续,行<代码> iRe> <代码>和<代码> iRO+ 1 可能不会直接分配。在C++中,<代码> new < /COD>和<代码> new */COD>完全相同的工作。
  • 为了解决这个问题,我建议您创建一个临时变量,比如
    geneTemp
    ,这将是分配内存本身的方式

    int *geneTemp;
    geneTemp = (int *)malloc(nRow*nCol*sizeof(int));
    
    现在有了一个连续的内存块(nRow*nCol整数),您可以使用如下方法将原始
    int**gene
    指向该内存块中的正确点:

    int **gene;
    for (int iRow = 0; iRow < nRow; ++iRow) {
        gene[iRow] = &geneTemp[iRow*nCol + 0];
    }
    
    以匹配您的
    个人
    结构

  • 现在,当您设置
    MPI\u individual
    类型时,您必须实际发送每个数组中的值。发送指针没有意义,因为每个MPI进程都有不同的内存空间。进程0中的地址
    55
    与进程1中的地址
    55
    完全不同

  • 要发送实际数据,而不是指针,请执行以下操作:

    int blocklens[3] = { nReals, nRows*nCols, 1 };
    MPI_Aint disps[3];
    disps[0] = offsetof(individual, xreal[0]);
    disps[1] = offsetof(individual, gene[0][0]);
    disps[2] = offsetof(individual, crowd_dist);
    
    (至少是这样……我不知道什么是
    offsetof()
    ,但我认为这里应该这样使用它。我还没有测试过这段代码。)


    我希望这能更清楚地解释内存是如何设置的,尤其是如何为MPI派生的数据类型设置它。

    我发现有几件事是错误的:(1)发送
    int**gene
    不会很简单,因为当分配内存时,它不会是连续的-只有每一行在内存中是连续的。(2)您的类型与
    单个结构本身不匹配。它应该是
    {MPI\u double,MPI\u int,MPI\u double}
    (3)您的计数不正确,因为它们必须反映数组
    xreal
    gene
    中的实际元素数(必须是连续的,才能使数据类型正确)。为了回答您的实际问题:
    MPI_Send
    MPI_Recv
    使用此数据类型应该可以。非常感谢。我是一名编程初学者。如果可能,请您详细说明这些(1)由于此程序中的其他功能,我必须使用**基因,那么我应该如何发送**基因?(2)计数不是派生类型元素的块数吗?它应该等于块透镜阵列的大小吗?(3)再次感谢您的回答!(1)当您首次分配
    基因
    阵列时,您必须在连续内存中分配它(通常通过制作1D阵列完成)。如果您确实想保持程序的其余部分不变,那么首先将
    geneTemp
    分配为1D,并将2D数组
    gene
    的每个指针设置为与1D数组
    geneTemp
    的内存位置相对应。这并不漂亮,但意味着您不必更改程序的任何其他部分。(2)是的,通过MPI发送的计数应该是数组的大小。谢谢!如果可能的话,请告诉我为geneTemp和gene分配的基本代码。另外,*xreal怎么样,如何将该指针指向的数组传输到其他进程?谢谢你的好意。还有一个小问题是,由于dual结构现在不同了(gene是nrow*ncol,xreal是nreal),我应该如何决定MPI_Type_结构中的计数?再次感谢!n此外,我已经测试了代码,offsetof是为了找到地址。offsetof(个人,xreal[0])似乎是会导致错误。正在寻找解决方案。你是说每个结构都有不同的nrow/ncol吗?那么,是的,你会遇到一个问题:你不能创建一个大小不断变化的MPI数据类型。我认为很遗憾,每次你想发送结构时,你都必须先发送第一个数组,然后是第二个数组,然后是t他输入int,然后在另一边重建结构……至于
    offset()
    函数,如果它接受的话
    int blocklens[3] = { nReals, nRows*nCols, 1 };
    MPI_Aint disps[3];
    disps[0] = offsetof(individual, xreal[0]);
    disps[1] = offsetof(individual, gene[0][0]);
    disps[2] = offsetof(individual, crowd_dist);