c - strlen AVX-512 __builtin_ctz 无效值

标签 c gcc bit-manipulation intrinsics avx512

我用 avx-512 指令编写了 strlen 函数,这是我的源代码

size_t avx512_strlen(const char * s) {
    __m512i vec0, vec1;
    unsigned long long mask;
    const char * ptr = s;

    vec0 = _mm512_setzero_epi32();

    while (1) {
        vec1 = _mm512_loadu_si512(s);
        mask = _mm512_cmpeq_epi8_mask(vec0, vec1);

        if(mask != 0) {
            mask = __builtin_ctz(mask);
            return (s-ptr) + mask;
        }

        s += 64;
    }

    return s-ptr;
}

'__builtin_ctz(mask)'的值有问题,返回值不正确。事实上,这个函数不能计算空终止符(0x00)在最后一次检查中的位置

例如我有这个字符串

char str[] = "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
                 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
                 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
                 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE";

这个字符串的长度是 (360) 但这个函数返回 (352) 问题来自 '__builtin_ctz' 部分。在执行“__builtin_ctz”之前,提供的掩码是正确的,它是

0001110100010001000100010000000000000000000000000000000000000000

在最后一次检查中,我们检查了 320 个字符并且 __builtin_ctz 必须返回 (40)(正如您在掩码中看到的那样,我们将 40 个零计数到第一个 '1' 并提供掩码正确且 '__builtin_ctz' 计数错误!

问题是什么?

最佳答案

__builtin_ctzunsigned int 上运行,这在任何 x86 平台上都可能是 32 位。同时,unsigned long long 在任何 x86 平台上都可能是 64 位的。所以你的掩码在这一行被截断了:

            mask = __builtin_ctz(mask);

由于低 32 位全为零,the result is undefined (per GCC) :

Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.

(尽管未定义,352 - 320 = 32 是“32 位零整数中尾随 0 位的数量”的合理答案。)

您可能打算改用 __builtin_ctzll(mask)。这应该能让您得到正确的计数。

关于c - strlen AVX-512 __builtin_ctz 无效值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58346032/

相关文章:

c++ - OpenCV:访问并求像素的平方根

c++ - GCC-Visual Studio std::thread 编译器差异

c++ - GCC:在需要复制构造函数时实例化模板构造函数

c - ECLIPSE 中的 X11 安装

c - 标签作为参数

c - 为什么 Q.15 乘法不起作用

c - getrusage 在 ru_utime.tv_usec 和 ru_utime.tv_sec 中返回零

c++ - (x ^ 0x1) != 0 是什么意思?

c++ - 将 3 个值的数组打包到缓冲区中

c - 内存对齐公式