自动向量化:说服编译器不需要别名检查

Ant*_*nio 18 c++ gcc opencv sse vectorization

我正在做一些图像处理,我从矢量化中受益.我有一个矢量化ok的函数,但是我无法说服编译器输入和输出缓冲区没有重叠,因此不需要进行别名检查.我应该可以使用__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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以说服编译器不执行别名检查的唯一方法是将内部循环放在一个单独的函数中,其中指针被定义为__restrict__参数.如果我将此内部函数声明为内联,则再次激活别名检查.

您可以通过此示例查看效果,我认为这是一致的:http://goo.gl/7HK5p7

(注意:我知道可能有更好的方法来编写相同的函数,但在这种情况下,我只是想了解如何避免别名检查)

编辑:
问题解决了!! (参见下面的答案)
使用gcc 4.9.2,这是完整的例子.注意使用编译器标志-fopt-info-vec-optimized代替被取代的-ftree-vectorizer-verbose=N.
所以,对于gcc,使用#pragma GCC ivdep和享受!:)

PhD*_*EcE 5

如果您使用的是英特尔编译器,您可以尝试包含以下行:

#pragma ivdep 
Run Code Online (Sandbox Code Playgroud)

以下段落引用自Intel编译器用户手册:

ivdep 编译指示指示编译器忽略假定的向量依赖性。为了确保正确的代码,编译器将假定的依赖关系视为已证明的依赖关系,这会阻止向量化。该编译指示优先于该决定。仅当您知道可以安全地忽略假定的循环依赖性时,才使用此编译指示。

gcc中,应该添加以下行:

#pragma GCC ivdep
Run Code Online (Sandbox Code Playgroud)

在函数内部以及要向量化的循环之前(请参阅文档)。仅从 gcc 4.9 开始支持此功能,顺便说一下,这使得使用变得__restrict__多余。