首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使clang/gcc向矢量化环数组比较?

如何使clang/gcc向矢量化环数组比较?
EN

Stack Overflow用户
提问于 2022-08-17 20:49:19
回答 2查看 92关注 0票数 1
代码语言:javascript
复制
bool equal(uint8_t * b1,uint8_t * b2){
    b1=(uint8_t*)__builtin_assume_aligned(b1,64);
    b2=(uint8_t*)__builtin_assume_aligned(b2,64);
    for(int ii = 0; ii < 64; ++ii){
        if(b1[ii]!=b2[ii]){
            return false;
        }
    }
    return true;
}

从程序集的角度来看,除了循环展开之外,clang和gcc似乎没有任何可以添加的优化(带有标志-O3 -mavx512f -msse4.2)。我认为将这两个内存区域放在512位寄存器中并进行比较是非常容易的。更令人惊讶的是,这两种编译器也未能对其进行优化(理想情况下,只需要一个64位的比较,而不需要特殊的大型寄存器):

代码语言:javascript
复制
bool equal(uint8_t * b1,uint8_t * b2){
    b1=(uint8_t*)__builtin_assume_aligned(b1,8);
    b2=(uint8_t*)__builtin_assume_aligned(b2,8);
    for(int ii = 0; ii < 8; ++ii){
        if(b1[ii]!=b2[ii]){
            return false;
        }
    }
    return true;
}

那么,这两个编译器都是愚蠢的,还是这段代码没有向量化的原因呢?有没有办法迫使矢量化,而不写内嵌装配?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-17 21:14:59

“我想”以下是最有效的

代码语言:javascript
复制
memcmp(b1, b2, any_size_you_need);

特别是对于巨大的阵列!

(对于小型数组,无论如何也没有什么可获得的!)

否则,您将需要使用Intel Intrinsics手动矢量化。(chtz也提到)我开始研究这个问题,直到我想到了memcmp

票数 3
EN

Stack Overflow用户

发布于 2022-08-17 21:07:41

编译器必须假设,一旦函数返回(或者退出循环),它就不能读取当前索引后面的任何字节--例如,如果其中一个指针恰好指向无效内存边界附近的某个位置。您可以通过使用(非懒惰)位&/|运算符来组合单个比较的结果来使编译器有机会对其进行优化:

代码语言:javascript
复制
bool equal(uint8_t * b1,uint8_t * b2){
    b1=(uint8_t*)__builtin_assume_aligned(b1,64);
    b2=(uint8_t*)__builtin_assume_aligned(b2,64);
    bool ret = true;
    for(int ii = 0; ii < 64; ++ii){
        ret &= (b1[ii]==b2[ii]);
    }
    return ret;
}

https://godbolt.org/z/3ePh7q5rM演示

尽管如此,gcc仍然未能证明这一点。因此,如果该函数的性能非常关键,则可能需要编写该函数的手动向量化版本。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73394742

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档