c++ - 反平方根内在函数

标签 c++ visual-studio

是否有针对标量参数的反平方根、单精度和 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/

相关文章:

c++ - 捕捉信号 : Use a member function as signal handler

c++ - 基本 OpenCV Hello World 的错误

c++ - 在 Arduino ide 中读取多个文本文件

c++ - 我可以单独定义类模板的函数模板成员吗?

visual-studio - 什么可能导致 Visual Studio 2008 中出现 "Debugging will be aborted"错误?

c# - 动态添加 LINQWhere 子句

visual-studio - 在 Visual Studio 中更改宏

visual-studio - 无法将调试器附加到 Azure Web 服务聊天机器人应用程序

c++ - 我可以转发声明一个 lambda 以便其上面的代码可以调用它吗?

C++ 重载 >> 运算符基于 >> 的哪一侧具有不同的交互