1) 如果在x64中使用long long以实现最大性能,即使对于1-4字节的数据,这是否是最佳实践?
不是最佳实践,实际上可能会降低性能。例如,如果您在可以使用32位整数的情况下使用64位整数,则刚刚将必须在处理器和内存之间发送的数据量加倍,而内存速度要慢得多。所有缓存和内存总线都将两倍崩溃。
2) 使用小于字长的类型的权衡(内存优势与额外操作)
通常,在现代计算机中,性能的主要驱动因素将是运行程序所需存储的数据量。一旦程序的工作集大小超过寄存器、L1高速缓存、L2高速缓存、L3高速缓存和RAM的容量,你将看到显著的性能下降。
此外,如果编译器足够聪明,能够找出如何使用处理器的矢量指令(也称为SSE指令),使用较小的数据类型可能会更好。现代矢量处理单元足够聪明,可以将8个16位短整数压缩到与两个64位long long整数相同的空间中,因此您可以同时执行四倍的操作。
3) 在使用64位字和整数的x64计算机上,是否可以通过所谓的向后兼容性使用16位字大小来处理short?或者必须将16位文件放入64位文件中,并且能够这样做的事实定义了系统为向后兼容。
我不确定您在此处询问的是什么。一般来说,64位计算机能够执行32位和16位可执行文件,因为这些早期的可执行文件使用了64位计算机潜力的子集。
硬件指令集通常是向后兼容的,这意味着处理器设计人员倾向于添加功能,但很少或从不删除功能。
4) 我们能强制编译器使int为64位吗?
所有编译器都有相当标准的扩展,允许您使用固定位大小的数据。例如,头文件stdint.h
声明了类型,如int64_t
、uint64_t
等。
5) 如何将ILP64合并到使用LP64的PC中?
https://software.intel.com/en-us/node/528682
6) 使用适应上述问题的代码与其他编译器、操作系统和架构(32位处理器)可能存在哪些问题?
通常情况下,编译器和系统都足够聪明,可以在任何给定的系统上执行您的代码。然而,32位处理器需要额外的工作才能处理64位数据。换句话说,正确性不应该是一个问题,但性能会受到影响。
但通常情况下,如果性能对您来说真的很重要,那么您需要为特定的架构和平台编程。
澄清请求:非常感谢! 我想澄清第1个问题。您说它对内存有害。让我们以32位int为例。当您将其发送到内存时,因为它是64位系统,对于所需的整数0xee ee ee ee,当我们发送它时,它不会变成0x ee ee ee ee + 32个其他位吗?当字长为64位时,处理器如何发送32位?32位是期望的值,但它不会与32个未使用的位组合并以这种方式发送吗?如果我的假设是正确的,那么对于内存就没有区别了。
这里有两件事需要讨论。
首先,你所讨论的情况并不存在。处理器不需要将32位值“提升”为64位值以便适当使用它。这是因为现代处理器具有不同的访问模式,能够适当地处理不同大小的数据。
例如,64位英特尔处理器有一个名为RAX的64位寄存器。但是,通过将其称为EAX,甚至在16位和8位模式下,同样的寄存器可以在32位模式下使用。我从这里偷了一张图:
x86_64 registers rax/eax/ax/al overwriting full register contents
1122334455667788
================ rax (64 bits)
======== eax (32 bits)
==== ax (16 bits)
== ah (8 bits)
== al (8 bits)
在编译器和汇编器之间,生成正确的代码以便适当处理32位值。
其次,当我们谈论内存开销和性能时,应该更加具体。现代内存系统由磁盘、主存储器(RAM)和通常两到三个高速缓存(例如L3、L2和L1)组成。可以在磁盘上寻址的最小数据量称为“页面”,页面大小通常为4096字节(尽管不必如此)。然后,在内存中可以寻址的最小数据量称为“缓存行”,它通常比32位或64位大得多。在我的电脑上,缓存行大小为64字节。处理器是唯一实际传输数据并在字级别及以下地址的地方。
因此,如果您想要更改存储在磁盘上的一个64位单词,则在我的计算机上,这实际上需要将4096字节从磁盘加载到内存中,然后将64字节从内存加载到L3、L2和L1缓存中,然后处理器从L1缓存中取出一个64位单词。
结果是字长对内存带宽毫无意义。然而,你可以在相同的空间里放入16个32位整数或8个64位整数。或者你甚至可以在相同的空间里放置32个16位值或64个8位值。如果你的程序使用了许多不同的数据值,你可以通过使用最小的数据类型显著提高性能。
int
仍然是100%标准兼容的。为什么有人会这样做超出了我的理解,但它仍然是合法的。 - user4581301