在 C# 中否定浮点值的最佳方法
Optimal way to negate a floating point value in C#
从代码执行的角度来看什么更快:
double a = 1.234;
double minus_a = -a;
或:
double a = 1.234;
double minus_a = a * -1;
第二种情况真的执行浮点乘法吗?或者编译器是否足够聪明,可以将第二种情况优化为与第一种情况相同?
使用 .NET 4 的 64 位 JIT 进行测试,其他 JIT,例如旧的 32 位 JIT 或较新的 RyuJIT 可能不同(实际上 32 位旧 JIT 必须 做其他事情因为它不使用 SSE),尽管 64 位核心 CLR 5.0 仍然做同样的事情。
-x
转化为
vmovsd xmm1,qword ptr [00000050h] ; the constant is -0.0, so only the sign bit is set
vxorpd xmm0,xmm0,xmm1 ; literally flip the sign
x * -1
变成
vmulsd xmm0,xmm0,mmword ptr [00000048h] ; -1.0
是的,非常直白。
至于速度,您可以从 here 中选择您的模型并进行比较,但是 vxorpd
总是比 vmulsd
快。
是否可以将 x * -1
优化为 XOR?可能是。有一些古怪的情况下它不会做同样的事情,例如当 DAZ or FTZ are set (它们影响 vmulsd
在非规范值的情况下的操作,但 vxorps
忽略这些标志,它始终是纯异或)。但是在 .NET 中没有使用这些功能的官方方法。
从代码执行的角度来看什么更快:
double a = 1.234;
double minus_a = -a;
或:
double a = 1.234;
double minus_a = a * -1;
第二种情况真的执行浮点乘法吗?或者编译器是否足够聪明,可以将第二种情况优化为与第一种情况相同?
使用 .NET 4 的 64 位 JIT 进行测试,其他 JIT,例如旧的 32 位 JIT 或较新的 RyuJIT 可能不同(实际上 32 位旧 JIT 必须 做其他事情因为它不使用 SSE),尽管 64 位核心 CLR 5.0 仍然做同样的事情。
-x
转化为
vmovsd xmm1,qword ptr [00000050h] ; the constant is -0.0, so only the sign bit is set
vxorpd xmm0,xmm0,xmm1 ; literally flip the sign
x * -1
变成
vmulsd xmm0,xmm0,mmword ptr [00000048h] ; -1.0
是的,非常直白。
至于速度,您可以从 here 中选择您的模型并进行比较,但是 vxorpd
总是比 vmulsd
快。
是否可以将 x * -1
优化为 XOR?可能是。有一些古怪的情况下它不会做同样的事情,例如当 DAZ or FTZ are set (它们影响 vmulsd
在非规范值的情况下的操作,但 vxorps
忽略这些标志,它始终是纯异或)。但是在 .NET 中没有使用这些功能的官方方法。