【问题标题】:Is there any difference in speed in manipulating different types of variables?处理不同类型变量的速度有什么不同吗?
【发布时间】:2009-08-16 19:29:19
【问题描述】:

这是参考 C++ 并使用 Visual Studio 编译器。

在读/写(到 RAM)和对不同类型的变量(如 bool、short int、int、float 和 doubles)进行数学运算时,速度是否有差异?

据我目前所知,使用双精度进行数学运算(我说的是 32 位处理器,我对 64 位处理器知之甚少)比使用浮点数的运算花费的时间要长得多。

那么如何比较使用 float 和 int 进行操作(读取/写入 ram 和初等数学)? int 和 short int,甚至每种类型的有符号和无符号版本之间的差异如何?是否有任何一种数据类型可以最有效地用作小数计数器?

谢谢, -伪造

【问题讨论】:

  • 您应该只编写一个程序,对不同的数据类型执行数十万次相同类型的操作,并使用高分辨率计时器对其进行计时。另外,看看编译器生成的反汇编,看看是否生成了更多或更复杂的指令。没有什么比自己想办法更好的了。

标签: c++ performance variables


【解决方案1】:

这里有两个不同的问题:读/写速度和算术性能。这些是正交的。当然,在读取或写入大型数组时,速度取决于读取为 O(N) 的字节数,因此使用 short 而不是 int(考虑 VC++)将时间缩短约 1/2。

对于算术,一旦操作数在寄存器中,类型的大小就无关紧要了。 IIRC,在同一类别的类型之间,实际上是相同的(所以short 并不比int 快​​或慢)。在 32 位平台上使用 64 位整数类型自然会受到惩罚,因为没有一条指令可以处理它。另一方面,浮点类型比所有整数类型都慢,即使在 VC++ 上是 sizeof(float)==sizeof(int)。但是,同样,float 上的操作并不比double 上的操作快;这是假设默认 FPU 设置,将所有操作数提升为 80 位扩展浮点数 - 可以禁用此功能以从使用 floats,IIRC 中挤出更多。

根据问题的要求,以上是 VC++ 和 x86 特定的。其他平台,尤其是其他架构,可能会大不相同。

作为数字计数器最有效的一种数据类型(低或低)是int - 通常与架构和实现无关(因为标准建议将其作为平台的首选字长)。

