Код: Выделить всё
std::uint64_t popcnt_AVX2_lookup(const uint8_t* data, const size_t n) {
size_t i = 0;
const __m256i lookup = _mm256_setr_epi8(
/* 0 */ 0, /* 1 */ 1, /* 2 */ 1, /* 3 */ 2,
/* 4 */ 1, /* 5 */ 2, /* 6 */ 2, /* 7 */ 3,
/* 8 */ 1, /* 9 */ 2, /* a */ 2, /* b */ 3,
/* c */ 2, /* d */ 3, /* e */ 3, /* f */ 4,
/* 0 */ 0, /* 1 */ 1, /* 2 */ 1, /* 3 */ 2,
/* 4 */ 1, /* 5 */ 2, /* 6 */ 2, /* 7 */ 3,
/* 8 */ 1, /* 9 */ 2, /* a */ 2, /* b */ 3,
/* c */ 2, /* d */ 3, /* e */ 3, /* f */ 4
);
const __m256i low_mask = _mm256_set1_epi8(0x0f);
__m256i acc = _mm256_setzero_si256();
#define ITER { \
const __m256i vec = _mm256_loadu_si256(reinterpret_cast(data + i)); \
const __m256i lo = _mm256_and_si256(vec, low_mask); \
\\\ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ why do we need this?
const __m256i hi = _mm256_and_si256(_mm256_srli_epi16(vec, 4), low_mask); \
const __m256i popcnt1 = _mm256_shuffle_epi8(lookup, lo); \
const __m256i popcnt2 = _mm256_shuffle_epi8(lookup, hi); \
local = _mm256_add_epi8(local, popcnt1); \
local = _mm256_add_epi8(local, popcnt2); \
i += 32; \
}
while (i + 8*32
Код используется для замены функции Buildin_popcnt, которая подсчитывает число 1s при данном входе в двоичном формате.
Что меня беспокоит, так это эти две строки: < /p>
const __m256i lo = _mm256_and_si256(vec, low_mask); \
const __m256i hi = _mm256_and_si256(_mm256_srli_epi16(vec, 4), low_mask); \
< /code>
Согласно Intel Intrinsic Guide https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#techs=avx,AVX2 & IG_EXPAND = 6392,305,6221 6389 6389 6221 6188 6769 6389 124 6050 6389 и текст = MM256_SHUFFLE , _mm256_shuffle_epi8 Код: Выделить всё
__m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
FOR j := 0 to 15
i := j*8
IF b[i+7] == 1
dst[i+7:i] := 0
ELSE
index[3:0] := b[i+3:i]
\\\ ^^^^^^^^^^^^^^^^^^^^^^ only look at lower 4 bits
dst[i+7:i] := a[index*8+7:index*8]
FI
IF b[128+i+7] == 1
dst[128+i+7:128+i] := 0
ELSE
index[3:0] := b[128+i+3:128+i]
dst[128+i+7:128+i] := a[128+index*8+7:128+index*8]
FI
ENDFOR
dst[MAX:256] := 0
< /code>
Итак, если я не ошибаюсь, вы можете просто сделать < /p>
const __m256i lo = vec; \
const __m256i hi = _mm256_srli_epi16(vec, 4); \
Подробнее здесь: https://stackoverflow.com/questions/729 ... for-nibble