【发布时间】:2023-12-03 13:28:01
【问题描述】:
我最近发现 AVX2 没有 __m256i 的 popcount,我发现做类似事情的唯一方法是遵循 Wojciech Mula 算法:
__m256i count(__m256i v) {
__m256i lookup = _mm256_setr_epi8(0, 1, 1, 2, 1, 2, 2, 3, 1, 2,
2, 3, 2, 3, 3, 4, 0, 1, 1, 2, 1, 2, 2, 3,
1, 2, 2, 3, 2, 3, 3, 4);
__m256i low_mask = _mm256_set1_epi8(0x0f);
__m256i lo =_mm256_and_si256(v,low_mask);
__m256i hi = _mm256_and_si256( _mm256_srli_epi32(v, 4), low_mask);
__m256i popcnt1 = _mm256_shuffle_epi8(lookup,lo);
__m256i popcnt2 = _mm256_shuffle_epi8(lookup,hi);
__m256i total = _mm256_add_epi8(popcnt1,popcnt2);
return _mm256_sad_epu8(total,_mm256_setzero_si256());
}
问题在于它将 8 short 的总和返回给 long 而不是 4 short 的总和返回 int。
目前正在发生的事情:
我有 __m256i x,其中包含那些 8 个 32 位 int:
- 01101011111000011100000000000000
- 01110101011010010111100000000000
- 10100100011011000101010000000000
- 11101010100001001111000000000000
- 10010011111111001001010000000000
- 00011110101100101000000000000000
- 00011101011000111011000000000000
- 10011011100010100000110000000000
__m256i res = count(x);
资源包含:
- 24
- 21
- 22
- 21
结果是 4 长 64 位
期望:
我有 __m256i x,其中包含 8 个 32 位 int:
- 01101011111000011100000000000000
- 01110101011010010111100000000000
- 10100100011011000101010000000000
- 11101010100001001111000000000000
- 10010011111111001001010000000000
- 00011110101100101000000000000000
- 00011101011000111011000000000000
- 10011011100010100000110000000000
__m256i res = count(x);
资源包含:
- 11
- 13
- 10
- 11
- 12
- 9
- 11
- 10
结果是 8 个 int 32 位。
希望我说的很清楚,不要犹豫,要求我更准确。
谢谢。
【问题讨论】:
-
这个github.com/kimwalisch/libpopcnt 可能会有所帮助。