如何否定(改变符号)__m128类型变量中的浮点元素?

dor*_*mon 6 c x86 sse simd vectorization

是否有任何单个指令或函数可以反转 __m128内每个浮点的符号?即a = r0:r1:r2:r3 ===> a = -r0:-r1:-r2:-r3

我知道这可以通过_mm_sub_ps(_mm_set1_ps(0.0),a),但是它是否可能很慢,因为它_mm_set1_ps(0.0)是一个多指令函数?

Pau*_*l R 19

在实践中,您的编译器应该很好地为0.0生成常量向量.它可能只是使用_mm_xor_ps,如果你的代码在一个循环中,它应该提升循环中的常量生成.所以,底线,使用你原来的想法:

v = _mm_sub_ps(_mm_set1_ps(0.0), v);
Run Code Online (Sandbox Code Playgroud)

或另一个常见的伎俩,即:

v = _mm_xor_ps(v, _mm_set1_ps(-0.0));
Run Code Online (Sandbox Code Playgroud)

它只是翻转符号位而不是进行减法(不像第一种方法那样安全,因为它不能用NaN做正确的事情,但在某些情况下可能更有效).

  • 我很确定`xor`和NaN一样好.NaN中的符号位具有无关状态,因此所有NaN都保持为NaN,并且所有非NaN都保持非NaN.静音与信号NaN由尾数的最高位表示(不是整个浮点的最高位).使用`xor`通常是最好的.在AMD上,`xorps`在整数域中运行,因此具有到/来自FP数学指令的旁路延迟,它仍然与5c`subps'的延迟大致相同. (6认同)
  • 但是,从内存中加载 `-0.0` 常量可能会缓存未命中。编译器不喜欢[动态生成常量](http://stackoverflow.com/questions/35085059/what-are-the-best-instruction-sequences-to-generate-vector-constants-on-the- fly) 如果它需要一个以上的 insn(`xorps same,same` 或 `pcmpeqw same,same`(全 1))。这个只需要 [`pcmpeqw xmm7,xmm7` / `pslld xmm7, 31`](http://stackoverflow.com/a/32422471/224132)(请参阅该链接以获取 SSE 绝对值:带有该掩码的 ANDN,或 AND与其相反) (3认同)