快速实现c ++的三角函数

jan*_*048 33 c++ math optimization

简短版本:我想知道标准三角函数的实现是否比包含的更快math.h.

龙版本:我有一个程序,对NUMERICS相当重(这是一个物理模拟),并需要调用三角函数,主要是sincos,有很多.目前我只是使用其中包含的实现math.h.分析显示对这些函数的调用花费比我预期的要多(希望).

虽然代码的其他部分肯定有足够的优化空间,但速度更快sin,cos可能会给我一些额外的百分比..那么,你们有什么建议吗?
在另一篇文章中,建议使用自制的查找表.但也许有其他选择?或者在一些图书馆中提供现成且经过良好测试的查找解决方

cel*_*ion 17

以下是有关如何进行三角函数的幂级数近似(不是泰勒级数)的一些很好的幻灯片:http://www.research.scea.com/gdc2003/fast-math-functions.html

它面向游戏程序员,这意味着精度会因性能而牺牲,但您应该能够在近似值中添加另一个或两个术语以获得一些准确性.

关于这一点的好处是你还应该能够轻松地将它扩展到SIMD,这样你就可以在一个计算4个值的sin或cos(如果你使用双精度则为2).

希望有帮助......

  • 这个链接已经死了,这是该档案中最后一个版本:http://web.archive.org/web/20160322120707/http://www.research.scea.com/gdc2003/fast-math-functions.html (2认同)

Jer*_*ilo 7

如果你可以进一步优化它,那应该非常快,请像在pastie.org或者其他地方一样发布代码.

计算机规格 - > 512MB Ram,Visual Studio 2010,Windows XP Professional SP3版本2002,Intel(R)Pentium(R)4 CPU 2.8GHZ.

这非常准确,实际上在某些情况下会提供稍微好一些的结果.例如,C++中的90,180,270度返回非0小数.

完整表0到359度:https://pastee.org/dhwbj

格式 - >度# - > MINE_X(#),CosX(#),MINE_Z(#),SinZ(#).

下面是用于构造上述表格的代码.如果使用更大的数据类型,则可以使其更准确.我使用了unsigned short并做了N/64000.那么最接近我的cos(##)和sin(##)舍入到那个索引.我也尝试使用尽可能少的额外数据,因此这不会是一些杂乱的表,其中有cos和sin的720浮点值.哪个可能会产生更好的结果,但完全浪费内存.下面的表格尽可能小.我想看看是否可以制作一个可以舍入所有这些短值并使用它的方程式.我不确定它是否会更快,但它会完全消除表格,并且可能不会降低速度.

因此,与C++ cos/sin操作相比,准确度为99.99998%到100%.

下面是用于计算cos/sin值的表.

static const unsigned __int16 DEGREE_LOOKUP_TABLE[91] =
{
    64000, 63990, 63961, 63912, 63844, 63756,
    63649, 63523, 63377, 63212, 63028, 62824,
    62601, 62360, 62099, 61819, 61521, 61204,
    60868, 60513, 60140, 59749, 59340, 58912,
    58467, 58004, 57523, 57024, 56509, 55976,
    55426, 54859, 54275, 53675, 53058, 52426,
    51777, 51113, 50433, 49737, 49027, 48301,
    47561, 46807, 46038, 45255, 44458, 43648,
    42824, 41988, 41138, 40277, 39402, 38516,
    37618, 36709, 35788, 34857, 33915, 32962,
    32000, 31028, 30046, 29055, 28056, 27048,
    26031, 25007, 23975, 22936, 21889, 20836,
    19777, 18712, 17641, 16564, 15483, 14397,
    13306, 12212, 11113, 10012,  8907,  7800,
     6690,  5578,  4464,  3350,  2234,  1117,
        0,
};
Run Code Online (Sandbox Code Playgroud)

下面是执行cos/sin计算的实际代码.

    int deg1 = (int)degrees;
    int deg2 = 90 - deg1;
    float module = degrees - deg1;
    double vX = DEGREE_LOOKUP_TABLE[deg1] * 0.000015625;
    double vZ = DEGREE_LOOKUP_TABLE[deg2] * 0.000015625;
    double mX = DEGREE_LOOKUP_TABLE[deg1 + 1] * 0.000015625;
    double mZ = DEGREE_LOOKUP_TABLE[deg2 - 1] * 0.000015625;
    float vectorX = vX + (mX - vX) * module;
    float vectorZ = vZ + (mZ - vZ) * module;
    if (quadrant & 1)
    {
        float tmp = vectorX;
        if (quadrant == 1)
        {
            vectorX = -vectorZ;
            vectorZ = tmp;
        } else {
            vectorX = vectorZ;
            vectorZ = -tmp;
        }
    } else if (quadrant == 2) {
        vectorX = -vectorX;
        vectorZ = -vectorZ;
    }
Run Code Online (Sandbox Code Playgroud)

使用最初提到的计算机规格以下的速度.在调试模式之前,我在调试模式下运行它,但是运行可执行文件,我相信它是调试而无需调试.

我的方法

1,000 Iterations -> 0.004641 MS or 4641 NanoSeconds.
100,000 Iterations -> 4.4328 MS.
100,000,000 Iterations -> 454.079 MS.
1,000,000,000 Iterations -> 4065.19 MS.
Run Code Online (Sandbox Code Playgroud)

COS/SIN方法

1,000 Iterations -> 0.581016 MS or 581016 NanoSeconds.
100,000 Iterations -> 25.0049 MS.
100,000,000 Iterations -> 24,731.6 MS.
1,000,000,000 Iterations -> 246,096 MS.
Run Code Online (Sandbox Code Playgroud)

因此,总结以上执行cos(###)和sin(###)与我的策略允许每秒大约220,000,000次执行.利用最初显示的计算机规格.这是相当快的,并且利用非常少的内存,因此它是通常在C++中找到的数学cos/sin函数的绝佳替代品.如果你想看到准确度打开上面显示的链接,并且有一个0度到359的打印.此外,它支持0到89和象限0到3.所以你需要使用它或执行( DEGREES%90).

  • 在C++中`sin(90)`不为0的原因很简单:C++使用弧度,而不是度. (3认同)