浮点型与双精度浮点型性能比较

98

我进行了一些计时测试,也阅读了一些类似这篇文章(最后一条评论),看起来在Release版本中,float和double值处理时间相同。

那么这是怎么实现的呢?当float比double值精度低且更小的时候,CLR如何使得它们在处理时间上相同呢?


12
我不认为这是完全重复的,因为这个问题在问背后的原因,而另一个用户只是在问是否更快,但不一定为什么更快。 - Joan Venge
据另一位用户于2009年声称,这是*C#中double类型比float类型更快吗?*的完全副本。 - Peter Mortensen
5个回答

167
在x86处理器上,floatdouble至少会被FPU转换为10字节实数以便进行处理。FPU没有为其支持的不同浮点类型单独的处理单元。
长久以来,有人认为floatdouble快的建议是过时的,这种建议在100年前适用,当时大多数CPU没有内置FPU(很少有人有单独的FPU芯片),因此大多数浮点运算是通过软件完成的。在那些由熔岩坑生成蒸汽驱动的机器上,使用float确实更快。现在,float唯一的真正好处是占用更少的空间(只有在需要处理数百万个浮点数时才有意义)。

9
也许不是100年前...一些浮点处理器支持本地处理float、double和80位级别的数据,并且在较短的长度下执行速度更快。有些处理器在较短长度下执行某些任务的速度反而会变慢... :-) - Brian Knoblauch
4
可能的例外情况是,我认为除法所需的时间取决于位数(1个时钟周期/2个位)。 我进行的浮点数与双精度浮点数除法的时间测试似乎证实了这一点。 - Neil Coffey
25
在编写SIMD代码时需要注意:由于SIMD寄存器(如SSE)可以打包2倍数量的浮点数而不是双精度数,因此潜在地使用浮点数可能会更快。 但由于这是C#语言,这种情况不太可能发生。 - Calyth
15
@P Daddy:我会说在缓存层次结构的每个级别上,空间优势都很重要。当您的第一级数据缓存为16KB,并且您正在计算一个由4000个数字组成的数组时,使用float类型可能更快。 - Peter G.
6
@artificialidiot永远不要说“永远不能”;). SIMD在.NET 4.6及以上版本中得到支持。 - ghord
显示剩余6条评论

15

这取决于系统是32位还是64位。如果你编译为64位,那么双精度浮点数会更快。在64位(机器和操作系统)上编译成32位可以使浮点数速度提高约30%:

    public static void doubleTest(int loop)
    {
        Console.Write("double: ");
        for (int i = 0; i < loop; i++)
        {
            double a = 1000, b = 45, c = 12000, d = 2, e = 7, f = 1024;
            a = Math.Sin(a);
            b = Math.Asin(b);
            c = Math.Sqrt(c);
            d = d + d - d + d;
            e = e * e + e * e;
            f = f / f / f / f / f;
        }
    }

    public static void floatTest(int loop)
    {
        Console.Write("float: ");
        for (int i = 0; i < loop; i++)
        {
            float a = 1000, b = 45, c = 12000, d = 2, e = 7, f = 1024;
            a = (float) Math.Sin(a);
            b = (float) Math.Asin(b);
            c = (float) Math.Sqrt(c);
            d = d + d - d + d;
            e = e * e + e * e;
            f = f / f / f / f / f;
        }
    }

    static void Main(string[] args)
    {
        DateTime time = DateTime.Now;
        doubleTest(5 * 1000000);
        Console.WriteLine("milliseconds: " + (DateTime.Now - time).TotalMilliseconds);

        time = DateTime.Now;
        floatTest(5 * 1000000);
        Console.WriteLine("milliseconds: " + (DateTime.Now - time).TotalMilliseconds);

        Thread.Sleep(5000);
    }

6
你有没有考虑那30%可能是因为你使用了额外的铸造件? - Rasmus Damgaard Nielsen
@RasmusDamgaardNielsen 强制类型转换是问题的一部分,因为 Math 使用的是 double。但你误读了我的帖子:我的测试表明 float 在性能上更好。 - Bitterblue
5
上面发布的结果是虚假的。我的测试表明,在一个旧的32位计算机上,使用.NET 4.0 Release模式时,floatdouble的性能几乎相同。在许多独立的试验中平均下来,每个试验都对连续链接的变量执行乘法、除法和加法操作(以避免任何编译器优化妨碍测试),两者之间的差异不到0.3%。我进行了第二组测试,使用了Math.Sin()Math.Sqrt(),也得到了相同的结果。 - Special Sauce

12

我曾做过一个小项目,使用了CUDA,我记得在那个项目中,float 的速度比 double 快。因为 Host(即 CPU 和普通 RAM)与 Device(即 GPU 和相应的 RAM)之间的通信较少。但即使数据始终驻留在 Device 上,速度仍然较慢。我想我在某处读到过,最近或者下一代可能会有所改变,但不确定。

因此,似乎在这些情况下,GPU 不能本地处理双精度浮点数,这也可以解释为什么通常使用 GLFloat 而不是 GLDouble。

(正如我所说,这只是我记得的情况,在搜索 CPU 上的 float vs. double 时偶然发现的。)


7
GPU与FPU是完全不同的实体。正如其他人所提到的,FPU的本机格式是80位双精度浮点数,而且这已经持续了很长时间了。然而,GPU从单精度方向进入这个领域。众所周知,他们的双精度浮点性能通常只有单精度浮点性能的一半。看起来它们通常具有SP浮点单元,并且必须重复使用该单元以覆盖双精度。这会导致比一个周期多两倍的时间。这是一个巨大的性能差异,当我面对它时,我感到非常震惊。 - Csaba Toth
1
一些科学计算需要DP FP,而主要的GPU制造商并没有宣传其性能损失。现在他们(AMD、nVidia)似乎在DP vs SP这个话题上有所改进。Intel Xeon Phi的许多核心包含Pentium的FPU,并注意到Intel强调了它的双精度能力。这可能是它真正能够与GPGPU怪物竞争的地方。 - Csaba Toth

11

然而,仍有一些情况下需要使用浮点数 - 例如在OpenGL编程中,常见的是使用GLFloat数据类型(通常直接映射到16位浮点数),因为它在大多数GPU上比GLDouble更高效。


3
可能是由于数据吞吐量更高导致的?如果你有一个数字矩阵(如深度缓冲区等),数据大小变得更加重要,避免在浮点数和双精度之间转换可以加快处理速度。这只是我的猜测。 - Lucero
2
毫无疑问,吞吐量很重要。而且,考虑到专业上下文,使用双精度浮点数而不是单精度浮点数几乎不会带来任何可见的好处,为什么要浪费内存呢?特别是在GPU上,内存比CPU更为紧缺。 - Cruachan
1
吞吐量和SP FP(单精度浮点数)是GPU内部FPUs的本机格式,而不是DP FP(双精度浮点数)的事实。请参见我对@Mene答案的评论。 GPU和CPU FPUs是非常不同的实体,CPU的FPU正在以DP FP思考。 - Csaba Toth
浮点数与双精度在图形硬件上的区别 - zwcloud

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接