2009-06-28 116 views
11

英特尔的32位处理器(例如Pentium)具有64位宽的数据总线,因此每次访问可获取8个字节。基于此,我假设这些处理器在地址总线上发出的物理地址始终为8的整数倍。32位英特尔处理器上的内存对齐

首先,这个结论是否正确?其次,如果它是正确的,那么应该在8字节边界上对齐数据结构成员。但我已经看到人们在这些处理器上使用4字节对齐方式。

他们怎么能这样做是正当的?

+1

我不知道这个问题是什么意思,但是我对这与编程有关,以及这可能如何影响我感兴趣。我在哪里可以读到这种低级别类型的基本介绍? – 2009-06-28 10:38:53

+4

请参阅“每个程序员应该知道什么关于内存”:http://people.redhat.com/drepper/cpumemory.pdf – Crashworks 2009-06-28 10:56:24

+1

如何从“请求的读取总是8的倍数”到“您的数据始终应该始于一个8字节的边界“?我没有看到这些之间的逻辑连接。只要数据不交叉* 8字节的边界,我们就很好,是不是? – jalf 2009-06-28 11:59:35

回答

14

通常的经验法则(直接来自英特尔和AMD的优化手册)是每个数据类型应该按照自己的大小进行对齐。 int32应该在32位边界上对齐,在64位边界上则为int64,依此类推。字符在任何地方都适合。

另一个经验法则当然是“编译器已经被告知对齐要求”。您不必担心它,因为编译器知道添加正确的填充和偏移量以允许有效地访问数据。

唯一的例外是使用SIMD指令时,您必须在大多数编译器上手动确保对齐。

其次,如果它是正确的,那么一个 应 8字节边界对齐数据结构成员。但我看到 人使用4字节对齐 代替这些处理器。

我看不出有什么不同。 CPU可以简单地为包含这4个字节的64位块发出读取。这意味着它可以在请求的数据之前或之后获得4个额外的字节。但在这两种情况下,它只需要一次读取。 32位宽数据的32位对齐确保它不会跨越64位边界。

6

物理总线是64位宽... 8的倍数 - >是

然而,有两个因素需要考虑:

  1. 有的x86指令集是字节寻址。有些是32位对齐(这就是为什么你有4个字节的东西)。但没有(核心)指令是64位对齐的。 CPU可以处理未对齐的数据访问。
  2. 如果你关心性能,你应该考虑缓存行,而不是主内存。高速缓存线要宽得多。
0

对于随机访问和只要数据没有错位(例如跨越边界),我认为这不重要;数据中的正确地址和偏移量可以通过硬件中的简单AND结构来找到。当一个读访问不足以获得一个值时,它会变慢。这也是为什么编译器通常会将小值(字节等)放在一起的原因,因为它们不必位于特定的偏移处;短路应该在偶数地址上,32位在4字节地址和64位在8字节地址上。

请注意,如果您有缓存的involed和线性数据访问,事情会有所不同。

2

这样做是有道理的,因为改为8字节对齐将构成ABI更改,并且边际性能改进不值得麻烦。

正如其他人所说,缓存线很重要。实际存储器总线上的所有访问都是根据高速缓存行(x86上的64字节,IIRC)进行的。请参阅已经提到的“每个程序员需要了解的内存”文档。所以实际的内存流量是64字节对齐的。

1

您引用的64位总线馈送高速缓存。作为一个CPU,总是读写整个缓存行。高速缓存行的大小始终是8的倍数,并且其物理地址确实与8字节偏移对齐。

Cache-to-register传输不使用外部数据总线,因此该总线的宽度是不相关的。