mar*_*n s 6 c optimization sse
我试图以有效的方式从128位寄存器中提取4个字节.问题是每个值都是32位{120,0,0,0,55,0,0,0,42,0,0,0,120,0,0,0}.我想将128位转换为32位形式{120,55,42,120}.
"原始"代码如下所示:
__m128i byte_result_vec={120,0,0,0,55,0,0,0,42,0,0,0,120,0,0,0};
unsigned char * byte_result_array=(unsigned char*)&byte_result_vec;
result_array[x]=byte_result_array[0];
result_array[x+1]=byte_result_array[4];
result_array[x+2]=byte_result_array[8];
result_array[x+3]=byte_result_array[12];
Run Code Online (Sandbox Code Playgroud)
我的SSSE3代码是:
unsigned int * byte_result_array=...;
__m128i byte_result_vec={120,0,0,0,55,0,0,0,42,0,0,0,120,0,0,0};
const __m128i eight_bit_shuffle_mask=_mm_set_epi8(1,1,1,1,1,1,1,1,1,1,1,1,0,4,8,12);
byte_result_vec=_mm_shuffle_epi8(byte_result_vec,eight_bit_shuffle_mask);
unsigned int * byte_result_array=(unsigned int*)&byte_result_vec;
result_array[x]=byte_result_array[0];
Run Code Online (Sandbox Code Playgroud)
我怎样才能有效地使用SSE2.SSSE3或SSE4有更好的版本吗?
Chr*_*ica 10
您可以查看我之前的答案,了解一些解决方案和相反的操作.
特别是在SSE2中,您可以通过首先将32位整数打包为带符号的16位整数并使其饱和来实现:
byte_result_vec = _mm_packs_epi32(byte_result_vec, byte_result_vec);
Run Code Online (Sandbox Code Playgroud)
然后我们使用无符号饱和将这些16位值打包成无符号8位值:
byte_result_vec = _mm_packus_epi16(byte_result_vec, byte_result_vec);
Run Code Online (Sandbox Code Playgroud)
然后,我们最终可以从寄存器的低32位获取值:
int int_result = _mm_cvtsi128_si32(byte_result_vec);
unsigned char* byte_result_array = (unsigned char*)&int_result;
result_array[x] = byte_result_array[0];
result_array[x+1] = byte_result_array[1];
result_array[x+2] = byte_result_array[2];
result_array[x+3] = byte_result_array[3];
Run Code Online (Sandbox Code Playgroud)
编辑:上面假设8位字最初是在它们各自的32位字的低字节中,其余字用0s 填充,否则它们将在饱和打包过程中被钳位.因此操作如下:
byte 15 0
0 0 0 D 0 0 0 C 0 0 0 B 0 0 0 A
_mm_packs_epi32 -> 0 D 0 C 0 B 0 A 0 D 0 C 0 B 0 A
_mm_packus_epi16 -> D C B A D C B A D C B A D C B A
^^^^^^^
_mm_cvtsi128_si32 -> int DCBA, laid out in x86 memory as bytes A B C D
-> reinterpreted as unsigned char array { A, B, C, D }
Run Code Online (Sandbox Code Playgroud)
如果0最初没有用s 填充不间断的字节,则必须事先将它们掩盖掉:
byte_result_vec = _mm_and_si128(byte_result_vec, _mm_set1_epi32(0x000000FF));
Run Code Online (Sandbox Code Playgroud)
或者,如果有趣字节最初是高字节,则必须事先将它们转换为低字节:
byte_result_vec = _mm_srli_epi32(byte_result_vec, 24);
Run Code Online (Sandbox Code Playgroud)
或者,如果你真的想要{ D, C, B, A }(我的问题并不完全清楚),那么这就等于在分配中切换数组索引(或者_mm_shuffle_epi32事先在初始SSE寄存器上执行32位shuffle()) ).
| 归档时间: |
|
| 查看次数: |
1692 次 |
| 最近记录: |