为什么我的正弦算法比默认的算法慢得多?

const double pi = 3.1415926535897;

static double mysin(double x) {
    return ((((((-0.000140298 * x - 0.00021075890) * x + 0.008703147) * x -
        0.0003853080) * x - 0.16641544) * x - 0.00010117316) * x +
        1.000023121) * x;
}

static void Main(string[] args) {
    Stopwatch sw = new Stopwatch();

    double a = 0;
    double[] arg = new double[1000000];
    for (int i = 0; i < 1000000; i++) {
        arg[i] = (pi / 2000000);
    } 
    sw.Restart();
    for (int i = 0; i < 1000000; i++) {
        a = a + Math.Sin(arg[i]);
    }
    sw.Stop();
    double t1 = (double)(sw.Elapsed.TotalMilliseconds);

    a = 0;
    sw.Restart();
    for (int i = 0; i < 1000000; i++) {
        a = a + mysin(arg[i]);
    }
    sw.Stop();
    double t2 = (double)(sw.Elapsed.TotalMilliseconds);
    Console.WriteLine("{0}n{1}n", t1,t2);
    Console.Read(); 
}

该功率序列对于[0,pi / 2]有效,比释放模式下的内置正弦功能慢10倍。 1ms vs 10ms。

但是,当我将粘贴mysin代码复制到函数中时,我几乎可以在发布时获得相同的时间,并且在调试模式下,我的代码速度提高了约4倍。

a = 0;
sw.Restart();
for (int i = 0; i < 1000000; i++) {
    double x = arg[i];
    a = a + ((((((-0.000140298 * x - 0.00021075890) * x + 0.008703147) * x -
        0.0003853080) * x - 0.16641544) * x - 0.00010117316) * x +
        1.000023121) * x;
    //a = a + mysin(arg[i]);
}

这里的交易是什么? 如何更快地进行这种计算? 我猜测代码自动识别不应该调用罪恶算法,但复制粘贴到循环中。 我如何让编译器对我做同样的事情。

还有一个问题,c ++会为它的默认sin / cos函数做相同的优化吗? 如果不是,我会如何确保它确实如此。 编辑:我测试了它,并且我的正弦函数(如果添加了4个额外的条件以将域扩展为全部实数)的运行速度比默认的sin函数快25%(尽管不准确)。 事实上,复制粘贴版本的运行速度要比将它作为单独函数写入时要慢。


我假设你在x86上测试了这个,因为我不能在x64上重新编号。 在x64上,您的代码实际上似乎更快。

我反汇编了x86 / release的代码。 不同之处在于你的方法就是这样一种方法,而Math.Sin被编译为直接使用x86 fsin指令,从而消除了每个调用的函数调用。

FWIW,x64代码是完全不同的。 Math.Sin被转换为clr!COMDouble::Sin

见FSIN。

链接地址: http://www.djcxy.com/p/28019.html

上一篇: Why is my sine algorithm much slower than the default?

下一篇: MS Log Parser 2.2 Query Error