我正在做一些图像处理,为此我受益于矢量化。
我有一个可以矢量化的函数,但是我无法让编译器相信输入和输出缓冲区没有重叠,因此不需要进行别名检查。
我应该可以使用 __restrict__
来做到这一点,但是如果缓冲区在作为函数参数到达时未定义为 __restrict__
,则无法让编译器相信我是绝对确定 2 个缓冲区永远不会重叠。
这是函数:
__attribute__((optimize("tree-vectorize","tree-vectorizer-verbose=6")))
void threshold(const cv::Mat& inputRoi, cv::Mat& outputRoi, const unsigned char th) {
const int height = inputRoi.rows;
const int width = inputRoi.cols;
for (int j = 0; j < height; j++) {
const uint8_t* __restrict in = (const uint8_t* __restrict) inputRoi.ptr(j);
uint8_t* __restrict out = (uint8_t* __restrict) outputRoi.ptr(j);
for (int i = 0; i < width; i++) {
out[i] = (in[i] < valueTh) ? 255 : 0;
}
}
}
我可以说服编译器不执行别名检查的唯一方法是将内部循环放在一个单独的函数中,其中指针被定义为 __restrict__
参数。如果我将此内部函数声明为内联函数,则会再次激活别名检查。
这个例子你也可以看到效果,我认为是一致的:http://goo.gl/7HK5p7
(注意:我知道编写相同函数可能有更好的方法,但在这种情况下,我只是想了解如何避免别名检查)
编辑:
问题解决了!! (见 answer below)
使用 gcc 4.9.2,here is the complete example .注意编译器标志 -fopt-info-vec-optimized
的使用代替被取代的 -ftree-vectorizer-verbose=N
。
因此,对于 gcc,使用 #pragma GCC ivdep
并享受吧! :)
最佳答案
如果您使用的是英特尔编译器,您可以尝试包含以下行:
#pragma ivdep
以下段落引自英特尔编译器用户手册:
The ivdep pragma instructs the compiler to ignore assumed vector dependencies. To ensure correct code, the compiler treats an assumed dependence as a proven dependence, which prevents vectorization. This pragma overrides that decision. Use this pragma only when you know that the assumed loop dependencies are safe to ignore.
在 gcc 中,应添加以下行:
#pragma GCC ivdep
在函数内部和要矢量化的循环之前(参见 documentation)。这仅从 gcc 4.9 开始受支持,顺便说一下,使用 __restrict__
是多余的。
关于c++ - 自动矢量化 : Convincing the compiler that alias check is not necessary,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25934239/