简体   繁体   中英

Best way to parallelize this recursion using OpenMP

I have following recursive function (NOTE: It is stripped of all unimportant details)

int recursion(...) {

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

      if (foo < minimum) {
          minimum = foo;
      }
  }

  return minimum;
}

Note 2: It is finite , but not in this simplified example, so please ignore it. Point of this question is how to aproach this problem correctly.

I was thinking about using tasks , but I am not sure, how to use it correctly - how to paralelize the inner cycle.

EDIT 1: The recursion tree isn't well balanced. It is being used with dynamic programing approach, so as time goes on, a lot of values are re-used from previous passes. This worries me a lot and I think it will be a big bottleneck.

C is somewhere around 20.

Metric for the best is fastest :)

It will run on 2x Xeon , so there is plenty of HW power availible.

Yes, you can use OpenMP tasks exploit parallelism on multiple recursion levels and ensure that imbalances don't cause wasted cycles.

I would collect the results in a vector and compute the minimum outside. You could also perform a guarded (critical / lock) minimum computation within the task.

Avoid spawning tasks / allocating memory for the minimum if you are too deep in the recursion, where the overhead / work ratio becomes too bad. The strongest solution it to create two separate (parallel/serial) recursive functions. That way you have zero runtime overhead once you switch to the serial function - as opposed to checking the recursion depth against a threshold every time in a unified function.

int recursion(...) {
    #pragma omp parallel
    #pragma omp single
    return recursion_omp(...);
}

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(...) {
    std::vector<int> foos(C);
    for(int i=0; i<C; i++) {
        #pragma omp task
        {
            if (depth < threshhold) {
                foos[i] = recursion_par(...);
            } else {
                foos[i] = recursion_ser(...);
            }
        }
    }
    #pragma omp taskwait
    return *std::min_element(std::begin(foos), std::end(foos));
}

Obviously you must not do any nasty things with global / shared state within the unimportant details .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM