使用OpenMP并行化此递归的最佳方法

Best way to parallelize this recursion using OpenMP

本文关键字:最佳 方法 递归 OpenMP 并行化 使用      更新时间:2023-10-16

我具有以下递归功能(注意:它被剥离了所有不重要的细节)

int recursion(...) {
  int minimum = INFINITY;
  for(int i=0; i<C; i++) {
      int foo = recursion(...);
      if (foo < minimum) {
          minimum = foo;
      }
  }
  return minimum;
}

注2:它是有限的,但在这个简化的示例中不是,所以请忽略它。这个问题的重点是如何正确解决此问题。

我正在考虑使用任务,但是我不确定如何正确使用它 - 如何将内部周期置换。

编辑1:递归树不能很好地平衡。它与动态编程方法一起使用,因此随着时间的流逝,从以前的通过中重新使用了许多值。这让我非常担心,我认为这将是一个很大的瓶颈。

c在20。

左右。

最好的度量是最快的:)

它将在2x Xeon上运行,因此可以使用大量的HW功率。

是的

我将在vector中收集结果,并计算最小值外部。您也可以在任务中执行受保护的(关键/锁定)的最小计算。

,如果您在递归中太深,则避免在最低限度的情况下产卵任务/分配内存,在递归中,开销/工作比率太差了。最强的解决方案是创建两个独立的(并行/串行)递归函数。这样,一旦切换到串行功能,您就会有零运行时的开销 - 而不是每次在统一功能中检查递归深度。

int recursion(...) {
    #pragma omp parallel
    #pragma omp single
    return recursion_par(..., 0);
}
int recursion_ser(...) {
    int minimum = INFINITY;
    for(int i=0; i<C; i++) {
        int foo = recursion_ser(...);
        if (foo < minimum) {
            minimum = foo;
        }
    }
    return minimum;
}
int recursion_par(..., int depth) {
    std::vector<int> foos(C);
    for(int i=0; i<C; i++) {
        #pragma omp task
        {
            if (depth < threshhold) {
                foos[i] = recursion_par(..., depth + 1);
            } else {
                foos[i] = recursion_ser(...);
            }
        }
    }
    #pragma omp taskwait
    return *std::min_element(std::begin(foos), std::end(foos));
}

显然,您不得在不重要的细节中使用全球/共享状态做任何令人讨厌的事情