为啥 strchr 比我的 simd 代码快两倍

Posted

技术标签:

【中文标题】为啥 strchr 比我的 simd 代码快两倍【英文标题】:why is strchr twice as fast as my simd code为什么 strchr 比我的 simd 代码快两倍 【发布时间】:2017-11-12 05:25:42 【问题描述】:

我正在学习 SIMD,我很想知道是否有可能在寻找角色方面击败 strchr。似乎 strchr 使用相同的内在函数,但我假设它检查空值,而我知道字符在数组中并计划避免空值检查。

我的代码是:

size_t N = 1e9;
bool found = false; //Not really used ...
size_t char_index1 = 0;
size_t char_index2 = 0;
char * str = malloc(N);
memset(str,'a',N);

__m256i char_match;
__m256i str_simd;
__m256i result;
__m256i* pSrc1;

int simd_mask;

str[(size_t)5e8] = 'b';


    char_match = _mm256_set1_epi8('b');
    result = _mm256_set1_epi32(0);

    simd_mask = 0;

    pSrc1 = (__m256i *)str;

    while (1)
        str_simd  = _mm256_lddqu_si256(pSrc1);
        result = _mm256_cmpeq_epi8(str_simd, char_match);
        simd_mask = _mm256_movemask_epi8(result);   
        if (simd_mask != 0)
            break;
        
        pSrc1++;
    

完整(尚未完成的代码)位于: https://gist.github.com/JimHokanson/433e185ba53b41e49ce3ac804568ac1e

strchr 是这段代码的两倍(使用 gcc 和 xcode)。我希望了解原因。

更新:编译使用:gcc -std=c11 -mavx2 -mlzcnt

【问题讨论】:

相关帖子:***.com/questions/40915243/… 你编译优化了吗,比如-O3? 在大多数系统上,可以获得标准函数的源代码,例如strchr,或者至少您可以随时检查生成的机器代码。我建议您研究源代码(或机器代码)以了解它的作用。我的猜测是,在 40 年左右的时间里,该功能已经存在,并且已经进行了相当多的调整和优化。 @Someprogrammerdude 我不确定如何研究机器代码。重要的是,如果您做出参考代码没有做出的简化假设,通常可以击败经过高度优化的代码。 This is glibc's strchr-avx2.S。是的,它必须做大约 2 倍的检查 nul 和字符的工作。但请注意它们是如何展开 4 个向量和 OR 比较结果的,以节省 vpmovmskb / 分支吞吐量。这是memchr-avx2.S,他们不检查nul。相当不错的 asm,未对齐的启动和对齐的内循环。 【参考方案1】:

我没有在编译器中设置优化标志。设置 -O3 导致 SIMD 代码只占用 strchr 时间的 75%。

更新:我还应该澄清这不是代码的最终工作版本。仍然需要进行额外的检查以及优化调用的可能方法(我认为)。至少在这一点上,虽然代码在 strchr 的范围内。正如问题 cmets 所指出的那样,这个版本可以读取过去的页面和错误。最后,这主要是一个 SIMD 学习机会(对我自己而言),memchr 可能是你最好的选择(尽管我怀疑如果你有一个哨兵缓冲区,你可能会稍微击败 memchr)。

【讨论】:

以上是关于为啥 strchr 比我的 simd 代码快两倍的主要内容,如果未能解决你的问题,请参考以下文章

MF SinkWriter mp4 文件的播放持续时间是添加音频样本时的一半时间,图像的播放速度也快两倍

报告称:苹果iPhone/iPad升级到iOS11后,耗电比iOS10快两倍

为啥这个 C 语言中的 SIMD 示例代码可以用 minGW 编译,但可执行文件不能在我的 Windows 机器上运行?

为啥向量长度 SIMD 代码比普通 C 慢

为啥 SSE 和 AVX 具有相同的效率?

为啥 strcmp 比我的函数快这么多?