OpenMP SIMD:嵌套循环

时间:2017-11-20 10:21:07

标签: c openmp vectorization simd

我想将SIMD矢量化用于替换计算函数的傅里叶变换。它可以概括为:

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

直接前进的方式是在outso循环s上并行化并减少sum [k],但它的直接大小会溢出缓存。然而,仅仅对内环进行矢量化将不会改善昂贵的函数f_1。是否有一个很好的方法来获得两者,f_1的矢量化和s的积累?如果可能,尽可能使用OpenMP,而无需手动分块。

编辑: 到目前为止,我发现的最好的方法是手动分块。但是,以这种方式重构代码是一项重要任务。它很好地验证了f_1,但是gcc似乎不喜欢这样做f_2。也许是一个错误...

#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 个答案:

没有答案