C++ 是否有快速C或C++;双精度逆平方根的标准库函数?

C++ 是否有快速C或C++;双精度逆平方根的标准库函数?,c++,c,double,sqrt,C++,C,Double,Sqrt,我发现自己在打字 double foo=1.0/sqrt(...); 很多,我听说现代处理器有内置的平方根逆操作码 是否存在C或C++标准库反平方根函数 使用双精度浮点 精确到1.0/sqrt(…) 与1.0/sqrt(…)的结果一样快或更快 不,不,没有。不在C++中。没有。为什么不试试这个#定义INSQRT(x)(1.0/sqrt(x)) 它同样快速,需要更少的输入(让你感觉它是一个函数),使用双精度,精确到1/sqrt(…)如果你发现自己一遍又一遍地写着同样的东西,你应该想一想“函数!”

我发现自己在打字

double foo=1.0/sqrt(...);
很多,我听说现代处理器有内置的平方根逆操作码

是否存在C或C++标准库反平方根函数

  • 使用双精度浮点
  • 精确到
    1.0/sqrt(…)
  • 1.0/sqrt(…)
    的结果一样快或更快

  • 不,不,没有。不在C++中。没有。

    为什么不试试这个<代码>#定义INSQRT(x)(1.0/sqrt(x))


    它同样快速,需要更少的输入(让你感觉它是一个函数),使用双精度,精确到1/sqrt(…)

    如果你发现自己一遍又一遍地写着同样的东西,你应该想一想“函数!”:

    现在,代码更加自我记录:人们不必推断
    1.0/std::sqrt(x)
    是平方根的倒数,而是阅读它。此外,您现在可以插入任何您想要的实现,并且每个调用站点都会自动使用更新的定义


    要回答您的问题,没有,它没有C(++)函数,但是现在您已经制作了一个,如果您发现您的性能太差,您可以替换您自己的定义。

    如果您不怕使用自己的函数,请尝试以下操作:

    template <typename T>
    T invsqrt(T x)
    {
        return 1.0 / std::sqrt(x);
    }
    
    模板
    T invsqrt(T x)
    {
    返回1.0/std::sqrt(x);
    }
    

    它应该与任何现代优化编译器中的原始
    1.0/std::sqrt(x)
    一样快。此外,它还可以用于双精度或浮点。

    您可以使用此函数进行更快的平方根求逆运算
    维基百科上有一篇文章介绍了它的工作原理:
    还有这个算法的C版本

    float invSqrt( float number ){
        union {
            float f;
            uint32_t i;
        } conv;
    
        float x2;
        const float threehalfs = 1.5F;
    
        x2 = number * 0.5F;
        conv.f  = number;
        conv.i  = 0x5f3759df - ( conv.i >> 1 );
        conv.f  = conv.f * ( threehalfs - ( x2 * conv.f * conv.f ) );
        return conv.f;
    }
    

    违反限制1。二,。(这也不是标准的),但它仍然可以帮助人们浏览

    我曾经及时编译过您想要的确切汇编操作:
    RSQRTSS
    (单精度,可以,但应该与双精度类似)

    我的代码如下(参见我在另一篇文章中的代码):

    typedef float(*JITFunc)();
    JITFunc func;
    asmjit::jit运行时jit_运行时;
    asmjit::代码持有者代码;
    init(jit_runtime.getCodeInfo());
    asmjit::x86编译器cc(&code);
    cc.addFunc(asmjit::functSignature0());
    浮动值=2.71;//一些示例值。
    asmjit::X86Xmm x=cc.newXmm();
    uint32\u t*i=重新解释铸件和价值;
    cc.mov(asmjit::x86::eax,i[0]);
    cc.movd(x,asmjit::x86::eax);
    抄送rsqrtss(x,x);//asm功能。
    cc.ret(x);
    cc.endFunc();
    cc.finalize();
    jit_runtime.add(&func,&code);
    //现在,func()可以用作rsqrt(value)的结果。
    

    如果只执行一次JIT编译部分,稍后使用不同的值调用它,那么这应该比
    1.0/sqrt(…)

    更快(虽然精度稍低,但这是您所说的内置操作固有的),但这并不意味着您不能使用快速反向sqrt指令,只要您愿意编写平台相关的内部函数

    以64位x86和AVX为例,您可以使用 近似平方根的倒数。或者更具体地说:使用SIMD,一次执行8个平方根

    #include <immintrin.h>
    
    ...
    
    float inputs[8] = { ... } __attribute__ ((aligned (32)));
    __m256 input = _mm256_load_ps(inputs);
    __m256 invroot = _mm256_rsqrt_ps(input);
    
    
    #包括
    ...
    浮点输入[8]={…}uuuuu属性_uuu((对齐(32));
    __m256输入=mm256_load_ps(输入);
    __m256 invroot=_mm256_rsqrt_ps(输入);
    
    类似地,您可以将ARM上的固有功能与NEON一起使用。在本例中,SIMD的宽度为4,因此它将在一次go中计算四个平方反根

    #include <arm_neon.h>
    
    ...
    
    float32x4_t sqrt_reciprocal = vrsqrteq_f32(x);
    
    #包括
    ...
    浮动32x4_t sqrt_倒数=vrsqrteq_f32(x);
    

    即使每批只需要一个根值,它仍然比完整的平方根快。只需在SIMD寄存器的所有或一个通道中设置输入。这样,您就不必通过加载操作来遍历内存。在x86上通过
    \u mm256\u set1\u ps(x)

    @Pherric Oxide:这是平方反比,而不是平方反比。#定义INSQRT(x)(1.0/sqrt(x))您听说过的内置平方反比指令是近似值,不像
    sqrt
    那样精确。马克·兰瑟姆:这基本上就是我想要的答案。我没有投反对票,但当函数可以运行时,这里的宏没有用。(你甚至自己说过:让它感觉像一个函数?只是真正地做一个函数。)@gmannick我没有将它转换成函数的原因是,因为问题清楚地提到:“与1.0/sqrt(…)的结果一样快或更快。”。将其变为函数将增加额外的开销,使“语句”1.0/sqrt(…)变慢。过去十年中的任何编译器都不会这样做。@PrototypeStark:请提供基准来支持您的说法,即使用真正的函数会变慢。在没有证据表明宏需要满足某些标准的情况下,可以安全地避免使用宏。也就是说,我总是随身携带我的
    #define isNaN(x)((x)!=(x))
    ;有时候感觉这么糟糕真是太好了。这违反了问题中的第三条规则!很抱歉,据我所知,它应该“一样快”。阅读以了解为什么模板函数应该比非模板代码慢。此外,如果在gcc中启用
    -ffast math
    ,它将使用平方根反比的近似值。这将确保它和普通平方根一样快。@PrototypeStark:因为它不像或那样简单。一个是类型检查、可调试、可作用域、可重载、对其参数进行一次计算等(函数的所有特性),另一个不是。这是一个单一的否决票,这不是世界末日;我理解没有从当事人自己那里得到一个理由是令人沮丧的,但事实就是如此。我认为阅读
    1.0/sqrt(x)
    as更容易
    #include <immintrin.h>
    
    ...
    
    float inputs[8] = { ... } __attribute__ ((aligned (32)));
    __m256 input = _mm256_load_ps(inputs);
    __m256 invroot = _mm256_rsqrt_ps(input);
    
    
    #include <arm_neon.h>
    
    ...
    
    float32x4_t sqrt_reciprocal = vrsqrteq_f32(x);