为什么C中的double是8字节对齐的?

为什么C中的double是8字节对齐的?,c,32bit-64bit,memory-alignment,C,32bit 64bit,Memory Alignment,我正在读一篇关于内存中数据类型对齐的文章(我无法理解一点,即 注意,一个双变量将在32的8字节边界上分配 位机器,需要两个内存读取周期。在64位机器上, 根据银行数量,将在8字节上分配双变量 边界,只需要一个内存读取周期 我的疑问是:为什么双变量需要分配在8字节边界上而不是4字节边界上?如果它分配在4字节边界上,我们仍然只需要2个内存读取周期(在32位机器上)。如果我错了,请纠正我 另外,如果有人有关于成员/内存对齐的好教程,请分享。参考这篇关于 内存周期的数量取决于硬件体系结构,硬件体系结构决

我正在读一篇关于内存中数据类型对齐的文章(我无法理解一点,即

注意,一个双变量将在32的8字节边界上分配 位机器,需要两个内存读取周期。在64位机器上, 根据银行数量,将在8字节上分配双变量 边界,只需要一个内存读取周期

我的疑问是:为什么双变量需要分配在8字节边界上而不是4字节边界上?如果它分配在4字节边界上,我们仍然只需要2个内存读取周期(在32位机器上)。如果我错了,请纠正我


另外,如果有人有关于成员/内存对齐的好教程,请分享。

参考这篇关于


内存周期的数量取决于硬件体系结构,硬件体系结构决定了您有多少个RAM组。如果您有32位体系结构和4个RAM组,则只需2个内存周期即可读取。(每个RAM组贡献1个字节)

在2^N的边界上对齐大小为2^N的数据值的原因是为了避免该值跨缓存线边界分割的可能性

x86-32处理器可以从任何字边界(8字节对齐与否)获取双精度最多读取两次32位内存。但如果该值跨缓存线边界分割,则由于需要从内存中提取第二条缓存线,因此提取第二个字的时间可能相当长。这会不必要地导致处理器性能低下。(实际上,当前的处理器一次不会从内存中获取32位;它们倾向于在更宽的总线上获取更大的值,以实现真正的高数据带宽;如果两个字位于同一缓存线中,并且已经缓存,则获取这两个字的实际时间可能只有1个时钟)

<> P>这种对齐方案的一个自由结果是这样的值也不跨越页面边界。这避免了在数据获取中间出现页面错误的可能性。


因此,出于性能原因,您应该在8字节边界上对齐双精度。编译器知道这一点,只需为您这样做。

在低于其大小的边界上对齐一个值会使其容易被拆分为两个缓存线。在将缓存线逐出到备份存储时,将该值拆分为两个缓存线意味着额外的工作(两条缓存线将被逐出;而不是一条),这是一个无用的内存总线负载。

双32位体系结构的8字节对齐不会减少内存读取,但它仍然可以在减少缓存访问方面提高系统性能。请阅读以下内容:

看看这个答案:它匹配缓存对齐,也匹配SSE指令要求。所有这一切都取决于硬件体系结构,而不是C。@m0skit0:如果一切都依赖于arch,那么为什么不同的编译器会有所不同…
双精度(8字节)在Windows上是8字节对齐的,在Linux上是4字节对齐的(8字节,带-malign双编译时选项).
…source@OliverCharlesworth:SSE没有需要8字节对齐的加载/存储。16字节加载/存储需要16字节对齐,或者任何较窄的操作数都不需要对齐。但是,将双字节8字节对齐对性能有好处,这样它们就不能跨缓存线拆分。(或跨越任何其他大于8字节的边界,用于关心缓存线内对齐的CPU)。不理解关于只需要一个内存周期的评论。首先,“双精度”通常意味着8字节浮点数,其次,32位体系结构通常意味着32位数据总线。无论您如何组织RAM,都不可能在一次操作中从32位管道中获取64位。存在类型错误。请重新措辞:具有4个RAM组的32位机器将在2个内存周期内访问8字节。问题是什么如果对齐在4字节边界,那么32位仍然需要2个周期system@Raman:您没有考虑从导致从主内存提取缓存线的位置读取第2个32位的成本。与“1个周期”相比,这样的提取需要数十纳秒需要0.2纳秒,所以它不仅仅是一个周期。这可能很少见,但如果发生这种情况,它的成本会很高。像P5 Pentium一样古老的CPU中的x87 FPU可以从缓存中一次加载64位。这就是为什么gcc选择在
-m32
的情况下提供
8字节对齐,但在i386 System V ABI可能强制将其设置为b的结构中除外在2012年,所有关于32位CPU无法获取整个双精度的说法都是无稽之谈;这只是整数寄存器宽度。这在历史上是正确的,也是ABI设计的原因。