gpt4 book ai didi

64 位机器中的 C++ int 与 long long

转载 作者:IT老高 更新时间:2023-10-28 22:17:44 30 4
gpt4 key购买 nike

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

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

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

3) 字和整数大小为 64 位的 x64 计算机是否有可能通过使用所谓的向后兼容性来处理短的、使用 16 位字的大小?或者它必须将 16 位文件转换为 64 位文件,并且可以做到这一点的事实将系统定​​义为向后兼容。

4) 我们可以强制编译器生成吗?国际 64位?

5) 如何将 ILP64 集成到使用 LP64 的 PC 中?

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

最佳答案

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

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

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

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

此外,如果您的编译器足够聪明,可以弄清楚如何使用处理器的 vector 指令(又名 SSE 指令),那么使用较小的数据类型可能会是一个胜利。现代 vector 处理单元足够智能,可以将 8 个 16 位短整数与两个 64 位长整数填充到相同的空间中,因此您可以一次执行四倍的运算。

3) 字和整数大小为 64 位的 x64 计算机是否有可能通过使用所谓的向后兼容性来处理短的、使用 16 位字的大小?或者它必须将 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 位 Intel 处理器有一个名为 RAX 的 64 位寄存器。但是,通过将其称为 EAX,这个相同的寄存器可以在 32 位模式下使用,甚至可以在 16 位和 8 位模式下使用。我从这里偷了一张图:

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 位字。

结果是字长对内存带宽没有任何意义。但是,您可以在可以打包 8 个 64 位整数的相同空间中放置 16 个 32 位整数。或者您甚至可以在同一空间中容纳 32 个 16 位值或 64 个 8 位值。如果您的程序使用许多不同的数据值,您可以通过使用所需的最小数据类型来显着提高性能。

关于64 位机器中的 C++ int 与 long long,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39779880/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com