strlen AVX-512 __builtin_ctz неверное значение - PullRequest
2 голосов
/ 11 октября 2019

я написал функцию strlen с инструкциями avx-512, и это мой исходный код

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» считает ее неправильной!

В чем проблема?

1 Ответ

4 голосов
/ 11 октября 2019

__builtin_ctz работает на unsigned int, что, вероятно, 32 бита на любой платформе x86. Между тем, unsigned long long - это, вероятно, 64 бита на любой платформе x86. Таким образом, ваша маска усекается в этой строке:

            mask = __builtin_ctz(mask);

Поскольку все младшие 32 бита равны нулю, результат не определен (для GCC) :

Возвращает количество завершающих 0 битов в x, начиная с позиции младшего разряда. Если x равен 0, результат не определен.

(Несмотря на то, что он не определен, 352 - 320 = 32 является разумным ответом для "количества завершающих 0 бит в 32-битном нуле"целое число. ")

Возможно, вы хотели использовать __builtin_ctzll(mask) вместо этого. Это должно дать вам правильный счет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...