gpt4 book ai didi

c - 具有包含动态分配数组的自定义数据类型的 MPI_reduce() : segmentation fault

转载 作者:行者123 更新时间:2023-12-02 02:36:41 24 4
gpt4 key购买 nike

我不明白为什么一旦我使用包含动态分配数组的自定义 MPI 数据类型,MPI_Reduce() 就会出现段错误。有人知道吗 ?以下代码在 MPI_Reduce() 内部使用 2 个处理器时会崩溃。但是,如果我删除成员 double *d int MyType 并相应地更改运算符和 MPI 类型例程,则减少过程不会出现任何问题。

使用动态分配的数组是否存在问题,或者我所做的事情是否存在根本性错误:

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



typedef struct mytype_s
{
int c[2];
double a;
double b;
double *d;
} MyType;



void CreateMyTypeMPI(MyType *mt, MPI_Datatype *MyTypeMPI)
{
int block_lengths[4]; // # of elt. in each block
MPI_Aint displacements[4]; // displac.
MPI_Datatype typelist[4]; // list of types
MPI_Aint start_address, address; // use for calculating displac.
MPI_Datatype myType;

block_lengths[0] = 2;
block_lengths[1] = 1;
block_lengths[2] = 1;
block_lengths[3] = 10;

typelist[0] = MPI_INT;
typelist[1] = MPI_DOUBLE;
typelist[2] = MPI_DOUBLE;
typelist[3] = MPI_DOUBLE;

displacements[0] = 0;

MPI_Address(&mt->c, &start_address);
MPI_Address(&mt->a, &address);
displacements[1] = address - start_address;

MPI_Address(&mt->b,&address);
displacements[2] = address-start_address;

MPI_Address(&mt->d, &address);
displacements[3] = address-start_address;

MPI_Type_struct(4,block_lengths, displacements,typelist,MyTypeMPI);
MPI_Type_commit(MyTypeMPI);
}




void MyTypeOp(MyType *in, MyType *out, int *len, MPI_Datatype *typeptr)
{
int i;
int j;

for (i=0; i < *len; i++)
{
out[i].a += in[i].a;
out[i].b += in[i].b;
out[i].c[0] += in[i].c[0];
out[i].c[1] += in[i].c[1];

for (j=0; j<10; j++)
{
out[i].d[j] += in[i].d[j];
}
}
}




int main(int argc, char **argv)
{
MyType mt;
MyType mt2;
MPI_Datatype MyTypeMPI;
MPI_Op MyOp;
int rank;
int i;

MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);


mt.a = 2;
mt.b = 4;
mt.c[0] = 6;
mt.c[1] = 8;
mt.d = calloc(10,sizeof *mt.d);
for (i=0; i<10; i++) mt.d[i] = 2.1;

mt2.a = 0;
mt2.b = 0;
mt2.c[0] = mt2.c[1] = 0;
mt2.d = calloc(10,sizeof *mt2.d);


CreateMyTypeMPI(&mt, &MyTypeMPI);
MPI_Op_create((MPI_User_function *) MyTypeOp,1,&MyOp);

if(rank==0) printf("type and operator are created now\n");

MPI_Reduce(&mt,&mt2,1,MyTypeMPI,MyOp,0,MPI_COMM_WORLD);

if(rank==0)
{




for (i=0; i<10; i++) printf("%f ",mt2.d[i]);
printf("\n");
}

free(mt.d);
free(mt2.d);
MPI_Finalize();

return 0;
}

最佳答案

让我们看看你的结构:

typedef struct mytype_s
{
int c[2];
double a;
double b;
double *d;
} MyType;

...

MyType mt;
mt.d = calloc(10,sizeof *mt.d);

以及您对此结构作为 MPI 类型的描述:

displacements[0] = 0;

MPI_Address(&mt->c, &start_address);
MPI_Address(&mt->a, &address);
displacements[1] = address - start_address;

MPI_Address(&mt->b,&address);
displacements[2] = address-start_address;

MPI_Address(&mt->d, &address);
displacements[3] = address-start_address;

MPI_Type_struct(4,block_lengths, displacements,typelist,MyTypeMPI);

问题是,这个 MPI 结构永远仅适用于您在此处定义中使用的结构的一个实例。你根本无法控制 calloc()决定从中获取内存;它可以位于虚拟内存中的任何位置。您创建并实例化的下一个类型是d 的位移。数组将完全不同;即使使用相同的结构,如果您使用 realloc() 更改数组的大小当前mt ,它最终可能会有不同的位移。

因此,当您使用其中一种类型发送、接收、减少或执行其他任何操作时,MPI 库将尽职尽责地进行可能无意义的位移,并尝试从那里读取或写入,这可能会导致段错误.

请注意,这不是 MPI 的事情;在使用任何低级通信库时,或者尝试从磁盘写出/读入时,您都会遇到同样的问题。

您的选项包括手动将数组“编码”到消息中,可以使用其他字段,也可以不使用其他字段;或者为 d 所在的位置添加一些可预测性,例如将其定义为某个已定义最大大小的数组。

关于c - 具有包含动态分配数组的自定义数据类型的 MPI_reduce() : segmentation fault,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13434879/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com