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);
}
}
}