平方根内禀反比

Inverse square root intrinsics

本文关键字:平方根      更新时间:2023-10-16

标量参数上的平方根反比、单精度浮点数和双精度浮点数是否有编译器内联函数?

我可以在打包的 SIMD 参数(SSE 和 AVX(中找到这些参数,但不能找到标量参数。

任何比除以<math.h>平方根更快的方法也是受欢迎的。

你去吧....

#include <immintrin.h>
// identical to std::sqrt
inline float sqrt(const float f)
{
__m128 temp = _mm_set_ss(f);
temp = _mm_sqrt_ss(temp);
return _mm_cvtss_f32(temp);
}
// faster than  1.0f/std::sqrt, but with little accuracy.
inline float rsqrt(const float f)
{
__m128 temp = _mm_set_ss(f);
temp = _mm_rsqrt_ss(temp);
return _mm_cvtss_f32(temp);
}
// identical to std::sqrt
inline double sqrt(const double f)
{
__m128d temp = _mm_set_sd(f);
temp = _mm_sqrt_sd(temp, temp);
return _mm_cvtsd_f64(temp);
}
// identical to 1.0 / std::sqrt
// .... there isn't an instruction for rsqrt with double, 
// so 1.0 / std::sqrt is the best you've got. 
inline double rsqrt(const double f)
{
__m128d temp = _mm_set_sd(f);
temp = _mm_div_sd(_mm_set_sd(1.0), _mm_sqrt_sd(temp, temp));
return _mm_cvtsd_f64(temp);
}

与 std::sqrt(( 的比较: https://godbolt.org/z/uufv3W

如果启用 -ffast-math(或在 MSVC 中启用快速浮点精度(,则 std::sqrt 无论如何都可能生成与使用内部函数相同的代码。唯一的例外是 rsqrt for float(clang 会将 1/sqrt 转换为 rsqrt + Newton-raphson 迭代(。

显然,rsqrt 带有一些非常讨厌的浮动错误。比如说,为OpenGL渲染规范化一堆表面法线可能是可以的,但对于几乎所有其他事情,缺乏准确性使其几乎无用。(例如二次公式(

你看到的任何"Quake3优化rsqrt"废话,都会比直接调用std::sqrt慢很多数量级,但准确性很差。

至少每个月一次左右,在游戏行业工作时,一些新人会尝试通过替换 std::sqrt 来"优化"代码。叹息

TL;DR:如果您启用了快速数学,只需使用 std::sqrt。如果禁用了快速数学,则C++标准指示为 errno 设置错误代码,这将强制编译器使用 std 库版本。