2016-09-29 78 views
4

我的计算机有64位处理器,并且当我寻找sizeof(int)sizeof(long)sizeof(long long),事实证明,INT是32位,并且长长是64位。我研究了其中的原因,并且似乎在C++中符合机器字大小的流行假设是错误的。据我了解,由编译器决定什么是规模,而我的是Mingw-w64。我的研究理由是,如果使用小于字号的字体对字体速度有利(例如,int),或者它有负面影响。在32位系统中,一个流行的观点是:由于字长为int,short将被转换为int并且它会导致额外的位移等,从而导致更差的性能。反对的意见是,缓存级别会有好处(我没有深入),并且使用short对于虚拟内存的经济性将是有用的。所以,除了这种困境之间的混乱之外,我还面临着另一个问题。我的系统是64位的,如果我使用intshort,它仍然会小于字的大小,并且我开始认为使用64位长长,因为它在系统设计的水平。另外我读到还有另一个约束,即定义类型大小的OS(库函数(ILP64,LP64))。在ILP64默认INT是64位与LP64相反,如果我使用支持ILP64的操作系统,它会加快程序吗?一旦我开始问我应该用哪种类型来加速我的C++程序,我面临着更多的深层次的话题,我没有专业知识,而且一些解释似乎与彼此矛盾。你能解释一下吗?C++ INT VS在64位机器长长

1)如果最好的做法是在x64中使用long long,即使对于1-4字节的数据也能获得最大性能?

2)权衡在使用A型小于字大小(存储器赢VS附加操作)

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

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

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

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

+2

永远不要依赖标准数据类型来获得特定的大小。为此,C++ 11具有[固定宽度整数类型](http://en.cppreference.com/w/cpp/types/整数)。 (在C++ 11之前有编译器特定的类型) – UnholySheep

+0

你可以有一个512位的CPU和一个16位的'int'仍然是100%符合标准。为什么任何人都会这样做,但这仍然是合法的。 – user4581301

回答

15

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

不,它可能实际上会让你的表现更糟。例如,如果您使用64位整数,而您可以使用32位整数,那么您只需将处理器和内存之间必须发送的数据量增加一倍,并且内存的速度要慢几个数量级。所有的高速缓存和内存总线都会浪费两倍的速度。

2)权衡使用类型小于字大小(内存胜利VS额外的操作)

一般的性能于一体的现代化机器的主要驱动力将是多少数据需要存储以便运行程序。一旦程序的工作集大小超过了寄存器,L1缓存,L2缓存,L3缓存和RAM的容量,您将看到显着的性能悬崖。

此外,如果您的编译器足够聪明,可以指出如何使用处理器的向量指令(又名SSE指令),那么使用较小的数据类型可能会成功。现代矢量处理单元足够聪明,可以将8个16位短整数塞入与两个64位长整数相同的空间,因此您可以一次执行四倍的操作。

3)是否有一个x64计算机的字& 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)什么是使用适合于上述问题和其它编译器,OS的代码的可能的问题,和体系结构(32位处理器)?

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

但是,一般情况下,如果性能对您来说确实非常重要,那么无论如何您都需要针对特定​​架构和平台进行编程。

澄清要求:非常感谢!我想澄清问题1:1。你说这对记忆不好。让我们以32位int为例。当你将它发送到内存时,因为它是64位系统,对于所需的整数0xeeee ee,当我们发送它时它不会变为0xeeeeeeeee + 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位字。

结果是字大小对于内存带宽没有任何意义。但是,您可以将32位整数中的16个整合到同一空间中,您可以打包这些64位整数中的8个整数。或者你甚至可以在同一个空间中放32个16位值或64个8位值。如果您的程序使用许多不同的数据值,则可以使用必需的最小数据类型显着提高性能。

+0

非常感谢!我想澄清问题1:1。你说这对记忆不好。让我们以32位int为例。当你将它发送到内存时,因为它是64位系统,对于所需的整数0xeeee ee,当我们发送它时它不会变为0xeeeeeeeee + 32其他位?当字长为64位时,处理器如何发送32位? 32位是所需的值,但不会与32个未使用的位组合使用并以此方式发送?如果我的假设是真的,那么记忆就没有区别。 – UserRR

+0

@UserRR您有一个64位寄存器和一个64位总线,但高速缓存和RAM仍然只是一排位。如果指定32位,则使用32位。 – user4581301

+0

@UserRR更新答案与答复 – David