将比较例程转换为Intel SIMD

时间:2018-05-09 11:43:10

标签: c x86 intel sse simd

我有一个例程,应该测试浮点数是否小于零。如果是,我应该存储标志,我得到它是绝对值。

int sign = 1;
if (x < 0)
{
    sign = -1;
}
x = fabs(x);

我查看了英特尔SIMD内在函数,我发现这条指令dst = _mm_cmplt_ps(a,b)生成一个包含(0xffffffff表示true)或(0表示false)的向量但是我被卡在那里;如何知道dst向量的哪个元素是否为负数来构建sign_vector

2 个答案:

答案 0 :(得分:3)

只有一个小异常(x == + 0.0f),您可以使用sign指令生成整数掩码:

_mm_sign_epi32(_mm_set1_epi32(1), x)

如果x <0,这将取消1,但当x == 0时产生符号== 0。

如果不允许0,则可以通过0<mask<0x80000000进行操作使x变为非零。

auto s=_mm_set1_epi32(1);
auto y=_mm_or_si128(x, s); // fix for x==0
s=_mm_sign_epi32(s, y);

答案 1 :(得分:2)

假设您的输入值位于向量__m128 v

__m128 vmask = _mm_set1_ps(-0.0f);      // create sign bit mask
__m128 vsign = _mm_and_ps(v, vmask);    // create vector of sign bits (MSB)
__m128i vsigni = _mm_add_epi32(_mm_srai_epi32((__m128i)vsign, 30), _mm_set1_epi32(1));
                                        // convert sign bits to integer +1/-1 (if needed (*))
v = _mm_andnot_ps(vmask, v);            // clear sign bits in v (i.e. v = fabsf(v))

(*)而不是浪费为符号生成+ 1 / -1的循环,考虑是否可以直接使用符号位,并省略此步骤。