【问题标题】:Are doubles faster than floats in C#?C# 中的双精度数比浮点数快吗?
【发布时间】:2010-09-14 14:32:22
【问题描述】:

我正在编写一个应用程序,它读取大量浮点数并对其执行一些简单的操作。我正在使用浮点数,因为我认为它会比双精度数更快,但是在做了一些研究之后,我发现这个话题有些混乱。谁能详细说明一下?

【问题讨论】:

    标签: c# performance floating-point precision


    【解决方案1】:

    Matthijs,

    你错了。 32 位比 16 位效率高得多 - 在现代处理器中......也许不是内存方面的,但在有效性方面 32 位是要走的路。

    您确实应该将您的教授更新为更“最新”的东西。 ;)

    无论如何,回答这个问题; float 和 double 具有完全相同的性能,至少在我的 Intel i7 870 上(理论上如此)。

    这是我的测量结果:

    (我做了一个“算法”,我重复了 10,000,000 次,然后重复了 300 次,然后我做了一个平均值。)

    double
    -----------------------------
    1 core  = 990 ms
    4 cores = 340 ms
    6 cores = 282 ms
    8 cores = 250 ms
    
    float
    -----------------------------
    1 core  = 992 ms
    4 cores = 340 ms
    6 cores = 282 ms
    8 cores = 250 ms
    

    【讨论】:

    • 嗯,我想你是对的。也许让我相信这个问题是错误的消息来源是错误的。我将更新我的答案以删除更新(即取消更新我的答案)。
    【解决方案2】:

    我一直认为处理器经过优化或相同,无论浮点数还是双精度数。在我的密集计算(大量从矩阵中获取,两个值的比较)中搜索优化时,我发现浮点数的运行速度快了大约 13%。

    这让我很惊讶,但我想这是由于我的问题的性质。我在核心运算中不做 float 和 double 之间的强制转换,我的计算主要是加法和减法。

    这是在我的 i7 920 上,运行 64 位操作系统。

    【讨论】:

      【解决方案3】:

      浮点数在 32 位系统上应该更快,但分析代码以确保优化正确。

      【讨论】:

      • @Steven A. Lowe:我会注意到一些 32 位系统内部缺少 32 位浮点数!因此,降低了整体性能。从内存带宽的角度来看,您的说法是正确的,因为 float 比 double 更适合。
      【解决方案4】:

      简短的回答是,“使用可接受的结果所需的任何精度。”

      您的一项保证是,对浮点数据执行的操作至少在表达式的最高精度成员中完成。因此,将两个 float 相乘至少达到 float 的精度,然后将 floatdouble 相乘> 将至少以双精度完成。该标准规定“[浮点] 运算可以以比运算结果类型更高的精度执行。”

      鉴于 .NET 的 JIT 试图让您的浮点运算保持所要求的精度,我们可以查看 Intel 的文档以加快我们的运算速度。在 Intel 平台上,您的浮点运算可能以 80 位的中间精度完成,并转换为要求的精度。

      来自 Intel 的 C++ 浮点操作指南1(抱歉只有死树),他们提到:

      • 除非需要通过 double 或 long double 获得的额外精度,否则请使用单精度类型(例如,float)。更高精度的类型会增加内存大小和带宽要求。 ...
      • 避免混合数据类型的算术表达式

      最后一点很重要,因为 you can slow yourself down with unnecessary casts to/from float and double,这会导致 JIT 代码要求 x87 在操作之间放弃其 80 位中间格式!

      1.是的,它说的是 C++,但是 C# 标准加上 CLR 的知识让我们知道 C++ 的信息应该适用于这种情况。

      【讨论】:

      • 附带说明(与您的答案无关),.net JIT 是否使用 x87?一段时间以来,英特尔一直在告诉所有人放弃它,转而支持 SSE。
      • @Mike F:据我所知,似乎没有选择 SSE 操作。不要引用我的话,这只是我在代码中看到的 JIT 的内容。我可能会问微软并找出答案。
      • @sixlettervariables:如果您得到答案并想在此处发布,我将非常有兴趣听到答案。
      • 我同意浮点、双精度、整数、短和字符甚至 1 位的指令需要一个 CPU 周期,而不管类型。但是,如果您考虑寻址、位置、并行处理的比较,是否会出现差异。在我看来,双精度处理的开销更大。做真正的测试并不容易。编译器很聪明,可以优化开销,所以如果测试做相对愚蠢的工作,真正的问题可以隐藏起来。
      • @DeveloperInToronto:许多浮点运算需要多个周期。一些整数运算也是如此。此外,比较的基线甚至不是“1 个周期”,而是一小部分,因为现代 CPU 有多个 ALU。
      【解决方案5】:

      我刚刚阅读了 MCTS 考试 70-536 的“Microsoft .NET Framework-Application Development Foundation 2nd”,第 4 页(第 1 章)有注释:

      注意使用内置类型优化性能
      运行时优化了 32 位整数类型(Int32 和 UInt32)的性能,因此将这些类型用于计数器和其他经常访问的整数变量。对于浮点运算,Double 是最有效的类型,因为这些运算是由硬件优化的。

      它是由托尼·诺斯鲁普 (Tony Northrup) 撰写的。我不知道他是否是权威,但我希望.NET 考试的官方书籍应该有一定的分量。这当然不是保证。我只是想我会把它添加到这个讨论中。

      【讨论】:

        【解决方案6】:

        我正在编写一个光线追踪器,并将我的 Color 类的浮点数替换为双精度数可以使我的速度提高 5%。用 double 替换 Vectors 浮点数再快 5%!很酷:)

        Core i7 920 是这样的

        【讨论】:

        • 我猜是因为你的一些代码在 float->double->float 之间来回转换,例如使用返回 double 的数学函数,因此消除强制转换是加快速度的原因;不一定是因为双打天生就更快。
        • 实际上,我收回了这一点。我刚刚用一个简单的 for 循环进行了测试,无论出于何种原因,似乎双打 更快!
        • 处理器无关。无论您是在慢速还是快速 PC 上执行此操作...... 5% 的改进就是 5% 的改进 :-)
        【解决方案7】:

        对于 387 FPU 算术,float 仅在某些长迭代操作(如 pow、log 等)中比 double 快(并且仅当编译器正确设置 FPU 控制字时)。

        使用打包的 SSE 算法,它会产生很大的不同。

        【讨论】:

          【解决方案8】:

          几周前我提出了一个类似的问题。底线是对于 x86 硬件,浮点数与双精度数的性能没有显着差异,除非您受到内存限制,或者您开始​​遇到缓存问题。在这种情况下,浮点数通常具有优势,因为它们更小。

          当前的 Intel CPU 在 80 位宽的寄存器中执行所有浮点运算,因此实际计算速度不应在浮点数和双精度数之间变化。

          【讨论】:

            【解决方案9】:

            如果加载和存储操作是瓶颈,那么浮点数会更快,因为它们更小。如果您在加载和存储之间进行大量计算,它应该大致相等。

            其他人提到避免浮点和双精度之间的转换,以及使用这两种类型的操作数的计算。这是个好建议,如果您使用任何返回双精度的数学库函数(例如),那么将所有内容都保留为双精度会更快。

            【讨论】:

            • C# 就是这种情况,所有数学运算都返回双精度数。对于文字值,您可以将 f 等用于值本身。
            【解决方案10】:

            这表明浮点数比双精度数稍快:http://www.herongyang.com/cs_b/performance.html

            一般来说,在进行性能比较时,您应该考虑任何特殊情况,例如使用一种类型是否需要额外的转换或数据按摩?这些加起来可能会掩盖这样的通用基准。

            【讨论】:

            • 我不知道我是否会相信一些家伙的基准,其中精度下降到不到一秒。为什么不写一个更大的(和更多不同类型的测试更真实的基准测试)并让它运行几分钟?
            • 我尝试了这个测试,在发布版本中,它们需要相同的处理时间。
            猜你喜欢
            • 1970-01-01
            • 2015-10-22
            • 1970-01-01
            • 2010-12-19
            • 2011-12-04
            • 1970-01-01
            • 1970-01-01
            • 2011-10-24
            • 2018-02-23
            相关资源
            最近更新 更多