【问题标题】:Float vs Double Performance浮动与双重性能
【发布时间】:2010-09-29 21:00:05
【问题描述】:

我做了一些计时测试,还阅读了一些文章,如 this one(最后一条评论),看起来在 Release 构建中,float 和 double 值需要相同的处理时间。

这怎么可能?当 float 与 double 值相比精度较低且较小时,CLR 如何在相同的处理时间内获得 double 值?

【问题讨论】:

  • 我不认为这是完全重复的,因为这个人在问它背后的原因,而另一个用户在问它是否真的更快,但不一定是为什么,
  • 据称与 Are doubles faster than floats in C#? 完全相同(2009 年被另一位用户声称)。

标签: c# .net clr performance


【解决方案1】:

至少在 x86 处理器上,floatdouble 将分别由 FPU 转换为 10 字节实数进行处理。 FPU 没有针对它支持的不同浮点类型的单独处理单元。

floatdouble 快​​的古老建议在 100 年前应用,当时大多数 CPU 没有内置 FPU(而且很少有人拥有单独的 FPU 芯片),所以大多数浮点操作是在软件中完成。在这些机器上(由熔岩坑产生的蒸汽提供动力),使用floats 更快。现在,floats 唯一真正的好处是它们占用的空间更少(这仅在您拥有数百万个空间时才重要)。

【讨论】:

  • 也许不是 100 年前...一些 FPU 支持浮点、双精度和 80 位级别的本机处理,并且在较短的长度下执行速度更快。有些实际上会以较短的长度执行一些更慢的事情...... :-)
  • 可能的例外:我认为除法的时间取决于位数(1 个时钟周期/2 位)。我用浮点数和双除法计算的时间似乎与此相符。
  • SIMD 代码注意事项 - 因为您可以将 2 倍的浮点数打包到 SIMD 寄存器(例如 SSE)中,所以对浮点数进行操作可能会更快。但由于它是 C#,这可能不会发生。
  • @P Daddy:我想说空间优势在缓存层次结构的每个级别都很重要。当您的一级数据缓存为 16KB 大并且您正在处理一个包含 4000 个数字的数组时,float 可能会更快。
  • @artificialidiot 永远不要说永远;)。 .NET 自 4.6 起支持 SIMD
【解决方案2】:

这取决于 32 位64 位 系统。如果编译为 64 位,double 会更快。在 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);
    }

【讨论】:

  • 您是否认为这 30% 可能是因为您使用了额外的演员表??
  • @RasmusDamgaardNielsen 演员表是问题的一部分,因为Math 与 double 一起使用。但是你误读了我的帖子:我的测试显示我的性能更好。
  • 上面发布的结果是假的。我的测试表明,在 .NET 4.0 处于发布模式的较旧的 32 位计算机上,floatdouble 的性能几乎相同。在许多独立试验中平均时差异小于 0.3%,其中每个试验对连续链接的变量执行乘法、除法和加法操作(以避免任何编译器优化妨碍)。我用Math.Sin()Math.Sqrt() 尝试了第二组测试,也得到了相同的结果。
【解决方案3】:

我有一个使用 CUDA 的小项目,我记得 float 也比 double 快。一旦主机和设备之间的流量较低(主机是 CPU 和“正常”RAM,设备是 GPU 和相应的 RAM)。但即使数据一直驻留在设备上,它也会变慢。我想我在某处读到过这种情况最近发生了变化,或者应该随着下一代而改变,但我不确定。

因此,在这些情况下,GPU 似乎根本无法原生处理双精度,这也可以解释为什么通常使用 GLFloat 而不是 GLDouble。

(正如我所说,这只是我所记得的,只是在 CPU 上搜索 float 与 double 时偶然发现了这一点。)

【讨论】:

  • GPU 与 FPU 完全不同。正如其他人提到的,FPU 的原生格式是 80 位双精度。现在已经有很长一段时间了。然而,GPU 从单精度接近这个领域。 众所周知,它们的 DP FP(双精度浮点)性能通常是 SP FP 性能的一半。似乎他们经常有 SP 浮点单元,他们不得不重用该单元来覆盖双精度。与一个周期相比,它恰好产生两个周期。这是一个巨大的性能差异,当我面对它时,我惊呆了。
  • 一些科学计算需要 DP FP,而领先的 GPU 制造商并没有宣传这方面的性能损失。现在他们(AMD、nVidia)似乎在 DP 与 SP 主题上有所改进。英特尔至强融核的多核包含奔腾的 FPU,请注意英特尔强调它的双精度功能。这就是它可能真正能够与 GPGPU 怪物竞争的地方。
【解决方案4】:

在某些情况下,浮点数仍然是首选 - 例如,对于 OpenGL 编码,使用 GLFloat 数据类型(通常直接映射到 16 位浮点数)更为常见,因为它在大多数 GPU 上比 GLDouble 更有效。

【讨论】:

  • 可能是因为更高的数据吞吐量?如果您有一个数字矩阵(z 缓冲区等),则数据大小变得更加重要,避免浮点数和双精度数之间的转换可以加快处理速度。我的猜测。
  • 无疑是吞吐量。同样考虑到专门的上下文,使用双精度浮点数不太可能获得任何可见的结果,所以为什么要浪费内存 - 特别是因为它在 GPU 上的供应量比 CPU 短
  • 吞吐量还有一个事实,即 SP FP(单精度浮点)比 DP FP(双精度)更像是 GPU 内部 FPU 的原生格式。请参阅我对@Mene 回答的评论。 GPU 和 CPU FPU 是非常不同的动物,CPU 的 FPU 在 DP FP 中思考。
猜你喜欢
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 2013-07-18
  • 2011-09-05
  • 2013-03-12
  • 2013-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多