c中的x64内联汇编以对齐说明

时间:2016-02-16 17:50:26

标签: c gcc alignment x86-64 inline-assembly

我有一个非常热的指令循环,需要在32字节边界上正确对齐,以最大限度地提高Intel's Instruction Fetcher的效率。

此问题特定于英特尔不太老的CPU系列(从Sandy Bridge开始)。如果未能正确对齐循环开始,则速度损失高达20%,这绝对太明显了。 这个问题非常罕见,需要一组高度优化的指令才能使指令获取器成为瓶颈。但幸运的是,这不是一个独特的案例。这是nice article explaining in details如何检测到这样的问题。

问题是,gcc还是clang会关心这个指令循环。它使得编译这个代码变成了一个产生随机结果的噩梦,这取决于热循环如何“好”地偶然排列。这也意味着修改完全不相关的函数可能会严重影响热循环的性能。

已经尝试了几个编译器标志,但没有一个能给出令人满意的结果。

[编辑] 尝试编译标志的更详细说明:

  • -falign-functions=32:没有影响或负面影响
  • -falign-jumps=32:没有影响
  • -falign-loops=32:当热循环被隔离成一小段测试代码时,工作正常。但是在正常构建中,编译标志应用于整个源代码,在这种情况下它是有害的:在32字节上对齐所有循环对性能不利。只有非常热门的人才能从中受益。
  • 还尝试在函数声明中使用__attribute__((optimize("align-loops=32")))。不会产生任何影响(生成相同的二进制文件,就好像声明不存在一样)。后来gcc支持小组确认有效忽略。 编辑:@Jester在评论中表明该语句适用于gcc 5+。不幸的是,我的开发站主要使用gcc 4.8.4,这更像是一个可移植性的问题,因为我不控制构建过程中使用的最终编译器。

只有使用PGO构建才能可靠地产生预期的性能,但PGO不能被接受为解决方案,因为这段代码将使用自己的构建链集成到其他程序中。

所以,我正在考虑内联汇编。 这将特定于x64指令集,因此不需要可移植性。

如果我的理解是正确的,像NASM这样的汇编允许使用诸如ALIGN 32之类的语句,这将强制下一条指令在32字节边界上对齐。

由于目标源代码在C中,因此需要包含此语句。例如,asm("ALIGN 32");之类的内容 (当然这不起作用)。

我希望这主要是知道正确的写作指令,而不是更深层次的东西,比如“这是不可能的”。

1 个答案:

答案 0 :(得分:5)

与NASM类似,GNU汇编程序支持.align伪OP进行对齐:

volatile asm (".align 32");

对于非汇编解决方案,您可以根据需要尝试提供-falign-loops=32-falign-functions=32-falign-jumps=32