简单的数学运算在double上比在float数据类型上更快?

Kam*_*mil 3 c# profiling .net-3.5

可能重复:
比c#中的浮点数快一倍?

我编写了简单的基准测试来检查我可以在我的应用程序中将double数据类型更改为多少float.这是我的代码:

    // my form: 
    // one textbox: textbox1 (MultiLine property set to true)
    // one button: button1 with event button1_Click

    private void button1_Click(object sender, EventArgs e)
    {

        int num = 10000000;

        float[] floats1 = new float[num];
        float[] floats2 = new float[num];
        float[] floatsr = new float[num];  // array for results
        double[] doubles1 = new double[num];
        double[] doubles2 = new double[num];
        double[] doublesr = new double[num]; // array for results

        Stopwatch stw = new Stopwatch();

        log("Preparing data");

        Random rnd = new Random();

        stw.Start();

        for (int i = 0; i < num; i++)
        {
            floats1[i] = NextFloat(rnd);
            floats2[i] = NextFloat(rnd);
            doubles1[i] = rnd.NextDouble();
            doubles2[i] = rnd.NextDouble();
        }
        stw.Stop();
        log(stw.Elapsed.TotalMilliseconds.ToString()+"ms");
        stw.Reset();




        log("");


        stw.Start();
        for (int i = 0; i <# i++)
        {
            floatsr[i] = floats1[i] * floats2[i];
        }
        stw.Stop();
        log("Multiplying floats: " + stw.Elapsed.TotalMilliseconds.ToString() + "ms");
        stw.Reset();



        stw.Start();
        for (int i = 0; i < num; i++)
        {
            doublesr[i] = doubles1[i] * doubles2[i];
        }
        stw.Stop();
        log("Multiplying doubles: " + stw.Elapsed.TotalMilliseconds.ToString() + "ms");
        stw.Reset();


        stw.Start();
        for (int i = 0; i < num; i++)
        {
            floatsr[i] = floats1[i] / floats2[i];
        }
        stw.Stop();
        log("Dividing floats: " + stw.Elapsed.TotalMilliseconds.ToString() + "ms");
        stw.Reset();


        stw.Start();
        for (int i = 0; i < num; i++)
        {
            doublesr[i] = doubles1[i] / doubles2[i];
        }
        stw.Stop();
        log("Dividing doubles: " + stw.Elapsed.TotalMilliseconds.ToString() + "ms");
        stw.Reset();

    }

    private void log(string text)
    {
        textBox1.Text = textBox1.Text + text + Environment.NewLine;
    }

    // I found that function somewhere on stackoverflow
    static float NextFloat(Random random)
    {
        double mantissa = (random.NextDouble() * 2.0) - 1.0;
        double exponent = Math.Pow(2.0, random.Next(-126, 128));
        return (float)(mantissa * exponent);
    }
Run Code Online (Sandbox Code Playgroud)

我得到了这样的结果(发布,没有调试,英特尔移动酷睿双核T2500 2.0GHz 2MB CPU):

Preparing data 5275,6862ms

Multiplying floats: 442,7865ms 
Multiplying doubles: 169,4028ms
Dividing floats: 550,7052ms 
Dividing doubles: 164,1607ms
Run Code Online (Sandbox Code Playgroud)

令我感到惊讶的是,操作的double速度几乎是操作的3倍float.我在这里搜索"双浮",我发现了这个:

使用比浮动更快的双倍?

最佳答案主要集中在CPU架构上,但我不同意这一点.

我怀疑其他东西导致浮点数性能低下,因为我的带有英特尔SSE的CPU应该能够一次乘法或除4浮点数(打包浮点指令),或者一次加倍2倍.所以花车应该更快.

也许编译器(或.net中的clr)以某种方式优化内存使用?

有没有办法优化它并使浮动速度更快?

请不要报告重复,我看到其他问题,他们不满意我.


更改生成浮动的方法后我的结果现在看起来很好(由Servy建议):

Preparing data 1367,0678ms

Multiplying floats: 109,8742ms 
Multiplying doubles: 149,9555ms
Dividing floats: 167,0079ms 
Dividing doubles: 168,6821ms
Run Code Online (Sandbox Code Playgroud)

Ser*_*rvy 6

它与你如何生成随机数有关.浮点数的乘法和除法并不完全相同; 这些数字的实际值很重要.在浮点数的情况下,您将在相当大的范围内填充值.如果你创建你的花车,使它们介于0和1之间,就像双打一样,那么它会更像你期望的那样.只需改为NextFloat:

static float NextFloat(Random random)
{
    return (float) random.NextDouble();
}
Run Code Online (Sandbox Code Playgroud)

我只是运行了一些测试,并且通过这种改变,浮点数在乘法时的速度提高了33%.

当然,这只是使比较"公平"的最简单方法.为了更好地理解浮点数与双精度数的比较,你需要生成随机浮点数,并在各个类型的整个范围之间加倍,或者更好的是,两个保持值代表程序将使用的数据类型.