OpenMP SIMD: Nested loops

Viewed 1113

I want to use SIMD vectorization for Fourier transformations of an inplaced calculated function. It can be summerized as:

double f_1(int s);        // expensive
double f_2(int s, int k); // cheap but frequent

void accumulate(double *sum, int samples, int freqs) {
  for (int s=0; s<samples; s++) {
    double data = f_1(s);
    for (int k=0; k<freqs; k++)
      sum[k] += data * f_2(s, k);
  }
}

The streight forward way would be to parallelize over the outher loop s with an reduction on sum[k], but its immediate size would overflow the cache. Just vectorizing the inner loop however will not improve the costly function f_1. Is there a good way to get both, a vectorization of f_1 over s and the accumulation over k? Best if possible with OpenMP without chunking the loops manually.

Edit: The best way I've found so far is manual chunking. However refactoring the code in such a way is a major task. It verctorizes f_1 well, but gcc seems to not like to do so for f_2. Maybe a bug through...

#pragma omp declare simd linear(s)
double f_1(int s);        // expensive

#pragma omp declare simd uniform(s) linear(k)
double f_2(int s, int k); // cheap but frequent

void accumulate(double *sum, int samples, int freqs) {
  const int N = 8;
  for (int s=0; s<samples; s+=N) {
    double data[N];
    #pragma omp simd
    for (int i=0; i<N; i++)
      data[i] = f_1(s+i);
    #pragma omp simd safelen(N)
    for (int k=0; k<freqs; k++) {
      for (int i=0; i<N; i++)
        sum[k] += data[i] * f_2(s+i, k);
    }
  }
}
0 Answers
Related