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