【发布时间】:2019-06-06 09:06:01
【问题描述】:
我正在尝试启用一个函数 SIMD 并通过函数调用对循环进行矢量化。
#include <cmath>
#pragma omp declare simd
double BlackBoxFunction(const double x) {
return 1.0/sqrt(x);
}
double ComputeIntegral(const int n, const double a, const double b) {
const double dx = (b - a)/n;
double I = 0.0;
#pragma omp simd reduction(+: I)
for (int i = 0; i < n; i++) {
const double xip12 = a + dx*(double(i) + 0.5);
const double yip12 = BlackBoxFunction(xip12);
const double dI = yip12*dx;
I += dI;
}
return I;
}
对于上面的代码,如果我用icpc编译的话:
icpc worker.cc -qopenmp -qopt-report=5 -c
opt-report 显示函数和循环都是矢量化的。
但是,如果我尝试使用 g++ 6.5 编译它:
g++ worker.cc -O3 -fopenmp -fopt-info-vec-missed -funsafe-math-optimizations -c
输出显示note:not vectorized: control flow in loop.和note: bad loop form,循环无法向量化。
如何使用 GCC 对循环进行矢量化?
编辑:
如果我把函数写到一个单独的文件中,
worker.cc:
#include "library.h"
double ComputeIntegral(const int n, const double a, const double b) {
const double dx = (b - a)/n;
double I = 0.0;
#pragma omp simd reduction(+: I)
for (int i = 0; i < n; i++) {
const double xip12 = a + dx*(double(i) + 0.5);
const double yip12 = BlackBoxFunction(xip12);
const double dI = yip12*dx;
I += dI;
}
return I;
}
library.h:
#ifndef __INCLUDED_LIBRARY_H__
#define __INCLUDED_LIBRARY_H__
#pragma omp declare simd
double BlackBoxFunction(const double x);
#endif
和library.cc:
#include <cmath>
#pragma omp declare simd
double BlackBoxFunction(const double x) {
return 1.0/sqrt(x);
}
然后我用 GCC 编译它:
g++ worker.cc library.cc -O3 -fopenmp -fopt-info-vec-missed -funsafe-math-optimizations -c
它显示:
worker.cc:9:31: note: loop vectorized
但是
library.cc:5:18: note:not vectorized: control flow in loop.
library.cc:5:18: note:bad loop form.
这让我很困惑。我想知道它是否已经矢量化了。
【问题讨论】:
-
Relevant GCC source。您可以看到,如果循环内有两个以上的basic blocks,它会引发控制流警告,将循环机制算作其中之一。我猜这意味着函数调用将循环内容分成两个或三个块;如果您手动内联
BlackBoxFunction是否有效? -
@Rup 我试过了,但 GCC 仍然提示
control flow in loop和bad loop form
标签: c++ openmp vectorization simd