2017-12-27 117 views
2

下面一段代码:SSE内在 - _mm_and_ps古怪行为

__m128 a = _mm_setr_ps(1, 2, 3, 4); 
__m128 b = _mm_set1_ps(2); 
__m128 res = _mm_and_ps(a, b); 
cout << a[0] << " " << a[1] << " " << a[2] << " " << a[3] << endl; 
cout << b[0] << " " << b[1] << " " << b[2] << " " << b[3] << endl; 
cout << res[0] << " " << res[1] << " " << res[2] << " " << res[3] << endl; 
cout<<endl; 
cout << (1 & 2) << " " << (2 & 2) << " " << (3 & 2) << " " << (4 & 2) << endl; 

结果:

1 2 3 4 
2 2 2 2 
0 2 2 2 

0 2 2 0 

不应在SSE操作的结果是因为0 2 2 02 = 010, 4 = 100 => 2&4 = 0
根据文档:

__m128 _mm_and_ps(__ M128一个,__m128 B)

计算的按位的a和b的四个SP FP值的AND。

R0 R1 R2 R3

A0 & B0 A1 & B1 A2 & B2 A3 & B3

+0

为什么不显示'a'和'b'的中间值? –

+0

检查编辑..... – Blue

回答

3

documentation我发现说:

计算四个的位与单精度,浮点数 a和b的值。

(我的强调)

2和4将具有相同的尾数(0,加上一个隐含的前导1个比特)分别为128和129,和指数。按位和这些是零尾数和128(= 2.0)的指数。


编辑

如果你想要做一个逐位非负整数,并且,你可以加一个偏移量。如果使用8388608的偏移量(== 1 < < 23),那么您可以像预期的那样对0..8388607执行按位运算。

const float offset=8388608; 
__m128 mm_offset = _mm_set1_ps(); 
__m128 a = _mm_setr_ps(1, 2, 3, 4); 
a =_mm_add_ps(mm_offset,a); 
__m128 b = _mm_set1_ps(2+offset); 
__m128 res = _mm_and_ps(a, b); 
res = _mm_sub_ps(res,mm_offset); 
+0

或者你可以在整数数据上使用SSE1'andps'。 ([有微小的性能影响](https://stackoverflow.com/questions/26942952/difference-between-the-avx-instructions-vxorpd-and-vpxor))。它仍然是一个AND,在使用实际的FP指令之前,它并不关心这些位的含义。如果你从不这样做,只是存储结果,那么你很好。 –