Why is my sine algorithm much slower than the default?

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(); 
}

This power series is valid for [0,pi/2] and it is 10 times slower than the built in sine function in release mode. 1ms vs 10ms.

But when I copy paste mysin code into the function I get practically the same time in release and my code is about 4 times faster when in debug mode.

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]);
}

What is the deal here? How do I make this sort of calculations faster? I am guessing the code automatically recognizes that sin algorithm should not be called but copy paste into the loop. How do I make the compiler do the same for me.

One more question, would c++ do the same optimization for its default sin/cos function? If not how would I make sure that it does. Edit: I tested it and my sine function (with 4 extra if conditions added to expand the domain to all real) runs about 25% faster (albeit inaccurate) than the default sin function. And in fact, the copy pasted version runs slower than when I write it as a separate function.


I assume that you tested this on x86, because I cannot repro the numbers on x64. On x64, your code actually appears to be faster.

I disassembled the code for x86/release. The reason for the difference is that your method is just that, a method whereas Math.Sin is compiled to use the x86 fsin instruction directly thus eliminating a function call per invocation.

FWIW, the x64 code is quite different. Math.Sin is translated into clr!COMDouble::Sin .

See FSIN.

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

上一篇: WebGL:将spritebatch渲染为渲染纹理时的奇怪行为

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