自动矢量化比较

Posted

技术标签:

【中文标题】自动矢量化比较【英文标题】:Auto-Vectorize comparison 【发布时间】:2016-12-06 19:06:42 【问题描述】:

我无法让我的 g++ 5.4 使用矢量化进行比较。基本上我想使用矢量化比较 4 个无符号整数。我的第一个方法很简单:

bool compare(unsigned int const pX[4]) 
    bool c1 = (temp[0] < 1);
    bool c2 = (temp[1] < 2);
    bool c3 = (temp[2] < 3);
    bool c4 = (temp[3] < 4); 
    return c1 && c2 && c3 && c4;

使用g++ -std=c++11 -Wall -O3 -funroll-loops -march=native -mtune=native -ftree-vectorize -msse -msse2 -ffast-math -fopt-info-vec-missed 编译时,由于数据未对齐,无法对比较进行矢量化处理:

main.cpp:5:17: note: not vectorized: failed to find SLP opportunities in basic block.
main.cpp:5:17: note: misalign = 0 bytes of ref MEM[(const unsigned int *)&x]
main.cpp:5:17: note: misalign = 4 bytes of ref MEM[(const unsigned int *)&x + 4B]
main.cpp:5:17: note: misalign = 8 bytes of ref MEM[(const unsigned int *)&x + 8B]
main.cpp:5:17: note: misalign = 12 bytes of ref MEM[(const unsigned int *)&x + 12B]

因此我的第二次尝试是告诉 g++ 对齐数据并使用临时数组:

bool compare(unsigned int const pX[4] ) 
    unsigned int temp[4] __attribute__ ((aligned(16)));
    temp[0] = pX[0];
    temp[1] = pX[1];
    temp[2] = pX[2];
    temp[3] = pX[3];

    bool c1 = (temp[0] < 1);
    bool c2 = (temp[1] < 2);
    bool c3 = (temp[2] < 3);
    bool c4 = (temp[3] < 4); 
    return c1 && c2 && c3 && c4;

但是,相同的输出。我的 CPU 支持 AVX2,英特尔内在指南告诉我,有例如_mm256_cmpgt_epi8/16/32/64 用于比较。知道如何告诉 g++ 使用它吗?

【问题讨论】:

不确定是否有便携式方法,但如果您只是想查看是否设置了所有bools,intrinsics 会告诉您是否通过位数等,它们都是错误的。intel even has an example 在 SSE/AVX 中没有 32 位无符号比较 - 尝试使用有符号。 AVX2 需要 32 字节对齐 使用bool compare(signed int const pX[4] ) signed int temp[4] __attribute__ ((aligned(32))); temp[0] = pX[0]; temp[1] = pX[1]; temp[2] = pX[2]; temp[3] = pX[3]; bool c1 = (temp[0] &lt; 1); bool c2 = (temp[1] &lt; 2); bool c3 = (temp[2] &lt; 3); bool c4 = (temp[3] &lt; 4); return c1 &amp;&amp; c2 &amp;&amp; c3 &amp;&amp; c4; 同样的问题。 【参考方案1】:

好的,显然编译器不喜欢“展开循环”。这对我有用:

bool compare(signed int const pX[8]) 
    signed int const w[] __attribute__((aligned(32))) = 1,2,3,4,5,6,7,8;
    signed int out[8] __attribute__((aligned(32)));

    for (unsigned int i = 0; i < 8; ++i) 
        out[i] = (pX[i] <= w[i]);
    

    bool temp = true;
    for (unsigned int i = 0; i < 8; ++i) 
        temp = temp && out[i];
        if (!temp) 
            return false;
        
    
    return true;

请注意,out 也是 signed int。 现在我只需要一种快速的方法来组合保存在out 中的结果

【讨论】:

我还发现展开的循环对编译器来说是有问题的。快速索引上的#omp pragma 应该矢量化,并且您可能需要求和为深位深度总和。另一种方法是联合,其中 2D[n,m] 共同表示为 1D[n*m],然后对编译器来说自然很容易。

以上是关于自动矢量化比较的主要内容,如果未能解决你的问题,请参考以下文章

LeafletAnalyzer--一款用于叶片的量化比较和分类的自动化软件

GCC 自动矢量化对运行时没有影响,即使在所谓“有利可图”的情况下也是如此

基于 Jenkins 实现的轻量化自动化测试运行框架

自动驾驶中神经网络模型量化技术:INT8还是INT4?

自动驾驶中神经网络模型量化技术:INT8还是INT4?

为啥库需要硬编码矢量化而不是编译器自动矢量化