Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
结构的动态数组中的数组上的MPI_Allreduce_C_Arrays_Structure_Mpi - Fatal编程技术网

结构的动态数组中的数组上的MPI_Allreduce

结构的动态数组中的数组上的MPI_Allreduce,c,arrays,structure,mpi,C,Arrays,Structure,Mpi,我有一个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]上完成的,最后我需

我有一个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]
上完成的,最后我需要在jsut这个数组上执行MPI\u Allreduce(
maypart[i].force
)。考虑到
MPI\u Type\u create\u struct
以及其他数据类型的函数,我无法得到任何将结构内部的数组传递给其他内核的有效解决方案。 有人知道吗


更新:关于代码的一些细节:这是一个分子动力学代码,其中每个粒子上的力是由于与其他粒子的相互作用。目的是在每个堆芯上拆分力计算。第i个粒子上的力可以同时在不同的磁芯上计算。在“力循环”之后,应将此粒子上的力求和为每个粒子提供一个值“力”(3个分量)。这是通过MPI_Allreduce+MPI_SUM函数实现的。我希望这能说明我要做什么。

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

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);
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
由于
MPI(All)Reduce
不允许源缓冲区和接收缓冲区使用不同的MPI数据类型,因此必须使用
struct particle
数组,而不是简单地使用
double[n][3]
。结果将放在每个数组元素的
forces[]
字段中

现在的问题是,
MPI\u 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);

一种更简单的方法是,首先将所有力聚集在一个
双力[n][3]
数组中。然后,整个还原操作归结为:

struct particle *particles = calloc(n, sizeof(struct particle));
MPI_Allreduce(mypart, particles, n, type_force_resized,
              MPI_SUM, MPI_COMM_WORLD);
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

但是这种方法需要额外的内存,并且需要内存复制操作。

不清楚您在这里想要减少什么;单个三分量速度是所有速度之和,或者一个处理器上的一组粒子,因此(比如)粒子2的速度是所有其他处理器上粒子2的所有速度之和?或者别的什么?粒子2的速度是所有其他处理器上粒子2的所有速度之和。情况就是这样!谢谢作为一名新手,我认为更简单的变体对我来说真的更简单!:)