在64位编译器和操作系统中使用64位整数

7

我对在面向64位操作系统时何时使用64位整数有疑问。

是否有人做过针对生成代码速度的定量研究?

  • 使用64位整数作为函数或方法的参数是否更好?(例如:uint64 myFunc(uint64 myVar)) 如果我们使用64位整数作为参数,它将占用更多内存,但也许效率会更高。 如果我们知道某个值始终应小于,例如,10。我们仍然要将这个参数设为64位整数吗?

  • 使用64位整数作为返回类型是否更好? 使用32位作为返回值会有什么惩罚吗?

  • 使用64位整数作为循环变量是否更好?(例如:for(size_t i=0; i<...))在这种情况下,我认为是的。 使用32位变量作为循环变量会有什么惩罚吗?

  • 使用64位整数作为指针索引是否更好?(例如:myMemory[index])在这种情况下,我认为是的。 使用32位变量作为索引会有什么惩罚吗?

  • 对于类或结构中不想保存到磁盘等的数据,使用64位整数是否更好?

  • 将bool类型设为64位是否更好?

  • 关于64位整数和浮点数之间的转换,现在使用double是否更好? 到目前为止,双精度数比单精度数慢。

  • 每次访问32位变量时,是否有惩罚?

谢谢!


4
尽管可能会对性能产生实际或想象中的影响,但请使用最能清晰表达您意图的方式。只有在真正需要时(即少于0.1%的情况下)才担心性能损失。在关键情况下,请考虑使用<stdint.h>中的*_fast_*类型。 - Paul R
1
@PaulR:在这种特定情况下,我有点不同意。大小惩罚可能相当显著。 - Jan Hudec
编译成64位的唯一好处是可以访问超过4GB的内存,并且amd64比ix86有更多的寄存器。大多数程序并不需要前者,后者的好处很容易被更大的内存消耗造成的缓存未命中所抵消。虽然我没有严格的测量数据来证明这一点。 - Jan Hudec
1
即使在AMD64/EM64T上,虽然地址空间实际上是64位,但一些编译器支持32位指针选项(这允许更多的数据适合缓存)。 - Ben Voigt
“过早优化是万恶之源” (c) Donald Knuth - SomeWittyUsername
显示剩余8条评论
3个回答

4

我同意@MarkB的观点,但希望在一些问题上提供更详细的解释。

在x64上,有更多的寄存器可用(数量增加了两倍)。因此,标准调用约定默认采用将更多参数放入寄存器中的方式。只要参数数量不过多(通常为4个或更少),它们的类型就不会产生影响。无论如何,它们都会被转换为64位并传递到寄存器中。

即使寄存器中传递了这些64位寄存器,内存中仍然会分配空间。这是出于设计考虑,使其存储位置与多余参数的连续性更加简单。对于多余的参数,无论如何都会将它们放置在堆栈上,因此在这些情况下大小可能很重要。

这个问题对于内存数据结构尤其重要。使用64位而32位足以满足需求的情况将浪费内存,并且更重要的是,占用缓存行的空间。但缓存影响并不简单。如果您的数据访问模式是顺序的,那么当您实际上只需要每个64位量的一半时,您将通过使得一半的缓存无法使用而受到代价。

如果您的访问模式是随机的,那么缓存性能就不会受到影响。这是因为每个访问都占用一个完整的缓存行。

访问小于字长的整数可能会有轻微影响。但是,流水线和多发指令将使得额外的指令(零或符号扩展)几乎总是被隐藏并且不会被观察到。

所有这些的要点很简单:选择与您的问题相关的整数大小。对于参数,编译器可以根据需要进行促进。对于内存结构,通常越小越好。


请注意,在x86平台上,使用8位或16位整数比使用32位整数更低效。此外,提升一个整数的效率比不提升要低;) - Darky
@Darky 这对于旧的实现(P4)是正确的,但对于当前的CPU(P4之后的任何东西,除了可能的Atom)可能不太适用。请查看由GMP团队制作的http://gmplib.org/~tege/x86-timing.pdf中`mov`,`movzx`和`movsx`的延迟和吞吐量数据。 - Kevin A. Naudé

3
您在这个问题中提出了大量问题。我认为您的所有问题基本上都涉及微观优化。因此,我将给出一个两部分的答案:
  • 不要从性能角度考虑大小,而是使用反映它们所包含数据的类型,并相信编译器的优化器会解决这个问题。

  • 如果在开发过程中出现性能问题,请对代码进行性能分析。然后,您可以根据需要进行算法调整,并且如果分析器显示整数操作存在问题,则可以进行不同大小的比较以进行比较。


SIMD(MMX,SSE)和缓存效应可能会使32位的浮点数即使被截断也更快。此外,在x86机器上,双精度浮点数也会被截断。 - Ben Voigt
@Ben Voigt,“double”类型在使用扩展精度数学计算结果时也会被截断,但并非总是如此。 - Mark B
x87寄存器比“double”变量宽。如果禁用扩展精度,你可以说截断是微不足道的,但你仍然会失去表示的位数。 - Ben Voigt
@MarkB 我成功地将一个程序的效率提高了一倍,不再依赖编译器的好意(例如光线追踪器)。 - Darky
@MarkB:双精度浮点数比单精度浮点数慢。如果你不相信,可以自己验证一下。 - Darky
我已经删除了我的答案中的浮点部分,因为我没有硬证据支持某个特定的立场。 - Mark B

0

使用int,并相信平台和编译器的作者已经完成了他们的工作,并选择了最有效的表示方式。在大多数64位平台上,它是32位,这意味着它不比64位类型低效。


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