【发布时间】:2017-05-09 23:37:30
【问题描述】:
1) 有没有办法使用具有以下特征的 SSE3(无 SSE4)有效地实现sign function?
- 输入是一个浮点向量
__m128。 - 输出也应该是
__m128,其值为 [-1.0f, 0.0f, 1.0f]
我试过这个,但它没有用(虽然我认为它应该):
inputVal = _mm_set_ps(-0.5, 0.5, 0.0, 3.0);
comp1 = _mm_cmpgt_ps(_mm_setzero_ps(), inputVal);
comp2 = _mm_cmpgt_ps(inputVal, _mm_setzero_ps());
comp1 = _mm_castsi128_ps(_mm_castps_si128(comp1));
comp2 = _mm_castsi128_ps(_mm_castps_si128(comp2));
signVal = _mm_sub_ps(comp1, comp2);
2) 有没有办法创建“标志”功能(我不确定正确的名称)。即,如果A > B,则结果将为1,否则为0。结果应该是浮点数 (__m128),就像它的输入一样。
更新:看来 Cory Nelson 的回答在这里会起作用:
__m128 greatherThanFlag = _mm_and_ps(_mm_cmpgt_ps(valA, valB), _mm_set1_ps(1.0f));
__m128 lessThanFlag = _mm_and_ps(_mm_cmplt_ps(valA, valB), _mm_set1_ps(1.0f));
【问题讨论】:
-
对于第 2 部分,您为什么需要
1.0f标志,而不仅仅是来自_mm_cmpgt_ps的 AND 掩码?例如要有条件地添加某些内容,请将具有比较结果的操作数屏蔽为比较为假的零元素。全零位 = 0.0f,这是加法恒等式。或者,如果您只想制作 0 或不变的内容,并且使用蒙版。 -
@PeterCordes,我不确定我是否理解你(我对位的经验并不丰富 :-))。你会为第 2 部分写一个解决方案吗?效率越高越好:-)。
-
你可以用
(A>B)?1.f:0.f查看g++生成的代码来获得一些想法......(cmpltps+andps) -
/facepalm.我担心你会因为那样可怕的事情而想要它。使用 FP 乘法和加法是实现
condition ? a : b的一种非常慢的方法。如果您没有 SSE4 BLENDPS,请使用通常的 ANDPS/ANDNPS/ORPS 序列根据比较结果进行混合。见Branchless “select”(cond ? a : b)section in this blog post -
如果你想否定一些东西,把掩码变成一个只设置符号位(有条件地)的向量,然后用它进行异或来翻转另一个向量的符号位。 (请记住,与
0进行异或没有效果,它是身份值。与1进行异或有点翻转。有关使用布尔值操作符号位的更多信息,另请参阅SSE absolute value。
标签: x86 vectorization x86-64 sse simd