在MPI和C中,如何将结构信息的结构发送到从进程并接收它们?
如代码所示,我在c中有两个结构。在一些输入读取和初始化_pop(parent_pop)后,生成包含4个个体的parent_pop。然后我必须将每个个体发送到每个进程(4个进程),以评估并在每个进程上生成新个体(总共仍然是4个个体),然后在主进程中接收这4个新个体,形成一个称为child_pop的新群体。这是我的psudo程序。谢谢你的帮助。提前谢谢在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
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
对作为类型发送个人
要扩展这些要点:
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);