gpt4 book ai didi

c - MPI_Allreduce 在动态结构数组内的数组上

转载 作者:太空宇宙 更新时间:2023-11-03 23:47:38 25 4
gpt4 key购买 nike

我在 C 中有一个结构的动态数组。说:

int n=100;
struct particle{
double pos[3];
double force[3];
double mass;
int type;
};
struct particle *mypart;
mypart = (struct particle*) calloc(n,sizeof(struct particle));

在并行代码中,一些操作是在 mypart[i].force[j] 上完成的,最后我需要在这个数组上执行 MPI_Allreduce (maypart[i] .force).通过考虑 MPI_Type_create_struct 和其他 data_type 函数,我无法获得任何有效的解决方案来仅将结构内部的数组传递给其他核心。有人知道吗?

更新:关于代码的一些细节:这是一个分子动力学代码,其中每个粒子上的力是由于与其他粒子的相互作用。目的是拆分每个核心上的力计算。可以同时在不同的核上计算第 i 个粒子上的力。在力循环之后,作用在该粒子上的力应该被求和为每个粒子具有单一值力(3 个分量)。这是通过 MPI_Allreduce + MPI_SUM 函数完成的。我希望这可以阐明我要做什么。

最佳答案

您想要实现的目标并非不可能,但也并非微不足道。首先,您必须声明一个表示整个结构类型的数据类型或一个仅包含力的数据类型。要构建后者,请从适当位移的三个连续 double 开始:

MPI_Datatype type_force;
int blen = 3;
MPI_Aint displ = offsetof(struct particle, force);
MPI_Type types = MPI_DOUBLE;

MPI_Type_create_struct(1, &blen, &displ, &types, &type_force);

必须调整新数据类型的大小以匹配 C 结构的范围,以便我们可以直接访问多个数组元素:

MPI_Datatype type_force_resized;
MPI_Aint lb, extent;

MPI_Type_get_extent(type_force, &lb, &extent);
extent = sizeof(struct particle);
MPI_Type_create_resized(type_force, lb, extent, &type_force_resized);
MPI_Type_commit(&type_force_resized);

现在全局(全部)减少几乎归结为:

struct particle *particles = calloc(n, sizeof(struct particle));
MPI_Allreduce(mypart, particles, n, type_force_resized,
MPI_SUM, MPI_COMM_WORLD);

由于 MPI_(All)Reduce 不允许将不同的 MPI 数据类型用于源缓冲区和接收缓冲区,因此必须使用一组 struct particle 而不是只需 double[n][3]。结果将放在每个数组元素的 forces[] 字段中。

现在,问题是 MPI_SUM 不对派生数据类型进行操作。解决方案是声明自己的归约操作:

void force_sum(struct particle *in, struct particle *inout,
int *len, MPI_Datatype *dptr)
{
for (int i = 0; i < *len; i++)
{
inout[i].force[0] += in[i].force[0];
inout[i].force[1] += in[i].force[1];
inout[i].force[2] += in[i].force[2];
}
}

MPI_Op force_sum_op;
MPI_Op_create(force_sum, 1, &force_sum_op);

通过上述所有准备工作,减少量变为:

MPI_Allreduce(mypart, particles, n, type_force_resized,
force_sum_op, MPI_COMM_WORLD);

一个更简单的变体是,如果您首先将所有力聚集在一个double forces[n][3] 数组中。那么整个归约操作归结为:

double forces[n][3]; // Local forces
double total_forces[n][3]; // Total forces

... transfer mypart[i].force into forces[i] ...

MPI_Allreduce(forces, total_forces, 3*n, MPI_DOUBLE,
MPI_SUM, MPI_COMM_WORLD);
// Done

但是这种方法占用额外的内存,需要进行内存拷贝操作。

关于c - MPI_Allreduce 在动态结构数组内的数组上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29184378/

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