字对齐加载比x64处理器上的未对齐加载更快吗?

在x86 / 64(Intel / AMD 64位)处理器上,在字边界上对齐的变量是否比未对齐的加载操作更快?

我的一位同事辩称,未对齐的载荷很慢,应该避免。 他引用了项目填充到结构中的单词边界,作为未对齐加载缓慢的证据。 例:

struct A { char a; uint64_t b; }; 

结构A通常大小为16个字节。

另一方面, Snappy压缩器的文档指出Snappy认为“未对齐的32位和64位负载和存储很便宜”。 根据源代码,英特尔32和64位处理器也是如此。

那么:这里的真相是什么? 如果和未对齐的负载有多少? 在哪种情况下?

互联网上随机的人我发现,486表示对齐的32位访问需要一个周期。 跨越四边形但位于同一缓存线内的未对齐32位访问需要四个周期。 跨越多个高速缓存行的未对齐等可能需要额外的六到十二个周期。

鉴于未对齐的访问需要访问多个内存,几乎按照定义,我对此并不感到惊讶。 我认为现代处理器上更好的缓存性能会使成本变得不那么糟糕,但仍然需要避免。

(顺便提一下,如果你的代码对可移植性有任何影响 …… ia32和后代几乎是唯一支持未对齐访问的现代架构。例如,ARM可以在抛出exception,模拟软件访问之间,或者只是加载错误的值 ,取决于操作系统!)

更新:这是一个真正去过并测量它的人 。 在他的硬件上,他认为未对齐的访问速度是对齐的一半。 去试试吧…

对齐的负载存储速度更快, 英特尔优化手册的两个摘录清楚地指出了这一点:

3.6优化内存访问

对齐数据,注意数据布局和堆栈对齐

对齐和转发问题是基于英特尔NetBurst微体系结构的处理器上最常见的大延迟源。

3.6.4对齐

数据的对齐涉及各种变量:

•动态分配变量

•数据结构的成员

•全局或局部变量

•参数在堆栈上传递

未对齐的数据访问可能会导致严重的性能损失。 对于缓存行拆分尤其如此。

在3.6.4中的那一部分之后,编译器开发人员有一个很好的规则:

汇编/编译器编码规则45.(H影响,H一般性)对齐自然操作数大小地址边界的数据。 如果使用向量指令加载和存储访问数据,请将数据对齐16字节边界。

然后列出对齐规则和3.6.6中的另一个gem

用户/源编码规则6.(H impact,M generality)在源代码中定义的填充数据结构,以便每个数据元素与自然操作数大小地址边界对齐。

这两个规则都标记为影响,这意味着它们可以极大地改变性能,连同摘录,第3.6节的其余部分充满了自然对齐数据的其他原因。 如果只是为了了解他/她正在使用的硬件,那么开发人员有时间阅读这些手册是非常值得的。

不应使用未对齐的加载/存储,但原因不是性能。 原因是C语言禁止它们(通过对齐规则和别名规则),并且它们不能在没有极慢的仿真代码的情况下在许多系统上工作 – 代码也可能破坏正确行为所需的C11内存模型multithreading代码,除非它是在纯字节级别上完成的。

至于x86和x86_64,对于大多数操作(某些SSE指令除外),允许未对齐的加载和存储,但这并不意味着它们与正确访问一样快。 它只是意味着CPU为您进行仿真,并且比您自己做的更有效率。 作为一个例子,一个memcpy类型的循环正在进行未对齐的字大小读取和写入将比执行对齐访问的相同memcpy慢一些,但它也会比编写自己的逐字节复制循环更快。

为了修复未对齐的读取,处理器需要执行两次对齐读取并修复结果。 这比必须进行一次读取和没有修复更慢。

Snappy代码具有利用未对齐访问的特殊原因。 它适用于x86_64; 它不适用于无法选择未对齐访问的体系结构,并且在修复未对齐访问是系统调用或类似的昂贵操作时,它将工作缓慢。 (在DEC Alpha上,有一种机制大致相当于修复未对齐访问的系统调用,你必须为你的程序打开它。)

使用未对齐访问是Snappy的作者做出的明智决定。 对每个人来说,模仿它并不合理。 例如,如果编译器默认使用它们,那么编译器编写器会因其代码性能不佳而受到谴责。

未对齐的32位和64位访问并不便宜。

我做了测试来validation这一点。 我在Core i5 M460(64位)上的结果如下:最快的整数类型是32位宽。 64位对齐稍慢但几乎相同。 16位对齐和8位对齐都明显慢于32位和64位对齐。 16位慢于8位对齐。 迄今为止最慢的访问forms是非对齐32位访问,比对齐的32位访问(最快的)慢3.5倍,未对齐的32位访问甚至比未对齐的64位访问慢40%。

结果: https : //github.com/mkschreder/align-test/blob/master/results-i5-64bit.jpg?raw = true源代码: https : //github.com/mkschreder/align-test