【问题标题】:Transform comparison routine to Intel SIMD将比较例程转换为英特尔 SIMD
【发布时间】:2018-10-19 12:34:24
【问题描述】:

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

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

我查看了英特尔 SIMD 内在函数,发现这条指令dst = _mm_cmplt_ps(a,b) 生成了一个包含(0xffffffff 表示真)或(0 表示假)的向量,但我被困在那里;我怎么知道dst 向量的哪个元素是负数或不构建sign_vector

【问题讨论】:

  • 在那之后你会怎么处理sign?您确定需要 2 的补码整数 -1 / +1 而不是 -1 / 0 或其他什么?此外,x&lt;0 是否需要是一个正确的 IEEE 比较,将x = -0.0x = -NaN 视为不是&lt;0.0?如果是这样,您需要 _mm_cmplt_ps 而不是 Paul R 的符号位提取。但如果不是,Paul 的回答看起来是一个很好的方法来得到你所要求的,但你可以根据你接下来做什么来简化它。

标签: c x86 intel sse simd


【解决方案1】:

除了一个小例外 (x==+0.0f),您可以使用指令sign 生成整数掩码:

_mm_sign_epi32(_mm_set1_epi32(1), x)

如果 x

如果不允许为 0,则可以通过与 0&lt;mask&lt;0x80000000 进行 oring 使 x 变为非零。

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

【讨论】:

  • -NaN 是另一个例外,它的行为与问题中的代码不同,假设 x &lt; 0 是 IEEE 比较。但是,是的,如果事实证明 OP 确实需要 +1 / -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,不如考虑是否可以直接使用符号位,并省略此步骤。

【讨论】:

  • 如果 OP 可以使用整数 0 / -1 结果,则整数 pcmpgtd 反对零可以测试符号位,作为右移的替代方法。或 SSE4.1 blendps 在整数 +1 / -1 位模式之间进行选择,但这在 Intel CPU 上具有额外的旁路延迟,并且 Haswell 上的 port5 为 2 uop,因此可能会成为 shuffle 端口的瓶颈。
  • 你可以避免and:直接在FP位模式上使用srai,然后用_mm_or_si128而不是_mm_add_epi32设置低位。这留下了高 31 位作为 FP 符号位的副本。 (请注意,您假设在 OP 的代码中将 -0.0-NaN 视为小于 +0.0 是可以的,因此仅查看符号位与 FP 比较不同。)跨度>
  • @PeterCordes:是的,所有优点 - 在我的脑海里,我在想 OP 实际上可以只使用符号位而不是浪费时间生成 +1/-1值,因此评论中的“如果需要”。不过,我应该在问题中记下这一点 - 我很快就会这样做。如果 OP 确实需要 +1/-1 的标志,那么我喜欢你的想法,直接将浮子拉起来。
猜你喜欢
  • 2023-03-06
  • 2016-05-03
  • 2015-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 2013-04-12
  • 1970-01-01
相关资源
最近更新 更多