strin AVX-512 __builtin_ctz无效值

问题描述 投票:1回答:1

我用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'认为它是错误的!

什么问题?

c gcc bit-manipulation intrinsics avx512
1个回答
3
投票

__builtin_ctzunsigned int上运行,在任何x86平台上可能都是32位。同时,在任何x86平台上unsigned long long可能都是64位。因此,您的遮罩在此行被截断:

            mask = __builtin_ctz(mask);

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

返回x中从最低有效位开始的尾随0位的数目。如果x为0,则结果不确定。

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

您可能打算改用__builtin_ctzll(mask)。那应该给您正确的计数。


0
投票

__builtin_ctzunsigned int上运行,在任何x86平台上可能都是32位。同时,在任何x86平台上unsigned long long可能都是64位。因此,您的遮罩在此行被截断:

            mask = __builtin_ctz(mask);

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

返回x中从最低有效位开始的尾随0位的数目。如果x为0,则结果不确定。

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

您可能打算改用__builtin_ctzll(mask)。那应该给您正确的计数。

© www.soinside.com 2019 - 2024. All rights reserved.