C 将比较例程转换为英特尔SIMD
我有一个例行程序,它应该测试一个浮点数是否小于零。如果是,我应该存储符号,我得到的是绝对值C 将比较例程转换为英特尔SIMD,c,x86,intel,sse,simd,C,X86,Intel,Sse,Simd,我有一个例行程序,它应该测试一个浮点数是否小于零。如果是,我应该存储符号,我得到的是绝对值 int sign = 1; if (x < 0) { sign = -1; } x = fabs(x); int符号=1; if(x假设输入值在向量中,M128V: __m128 vmask = _mm_set1_ps(-0.0f); // create sign bit mask __m128 vsign = _mm_and_ps(v, vmask); // create
int sign = 1;
if (x < 0)
{
sign = -1;
}
x = fabs(x);
int符号=1;
if(x<0)
{
符号=-1;
}
x=fabs(x);
我查看了英特尔SIMD内部函数,发现这条指令
dst=_-mm\u-cmplt\u-ps(a,b)
,它生成一个包含(0xffffff表示真)或(0表示假)的向量,但我被卡在那里;我如何知道dst
向量的哪个元素是负的,或者不构建符号向量
假设您的输入值在向量中\uuu 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,考虑是否可以直接使用符号位,省略这一步。
< P>假设输入值在向量<代码>中,M128V:__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,考虑是否可以直接使用符号位,省略这个步骤。
< P>一个小的异常(x==+0.0f),可以使用指令<代码>符号< /> >生成整数掩码:_mm_sign_epi32(_mm_set1_epi32(1), x)
这将取反1,如果x有一个小异常(x==+0.0f),您可以使用指令符号生成整数掩码
:
_mm_sign_epi32(_mm_set1_epi32(1), x)
这将否定1,如果x在这之后如何处理
符号
?您确定需要2的补码整数-1
/+1
而不是-1
/0或其他什么吗?还有,x在那之后你用sign
做什么?您确定需要2的补码整数-1
/+1
而不是-1
/0或其他什么吗?此外,如果OP可以使用整数0
/-1
结果,则整数pcmpgtd
对零可以测试符号位,作为右移的替代方案。或SSE4.1blendps
在整数+1/-1位模式之间进行选择,但这在英特尔CPU上有额外的旁路延迟,在Haswell上端口5有2个UOP,因此可能会造成随机端口瓶颈。您可以避免和:直接在FP位模式上使用srai
,然后用\u mm\u或
而不是\u mm\u add\u epi32
设置低位。这会将上面的31位保留为FP符号位的副本。(请注意,您假设可以将OP代码中的-0.0
和-NaN
视为小于+0.0
,因此仅查看符号位与FP比较不同。)@PeterCordes:yes,所有优点——在我的脑海深处,我认为OP实际上可能只处理符号位,而不是浪费时间生成+1/-1值,因此在注释中使用了“如果需要”。不过,我应该在问题中记下这一点——我很快就会这么做。如果OP确实需要+1/-1作为符号,那么我喜欢你直接使用浮点的想法。如果OP可以使用整数0
/-1
结果,则整数pcmpgtd
对零可以测试符号位,作为右移的替代方法。或SSE4.1blendps
在整数+1/-1位模式之间进行选择,但这在英特尔CPU上有额外的旁路延迟,在Haswell上端口5有2个UOP,因此可能会造成随机端口瓶颈。您可以避免和:直接在FP位模式上使用srai
,然后用\u mm\u或
而不是\u mm\u add\u epi32
设置低位。这会将上面的31位保留为FP符号位的副本。(请注意,您假设可以将OP代码中的-0.0
和-NaN
视为小于+0.0
,因此仅查看符号位与FP比较不同。)@PeterCordes:yes,所有优点——在我的脑海深处,我认为OP实际上可能只处理符号位,而不是浪费时间生成+1/-1值,因此在注释中使用了“如果需要”。不过,我应该在问题中记下这一点——我很快就会这么做。如果OP确实需要+1/-1作为符号,那么我喜欢你直接对浮点进行srai的想法。-NaN
是另一个例外,假设x<0
是IEEE比较,其行为与问题中的代码不同。但是,如果OP真的需要+1/-1,并且不能仅仅求和比较结果,并在末尾或其他地方校正偏移量,那么这是一个好主意。-NaN
是另一个例外,假设x<0
是IEEE比较,其行为与问题中的代码不同。但是,是的,如果OP确实需要+1/-1,并且不能简单地求和比较结果,并在末尾更正偏移量或其他东西,那么这是个好主意。