环路地址对齐如何影响Intel x86_64的速度?

时间:2010-12-25 22:40:26

标签: c++ optimization gcc intel x86-64

我看到相同C ++代码的性能降低15%,这些代码编译为完全相同的机器指令但位于不同对齐的地址上。当我的微小主循环从0x415220开始时,它比在0x415250时更快。我在Intel Core2 Duo上运行它。我在x86_64 Ubuntu上使用gcc 4.4.5。

任何人都可以解释减速原因以及如何强制gcc最佳地对齐循环吗?

以下是具有探查器注释的两种情况的反汇编:

  415220 576      12.56% |XXXXXXXXXXXXXX       48 c1 eb 08           shr    $0x8,%rbx
  415224 110       2.40% |XX                   0f b6 c3              movzbl %bl,%eax
  415227           0.00% |                     41 0f b6 04 00        movzbl (%r8,%rax,1),%eax
  41522c 40        0.87% |                     48 8b 04 c1           mov    (%rcx,%rax,8),%rax
  415230 806      17.58% |XXXXXXXXXXXXXXXXXXX  4c 63 f8              movslq %eax,%r15
  415233 186       4.06% |XXXX                 48 c1 e8 20           shr    $0x20,%rax
  415237 102       2.22% |XX                   4c 01 f9              add    %r15,%rcx
  41523a 414       9.03% |XXXXXXXXXX           a8 0f                 test   $0xf,%al
  41523c 680      14.83% |XXXXXXXXXXXXXXXX     74 45                 je     415283 ::Run(char const*, char const*)+0x4b3>
  41523e           0.00% |                     41 89 c7              mov    %eax,%r15d
  415241           0.00% |                     41 83 e7 01           and    $0x1,%r15d
  415245           0.00% |                     41 83 ff 01           cmp    $0x1,%r15d
  415249           0.00% |                     41 89 c7              mov    %eax,%r15d
  415250 679      13.05% |XXXXXXXXXXXXXXXX     48 c1 eb 08           shr    $0x8,%rbx
  415254 124       2.38% |XX                   0f b6 c3              movzbl %bl,%eax
  415257           0.00% |                     41 0f b6 04 00        movzbl (%r8,%rax,1),%eax
  41525c 43        0.83% |X                    48 8b 04 c1           mov    (%rcx,%rax,8),%rax
  415260 828      15.91% |XXXXXXXXXXXXXXXXXXX  4c 63 f8              movslq %eax,%r15
  415263 388       7.46% |XXXXXXXXX            48 c1 e8 20           shr    $0x20,%rax
  415267 141       2.71% |XXX                  4c 01 f9              add    %r15,%rcx
  41526a 634      12.18% |XXXXXXXXXXXXXXX      a8 0f                 test   $0xf,%al
  41526c 749      14.39% |XXXXXXXXXXXXXXXXXX   74 45                 je     4152b3 ::Run(char const*, char const*)+0x4c3>
  41526e           0.00% |                     41 89 c7              mov    %eax,%r15d
  415271           0.00% |                     41 83 e7 01           and    $0x1,%r15d
  415275           0.00% |                     41 83 ff 01           cmp    $0x1,%r15d
  415279           0.00% |                     41 89 c7              mov    %eax,%r15d

2 个答案:

答案 0 :(得分:4)

Gcc有一个 -falign-loops = n 选项,其中 n 要跳过的最大字节数,如果省略,则默认设置为使用。 Gcc在 -O2 -O3 优化级别自动启用此功能。

答案 1 :(得分:2)

在具有循环流检测的英特尔CPU上,循环体代码对齐可以提高效率,尤其是在正常的展开水平下。 首次从顶部进入循环时,对齐会受到惩罚。 你没有在那里显示代码,在对齐的案例中会有一些荒谬的美化无操作指令。 gcc通常使用条件对齐,仅在需要有限数量的填充的情况下才应用对齐。当我查看一次时,影响这种行为的选项看起来并不是很有效。正如亚历山大所说,为-march或-mtune设置一个值非常重要,这样gcc就可以使用相关的对齐设置。 我使用的所有编译器都无法在某些情况下对齐循环体,并且似乎无法控制它。