AVX2:AVX 寄存器中 8 位元素的 BitScanReverse 或 CountLeadingZeros

我想提取具有 8 位元素的 256 位 AVX 寄存器中最高设置位的索引。我既找不到bsr也找不到clz实现。

对于clz32 位元素,有一个带有浮点转换的 bithack,但这对于 8 位来说可能是不可能的。

目前,我正在研究一个解决方案,在那里我逐个检查位,稍后我会添加,但我想知道是否有更快的方法来做到这一点。

回答

这是一个vpshufb基于解决方案。这个想法是将输入分成两半,对两者进行查找并合并结果:

__m256i clz_epu8(__m256i values)
{
// extract upper nibble:
__m256i hi = _mm256_and_si256(_mm256_srli_epi16(values, 4), _mm256_set1_epi8(0xf));
// this sets the highest bit for values >= 0x10 and otherwise keeps the lower nibble unmodified:
__m256i lo = _mm256_adds_epu8(values, _mm256_set1_epi8(0x70));
// lookup tables for count-leading-zeros (replace this by _mm256_setr_epi8, if this does not get optimized away)
// ideally, this should compile to vbroadcastf128 ...
const __m256i lookup_hi = _mm256_broadcastsi128_si256(_mm_setr_epi8(0, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0));
const __m256i lookup_lo = _mm256_broadcastsi128_si256(_mm_setr_epi8(8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4));
// look up each half
__m256i clz_hi = _mm256_shuffle_epi8(lookup_hi, hi);
__m256i clz_lo = _mm256_shuffle_epi8(lookup_lo, lo);
// combine results (addition or xor would work as well)
return _mm256_or_si256(clz_hi, clz_lo);
}

带有粗测试的godbolt-link:https ://godbolt.org/z/MYq74Wxdh


以上是AVX2:AVX 寄存器中 8 位元素的 BitScanReverse 或 CountLeadingZeros的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>