2017-04-22 249 views
13

最近我看到了一个编译器如何组合两个32位整数,它们是一个类的属性值,并将它们存储为一个64位整数。我现在的问题是,为什么这样做?结合整数有什么优势?为什么要将两个32位整数合并成一个64位整数?

例如,如果我们有一个类

class FooBar { 
int x = 1; 
int y = 100; 
} 

以下属性,以便代替

i32 = 00000001 
i32 = 01100100 

我们得到:

i64 = 0000000101100100 

你为什么要结合呢?

+6

我的猜测是该寄存器使用64位。它只使用一个寄存器来存储这两个寄存器,而不是使用两个寄存器。 –

+0

为什么不呢?如果机器以64位整数工作效率更高,那么这可能是一场胜利。你为什么在乎? –

+2

CPU通常不具有类型。像“int”这样的东西是你的程序的一个属性,而不是机器代码的属性。将这种“组合”称为“合并”并不合适,因为前后是完全不同域的组成部分。 –

回答

10

现有的(当我写这篇文章的时候)答案和评论虽然部分正确,却错过了这个优化的要点。它是用一条指令(使用64位数据)替换两条指令(使用32位数据)。这会导致代码大小和执行时间的轻微缩短。

编译器使用一个64位指令初始化两个变量(因为它们共享连续的内存地址)。这些变量是分开的,并且将分开访问。不需要移位或掩蔽。

当许多成员初始化时,这在构造函数中经常出现。一个常见的情况是零初始化,编译器会将寄存器清零,然后使用该值初始化多个成员,将写入连续的存储器地址与较大的单次写入相结合(例如,通过写入一个16位短零值而不是两个8位)。

+0

接受你的答案,因为我觉得它是更完整。 – Asperger

+0

这是一个完美的答案,认真。谢谢 – Asperger

+3

>不需要移位或掩蔽。 我不同意这一点。您必须将内存空间别名为4字节对齐。请参阅此链接:https://software.intel.com/en-us/articles/coding-for-performance-data-alignment-and-structures 这么说,我认为你是正确的,别名地址为32或在性能方面,64接近“免费”。很好的答案。 – Sam

5

我相信你正在观察优化。英特尔指令(如PADDSW)假定有多个打包操作数。

https://en.wikipedia.org/wiki/X86_instruction_listings

也有益处只用在64位架构的缓存1项。

如果您只需要其中一个值,则需要解压缩代码,但我怀疑代码优化器正在运行的任何代码都会有更好的存储性能。

将C结构的所有成员对齐到字边界上是正常的。这是一个单独的char和一个int不会被打包,但与机器的字大小对齐。因此,struct { char, int}将具有8个字节的sizeof(..)。我猜这种情况翻转了?

非常有趣。

+0

您可能听说过webassembly?他们正在那里做。你所说的真的很有趣 – Asperger

+0

“PAD ...”指令适用于SIMD。他们打包的值都是相同的类型。由于个别值仍然具有正常地址,因此解包无需花费。 –

相关问题