avx2寄存器位反转 [英] avx2 register bits reverse

查看:98
本文介绍了avx2寄存器位反转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在avx2寄存器中是否存在(快速)执行32bit int值反转的位的方法?
例如

  _mm256_set1_epi32(2732370386); 
<在这里做某事>
// binary:101000101101110010101001110100100 => 1001011100101010011101101000101
//寄存器包含1268071237,这是1001011100101010011101101000101
的十进制表示形式


解决方案

由于找不到合适的欺骗对象,我将其发布。



此处的主要思想是利用 pshufb 的对偶使用并行16项表查找来反转每个半字节的位。反转字节是显而易见的。可以通过将两个半字节的顺序反转到查找表中(节省一个移位)或显式地将低半部分的上半字节向上移动(节省一个LUT)来完成每个字节中两个半字节的顺序的反转。



总计未经过测试的东西:

  __ m256i rbit32(__ m256i x){
__m256i shufbytes = _mm256_setr_epi8(3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12,12,3,2,1,0,7,6,5, 4、11、10、9、8、15、14、13、12);
__m256i luthigh = _mm256_setr_epi8(0、8、4、12、2、10、6、14、1、1、9、5、13、11、7、15、0、8、4、12、2 ,10、6、14、1、1、9、5、13、3、11、7、15);
__m256i lutlow = _mm256_slli_epi16(luthigh,4);
__m256i lowmask = _mm256_set1_epi8(15);
__m256i rbytes = _mm256_shuffle_epi8(x,shufbytes);
__m256i high = _mm256_shuffle_epi8(lutlow,_mm256_and_si256(rbytes,lowmask));
__m256i low = _mm256_shuffle_epi8(luthigh,_mm256_and_si256(_mm256_srli_epi16(rbytes,4),lowmask));
return _mm256_or_si256(low,high);
}

在循环中的典型情况下,应将这些负载解除。 / p>

奇怪地>语使用了4个混洗,它正在复制第一次洗牌。


Is there a (fast) way to perform bits reverse of 32bit int values within avx2 register? E.g.

_mm256_set1_epi32(2732370386); 
<do something here>
//binary: 10100010110111001010100111010010 => 1001011100101010011101101000101
//register contains 1268071237 which is decimal representation of 1001011100101010011101101000101

解决方案

Since I can't find a suitable dupe, I'll just post it.

The main idea here is to make use of pshufb's dual use a parallel 16-entry table lookup to reverse the bits of each nibble. Reversing bytes is obvious. Reversing the order of the two nibble in every byte could be done by building it into the lookup tables (saves a shift) or by explicitly shifting the low part nibble up (saves a LUT).

Something like this in total, not tested:

__m256i rbit32(__m256i x) {
    __m256i shufbytes = _mm256_setr_epi8(3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12);
    __m256i luthigh = _mm256_setr_epi8(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15, 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15);
    __m256i lutlow = _mm256_slli_epi16(luthigh, 4);
    __m256i lowmask = _mm256_set1_epi8(15);
    __m256i rbytes = _mm256_shuffle_epi8(x, shufbytes);
    __m256i high = _mm256_shuffle_epi8(lutlow, _mm256_and_si256(rbytes, lowmask));
    __m256i low = _mm256_shuffle_epi8(luthigh, _mm256_and_si256(_mm256_srli_epi16(rbytes, 4), lowmask));
    return _mm256_or_si256(low, high);
}

In a typical context in a loop, those loads should be lifted out.

Curiously Clang uses 4 shuffles, it's duplicating the first shuffle.

这篇关于avx2寄存器位反转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