数字的加法逆:从零减去或乘以 -1
Additive inverse of a number: subtraction from zero or multiplication by −1
取负数时哪种方法更快:-1*a
或 0-a
?其中 a
是双精度数。
两者都很糟糕,只需用 XOR 或专用的 FP 取反指令翻转符号位即可。
IEEE-754 浮点数使用 sign/magnitude 表示,因此 -x
与 x
仅相差 1 位:sign-bit。 (例如,在带有 SSE 的 x86 上,使用 xorps
How to negate (change sign) of the floating point elements in a __m128 type variable?)。这会将 NaN 翻转为 -NaN,反之亦然,而不会更改有效负载。
在C中,写成-a
,看看你的编译器会做什么。
更好的是,您通常可以通过稍后执行减法而不是加法,或者使用 FMSUB 或 FNMADD 而不是 FMADD,或者生成 a
最初使用 FNMSUB 而不是 FMADD 来取反来优化取反FMA 的一部分。
但是如果您必须在实际的 FP 乘法指令或 FP 加法指令之间进行选择,通常减法的延迟至少与乘法一样好。
Intel Haswell 和 Broadwell 的倍增吞吐量是增加吞吐量的两倍(运行 在 FMA 单元上具有更差或相同的延迟添加),但大多数微体系结构(包括现代 x86 Ryzen 和 Skylake)具有平衡的 FP添加与乘法吞吐量。
一般来说,对于非 x86 架构,加法至少和乘法一样便宜。但同样,大多数 ISA 都会有一些特殊的否定方式,例如 x86 的 SSE1 xorps
或旧版 x87 fchs
(CHange Sign).
无条件清除符号位的布尔 AND 或 ANDN(或内置 "mask" 的专用指令)作为绝对值也很有用。
取负数时哪种方法更快:-1*a
或 0-a
?其中 a
是双精度数。
两者都很糟糕,只需用 XOR 或专用的 FP 取反指令翻转符号位即可。
IEEE-754 浮点数使用 sign/magnitude 表示,因此 -x
与 x
仅相差 1 位:sign-bit。 (例如,在带有 SSE 的 x86 上,使用 xorps
How to negate (change sign) of the floating point elements in a __m128 type variable?)。这会将 NaN 翻转为 -NaN,反之亦然,而不会更改有效负载。
在C中,写成-a
,看看你的编译器会做什么。
更好的是,您通常可以通过稍后执行减法而不是加法,或者使用 FMSUB 或 FNMADD 而不是 FMADD,或者生成 a
最初使用 FNMSUB 而不是 FMADD 来取反来优化取反FMA 的一部分。
但是如果您必须在实际的 FP 乘法指令或 FP 加法指令之间进行选择,通常减法的延迟至少与乘法一样好。
Intel Haswell 和 Broadwell 的倍增吞吐量是增加吞吐量的两倍(运行 在 FMA 单元上具有更差或相同的延迟添加),但大多数微体系结构(包括现代 x86 Ryzen 和 Skylake)具有平衡的 FP添加与乘法吞吐量。
一般来说,对于非 x86 架构,加法至少和乘法一样便宜。但同样,大多数 ISA 都会有一些特殊的否定方式,例如 x86 的 SSE1 xorps
或旧版 x87 fchs
(CHange Sign).
无条件清除符号位的布尔 AND 或 ANDN(或内置 "mask" 的专用指令)作为绝对值也很有用。