C ++ int vs 64位机器长

时间:2016-09-29 20:55:57

标签: c++ performance memory 32bit-64bit word

我的电脑有64位处理器,当我查找sizeof(int)sizeof(long)sizeof(long long)时,结果是 int 是32位,长long 是64位。我研究了原因,看来普遍认为C ++中的 int 符合机器的字大小是错误的。据我所知,编译器需要定义大小,我的是Mingw-w64。我研究的原因是理解如果使用小于字大小的类型有利于速度(例如, vs int )或是否有负面影响。在32位系统中,一个流行的观点是:由于字大小 int 将转换为 int ,它会导致额外的位移等,从而导致更差的性能。反对意见是缓存级别会有好处(我没有深入研究),使用对虚拟内存经济有用。所以,除了这种困境之间的混淆之外,我还面临着另一个问题。我的系统是64位,如果我使用 int short 并不重要,它仍然会小于字大小,我开始认为使用64位 long long 是不是有效率,因为它处于系统设计的级别。另外我读到还有另一个约束,即OS的库(ILP64,LP64),它定义了类型大小。在ILP64中,与LP64相比,默认 int 是64位,如果我使用支持ILP64的操作系统,它会加速程序吗?一旦我开始询问我应该使用哪种类型来加速我的C ++程序,我就面临更深层次的主题,其中我没有专业知识,而且一些解释似乎相互矛盾。你能解释一下:

1)如果最佳做法是在x64中使用 long long 来实现最高性能,即使对于1-4字节数据也是如此?

2)使用小于字数的类型(内存胜利与附加操作)的权衡

3)word& int size为64位的x64计算机是否有可能通过使用所谓的向后兼容性使用16位字大小来处理短路?或者它必须将16位文件放入64位文件中,并且可以完成的事实将系统定​​义为向后兼容。

4)我们可以强制编译器使 int 64位吗?

5)如何将ILP64合并到使用LP64的PC中?

6)使用适用于其他编译器,操作系统和架构(32位处理器)的上述问题的代码有哪些可能出现的问题?

1 个答案:

答案 0 :(得分:30)

1)如果最好在x64中使用long long来实现最高性能,即使对于1-4字节数据也是如此?

不 - 它实际上可能会使您的表现更糟。例如,如果你使用64位整数,你可以用32位整数,那么你只需要在处理器和内存之间发送的数据量增加一倍,内存就会慢几个数量级。你的所有缓存和内存总线都会快两倍。

2)使用小于字号的类型(内存胜利与附加操作)的权衡

通常,现代机器性能的主要驱动因素是需要存储多少数据才能运行程序。一旦程序的工作集大小超过了寄存器,L1缓存,L2缓存,L3缓存和RAM的容量,您就会看到重要的性能悬崖。

此外,如果您的编译器足够聪明以了解如何使用处理器的向量指令(也称为SSE指令),则使用较小的数据类型可能会获胜。现代矢量处理单元非常智能,可以将8个16位短整数填充到与两个64位长整数相同的空间中,因此一次可以执行四次操作。

3)x64计算机中word& int大小是64位,是否有可能通过使用所谓的向后兼容性使用16位字大小来处理短路?或者它必须将16位文件放入64位文件中,并且可以完成的事实将系统定​​义为向后兼容。

我不确定你在这里问的是什么。通常,64位计算机能够执行32位和16位可执行文件,因为早期的可执行文件使用64位计算机的潜在子集。

硬件指令集通常是向后兼容的,这意味着处理器设计人员倾向于添加功能,但很少会删除功能。

4)我们可以强制编译器使int 64位吗?

所有编译器都有相当标准的扩展,允许您使用固定位大小的数据。例如,标题文件stdint.h声明了int64_tuint64_t等类型。

5)如何将ILP64合并到使用LP64的PC中?

https://software.intel.com/en-us/node/528682

6)使用适用于其他编译器,操作系统和架构(32位处理器)的上述问题的代码会出现什么问题?

通常,编译器和系统足够聪明,可以弄清楚如何在任何给定系统上执行代码。但是,32位处理器将不得不做额外的工作来操作64位数据。换句话说,正确性不应该是一个问题,但性能将是。

但通常情况下,如果性能对您来说真的很重要,那么无论如何您都需要针对特定​​的架构和平台进行编程。

澄清请求:非常感谢!我想澄清问题:1。你说它对记忆有害。让我们举一个32位int的例子。当你把它发送到内存时,因为它是64位系统,对于一个所需的整数0xee ee ee,当我们发送它时它会变成0xee ee ee ee + 32个其他位?当字长为64位时,处理器如何发送32位? 32位是所需的值,但是它不能与32个未使用的位组合并以这种方式发送?如果我的假设是正确的,那么内存没有区别。

这里有两件事要讨论。

首先,您讨论的情况不会发生。处理器不需要"促进"将32位值转换为64位值以便正确使用它。这是因为现代处理器具有不同的访问模式,能够适当地处理不同大小的数据。

例如,64位Intel处理器有一个名为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位值。如果您的程序使用大量不同的数据值,则可以使用所需的最小数据类型来显着提高性能。