Performance x86-64 ISA的32位指针:为什么不呢?

Performance x86-64 ISA的32位指针:为什么不呢?,performance,pointers,x86-64,32bit-64bit,abi,Performance,Pointers,X86 64,32bit 64bit,Abi,x86-64指令集添加了更多寄存器和其他改进,以帮助简化可执行代码。然而,在许多应用程序中,增加的指针大小是一个负担。每个指针中多余的未使用字节会阻塞缓存,甚至可能导致RAM溢出。例如,GCC使用-m32标志构建,我认为这就是原因 可以加载32位的值并将其视为指针。这不需要额外的指令,只需加载/计算32位并从结果地址加载即可。不过,这个技巧不会是可移植的,因为平台有不同的内存映射。在Mac OS X上,整个低4 GiB地址空间被保留。尽管如此,对于我编写的一个程序,在使用前将0x10000000

x86-64指令集添加了更多寄存器和其他改进,以帮助简化可执行代码。然而,在许多应用程序中,增加的指针大小是一个负担。每个指针中多余的未使用字节会阻塞缓存,甚至可能导致RAM溢出。例如,GCC使用
-m32
标志构建,我认为这就是原因

可以加载32位的值并将其视为指针。这不需要额外的指令,只需加载/计算32位并从结果地址加载即可。不过,这个技巧不会是可移植的,因为平台有不同的内存映射。在Mac OS X上,整个低4 GiB地址空间被保留。尽管如此,对于我编写的一个程序,在使用前将
0x10000000L
添加到32位“地址”中,大大提高了性能,超过了真正的64位地址,或者使用
-m32
进行编译

拥有32位x86-64平台是否存在任何基本障碍?我认为,支持这样一个幻想会增加任何操作系统的复杂性,任何想要最后20%的人都应该让它工作起来™, 但这似乎仍然最适合于各种计算密集型程序。

它在Windows上被称为“x86-32仿真”,或WOW64(在其他操作系统上可能是其他操作系统),是处理器中的硬件标志。这里不需要任何用户模式技巧。

在开发中有一个名为“x32”的用于linux的ABI。它是x86_64和ia32之间的混合,类似于您所描述的-32位地址空间,同时使用完整的64位寄存器集。它需要一个自定义内核、binutils和gcc


一些规范运行表明,在某些基准测试中,性能提高了约30%。请参阅

上的进一步信息,我不认为在操作系统中支持这样的模型很难。关于此模型中的流程,唯一需要更改的是页面管理,页面分配必须低于4GB点。如果内核将缓冲区传递给应用程序,那么它也应该从虚拟地址空间的前4 GB分配缓冲区。这同样适用于加载和启动应用程序的加载程序。除此之外,64位内核应该能够在不进行重大修改的情况下处理此类应用程序

编译器支持也不是什么大问题。主要是生成可以使用额外CPU寄存器及其完整64位的代码,并在需要时添加适当的REX前缀。

如上所述,ICC有权在64位模式下使用32位指针:

指示编译器分析程序,以确定是否有64位指针可以安全收缩为32位指针,以及是否有64位长(在Linux*系统上)可以安全收缩为32位长


在Windows上与Linux上没有类似之处,但是您仍然可以通过禁用默认为64位二进制文件启用的标志来使用32位指针

默认情况下,基于64位Microsoft Windows的应用程序具有数TB的用户模式地址空间。有关精确值,请参见。但是,应用程序可以指定系统应为低于2 GB的应用程序分配所有内存。如果满足以下条件,此功能对64位应用程序有利:

  • 2 GB的地址空间就足够了
  • 该代码有许多指针截断警告
  • 指针和整数可以自由混合
  • 代码具有使用32位数据类型的多态性
所有指针仍然是64位指针,但系统确保每次内存分配都低于2GB限制,因此如果应用程序截断指针,则不会丢失任何重要数据指针可以截断为32位值,然后通过符号扩展或零扩展扩展扩展为64位值。

当然,没有直接的编译器支持,所以每次存储指向内存的指针或取消对它的引用时,都需要手动处理指针。最简单的解决方案是编写一个类来包装一个32位指针来处理这个问题


谷歌的V8引擎使用了一种不同的方式来节省内存和提高性能。请参阅内存和性能改进方面的比较

另见


阅读更多


大多数应用程序中的分析数据表明,由于指针大小的增加,没有明显的损失。“英特尔编译器”有“尝试”使用32位作为指针的选项,即使在x64模式下也是如此。@神秘,但这更像老式的
指针,对吗?我想这个解决方案是可以的,但它没有我所指的那么干净。@potatosatter不,它不是。如果我读对了,它实际上试图将所有指针压缩到32位。哦,我以为你指的是过去16位的
near
far
指针。这是用户可访问的标志吗?所以操作系统需要保存/恢复并支持它?啊,查了一下-。不,这只是在64位操作系统上运行标准x86代码,即只有8个寄存器的旧ISA。与
-m32
相同。我不认为其他操作系统会费心给这个“功能”取个名字。@Potatoswatter:这和你描述的完全不同?处理器不是通过用户模式黑客来实现目标,而是通过硬件来实现。那总是会更快。没有编译器标志可以实现这一点,这是一个硬件处理器功能。OP要求使用32位指针的真正64位程序,而不是64位窗口上的32位程序有编译器标志;在GNU/Linux上,它是
gcc-mx32
(与通常的
-O3-march=native
等一起使用)-一种可以在64位模式下使用32位指针的ILP32 ABI,因此您仍然有16个寄存器而不是8个,并且可以有效地执行64位整数操作。还有一个不可怕的通话约定