我有一个例程,它使用一个循环来计算给定下面的粒子表面的粒子的最小高度.此例程尝试随机位置并计算最小高度,然后返回x, y, z
值,其中z
是找到的最小高度.
该例程可以并行化omp parallel for
.但是我在弄清楚如何获得三元组时遇到了问题(x, y, z)
,而不仅仅是最小值z
(因为最小值z
当然对应于给定的x, y
坐标).z
通过使用如下的缩减操作,我实际上可以得到最小的
double x = 0, y = 0, z = 1.0e300; // initially z is large
#pragma omp parallel for reduction(min:z)
for(int trial = 0; trial < NTRIALS; ++trial) {
// long routine that, at the end, computes x, y, z
// and selects only the x, y, z corresponding to the
// smallest z
}
Run Code Online (Sandbox Code Playgroud)
但我无法得到相应的x
和y
.最后我刚刚结束了一个随机的x
,并y
通过一个线程写入.
是否有可能获得这些价值观?怎么样?我正在考虑使用一个数组,其中每个线程存储它们的值,x, y, zmin
然后,在还原操作之后,将每个线程zmin
与减少的全局值进行比较,然后获得与选择的线程相对应的线程.在OpenMP这样做的意义上是否有更好的方法,所以我不需要定义这个动态数组并比较浮点数?
您可以使用用户定义的缩减(从OpenMP 4.0开始提供)为多个值实现argmin.为此,你必须将三重奏放在一种类型中.定义便利功能很有帮助.
struct xyz {
double x; double y; double z;
}
struct xyz xyz_min2(struct xyz a, struct xyz b) {
return a.z < b.z ? a : b;
}
#pragma omp declare reduction(xyz_min: struct xyz: omp_out=xyz_min2(omp_out, omp_in))\
initializer(omp_priv={0, 0, DBL_MAX})
struct xyz value = {0, 0, DBL_MAX};
#pragma omp parallel for reduction(xyz_min:value)
for (int trial = 0; trial < NTRIALS; ++trial) {
struct xyz new_value = ...;
value = xyz_min2(value, new_value);
}
Run Code Online (Sandbox Code Playgroud)