为啥 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 机器上运行?