为什么要将两个32位整数合并成一个64位整数?
最近我看到了一个编译器如何组合两个32位整数,它们是一个类的属性值,并将它们存储为一个64位整数。我现在的问题是,为什么这样做?结合整数有什么优势?为什么要将两个32位整数合并成一个64位整数?
例如,如果我们有一个类
class FooBar {
int x = 1;
int y = 100;
}
以下属性,以便代替
i32 = 00000001
i32 = 01100100
我们得到:
i64 = 0000000101100100
你为什么要结合呢?
现有的(当我写这篇文章的时候)答案和评论虽然部分正确,却错过了这个优化的要点。它是用一条指令(使用64位数据)替换两条指令(使用32位数据)。这会导致代码大小和执行时间的轻微缩短。
编译器使用一个64位指令初始化两个变量(因为它们共享连续的内存地址)。这些变量是分开的,并且将分开访问。不需要移位或掩蔽。
当许多成员初始化时,这在构造函数中经常出现。一个常见的情况是零初始化,编译器会将寄存器清零,然后使用该值初始化多个成员,将写入连续的存储器地址与较大的单次写入相结合(例如,通过写入一个16位短零值而不是两个8位)。
我相信你正在观察优化。英特尔指令(如PADDSW
)假定有多个打包操作数。
https://en.wikipedia.org/wiki/X86_instruction_listings
也有益处只用在64位架构的缓存1项。
如果您只需要其中一个值,则需要解压缩代码,但我怀疑代码优化器正在运行的任何代码都会有更好的存储性能。
将C结构的所有成员对齐到字边界上是正常的。这是一个单独的char
和一个int
不会被打包,但与机器的字大小对齐。因此,struct { char, int}
将具有8个字节的sizeof(..)
。我猜这种情况翻转了?
非常有趣。
您可能听说过webassembly?他们正在那里做。你所说的真的很有趣 – Asperger
“PAD ...”指令适用于SIMD。他们打包的值都是相同的类型。由于个别值仍然具有正常地址,因此解包无需花费。 –
我的猜测是该寄存器使用64位。它只使用一个寄存器来存储这两个寄存器,而不是使用两个寄存器。 –
为什么不呢?如果机器以64位整数工作效率更高,那么这可能是一场胜利。你为什么在乎? –
CPU通常不具有类型。像“int”这样的东西是你的程序的一个属性,而不是机器代码的属性。将这种“组合”称为“合并”并不合适,因为前后是完全不同域的组成部分。 –