是否有针对标量参数的反平方根、单精度和 double 浮点的编译器内在函数?
我可以找到这些用于打包 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 中快速 float 精度),则 std::sqrt 可能会生成与使用内在函数相同的代码。唯一的异常(exception)是 rsqrt for float(clang 会将 1/sqrt 转换为 rsqrt + newton-raphson 迭代)。
显然 rsqrt 带有一些非常讨厌的 float 错误。可以说,为 OpenGL 渲染标准化一堆表面法线可能没问题,但对于几乎所有其他事情,缺乏准确性使其几乎毫无用处。 (例如二次公式)
您看到的任何“Quake3 优化 rsqrt”废话都会比直接调用 std::sqrt 慢很多数量级,但准确性却很差。
在游戏行业工作时,至少每月一次左右,一些新人会尝试通过替换 std::sqrt 来“优化”代码。 叹息
TL;DR:如果您启用了快速数学,只需使用 std::sqrt。如果禁用 fast-math,则 C++ 标准规定为 errno 设置错误代码,这将强制编译器使用 std 库版本。
关于c++ - 反平方根内在函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59644197/