【讨论】:

    【解决方案2】:

    据我目前所知,使用双精度数的数学运算(我们谈论的是 32 位处理器,我对 64 位处理器知之甚少)比使用浮点数的运算要长得多。

    我不知道(我几乎从未编写过浮点运算),但我对此表示怀疑:因为 double 是本机精度(硬件支持),而我不知道浮点数。

    那么如何比较浮点和整数的操作(读/写内存和初等数学)?

    float 比 int 慢。

    int 和 short int,甚至每个变量的有符号和无符号版本之间的差异如何?

    Short 可能比 int 慢,因为 CPU 本身使用 int 并且需要截断结果以使其变短。只有当它们有很多连续的以更好地适应 CPU 缓存时,它们才会更快。

    每个变量的有符号和无符号版本之间的区别?

    不,我不这么认为。

    是否有任何一种数据类型可以最有效地与小数计数器一起使用?

    int.

    【讨论】:

    • 是的,如果有疑问,请使用 int。
    • x86 上的“本机”浮点精度实际上是 long double(80 位),因为这是 FPU 寄存器的大小。在任何情况下,它都不会影响floatdouble 的性能。
    • 值得指出的是,SSE 浮点运算通常使用更窄的类型更快吗? (也就是说,每个数据类型更窄的操作更多。)
    • @greyfade - 正如 OP 所说,浮点数是否比双精度数“快得多”?我的猜测是它们并没有太大的不同,因为它们都使用硬件 FPU。
    • @ChrisW:我的意思是,与使用 doubles 相比,在 SSE 寄存器中使用 floats 可以同时对更多值执行更多操作。 shorts 与 ints 等也是如此。
    【解决方案3】:

    大多数 CPU 在与其自然字长匹配的数据类型上运行速度最快。因此,根据架构,4 或 8 字节数据类型。 int 通常被定义为“自然字大小”,因此对 int 的任何操作都应该很快。

    然而,实际上,与任何类型的算术运算相比,您要为缓存未命中、软页和硬页错误以及内存访问付出更多的代价,因此优化数据类型可能会浪费时间.

    分析您的代码,然后优化热点。

    【讨论】:

    • 在 C++ 中,int总是定义为底层平台的自然整数类型。否则,特别是关于缓存等的特殊性。我希望我有更多的选票来投票支持这一点。对于首先介绍个人资料的建议,我会给你十票。 :)
    • 总是定义,但只有有时这样实现。最著名的反例是许多平台上的 x86-64 CPU,由于缺少“short short int”,它仍然具有 32 位 int。
    • @MSalters:我相信 32 位 int 在 64 位平台上令人厌恶的原因在于,他们不想让那些假设 int 编写代码的“程序员”失望是32位。我讨厌这个主意。 :(
    【解决方案4】:

    这在很大程度上取决于 C++ 代码的体系结构和编译的程序集。例如在 MIPS 上,浮点运算需要读取和读取多个 CPU 寄存器。

    这种类型的微优化应该不会对性能产生太大影响,应该留给编译器来处理。如果您希望优化某些内容,您应该分析您的应用程序的瓶颈。

    【讨论】:

    • 但他明确表示 Visual Studio 编译器和 32 位,所以我认为在这里假设 x86 是安全的。但你的观点是正确的。
    • 错了,好的。不幸的是,这并不能回答我的问题。一般来说,我想知道对于标准 x86 处理器,操作变量类型的相对速度。我是一名新程序员,我的程序有循环运行数学运算,计算次数达到数十亿甚至数万亿次,所以我确实有某种合理的理由。内存使用、精度、速度等之间的权衡/
    • 相对速度非常小,即使对图元进行多次重复操作也不会有明显差异。使用适合变量的类型。编译器将负责将位从内存移动到 CPU 寄存器。
    • 简单的答案是尝试一下。如果你在一个循环中运行十亿次(展开 10 或 100),然后看看它需要多少秒,那就等于纳秒。通常浮点比整数类型慢(因为它做的更多)。不过,一般来说,必须对代码进行非常积极的调整,然后才能做到这一点。
    【解决方案5】:

    我不知道处理双精度和浮点数的方式有什么区别,但我很确定它是使用浮点单元完成的。这与整数和长整数的寄存器操作相比较。 (现代 CPU 中是否有单独的整数计算处理器?)

    由于缓存级别和与 RAM 写入速度相比非常高的 CPU 时钟速度,现在要回答写入 RAM 的问题非常棘手。

    就性能而言 - 先衡量!

    编写准确反映您的目标环境的性能测试。

    【讨论】:

      【解决方案6】:

      主内存访问对性能的影响与 CPU 缓存类似。现代(SDRAM、DDRx)DRAM 访问时间随着参考的局部性而显着提高。这意味着您希望数据是连续的。这通常与面向对象相矛盾。 OOD 会让您将一个对象的所有元素放在一起。如果您的算法要求对一个对象的各种元素进行操作,那么您的引用局部性会很好。如果您的算法要求对多个对象的同一元素进行操作,那么您的位置将很糟糕。如果您有“运行数十亿甚至数万亿次计算的数学运算的循环”,那么您很可能遇到后一种情况。如果您的操作是从对象中挑选元素,那么您的 CPU 缓存和 RAM 预取可能几乎无效甚至有害。如果是这种情况,您可以通过将对象数组分解为类似元素的同步数组来显着提高性能。它很丑,但可以更快。

      【讨论】:

      • 所有数据都将非常整齐地排列在一个巨大的堆数组中,并按顺序进行处理。例如,假设对三个 x-y 坐标值进行了多次计算。堆数组中的值将像这样排列:x1、y1、x2、y2、x3、y3,并为下一组重复该模式。位置非常完美。
      【解决方案7】:

      如果您可以使用 SIMD 原语,则可以使用较小的类型(浮点数、8 位整数等)显着提高性能。 SIMD 原语可以将八个 8 位 int 操作(或两个双精度数或 4 个浮点数等)打包成一个在硬件中并行化的操作。不过,SIMD 原语仅在 Pentium III 之后的 CPU 上受支持。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-25
        • 2021-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-22
        • 1970-01-01
        相关资源
        最近更新 更多