【问题标题】:strlen AVX-512 __builtin_ctz invalid valuestrlen AVX-512 __builtin_ctz 无效值
【发布时间】:2020-02-09 06:19:31
【问题描述】:

我用 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)在last-check中的位置

例如,我有这个字符串

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

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

0001110100010001000100010000000000000000000000000000000000000000

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

有什么问题?

【问题讨论】:

    标签: c gcc bit-manipulation intrinsics avx512


    【解决方案1】:

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

                mask = __builtin_ctz(mask);
    

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

    返回 x 中尾随 0 位的数量,从最低有效位位置开始。如果 x 为 0,则结​​果未定义。

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

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

    【讨论】:

    • 32 告诉我们 GCC 使用 tzcnt felixcloutier.com/x86/tzcnt 制作的 asm,这保证了输出。 (而不是bsf,它会使输入= 0的目标寄存器保持不变。英特尔将BSF记录为输入= 0上的“未指定”值,但这就是它的作用,以及它具有输出依赖性的原因。AMD甚至记录了它.)
    猜你喜欢
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    • 2018-01-31
    • 2017-12-23
    • 1970-01-01
    相关资源
    最近更新 更多