go cmd/compile:重新组织关联计算以允许超标量执行

uemypmqf  于 4个月前  发布在  Go
关注(0)|答案(8)|浏览(59)

编译器目前将 a+b+c+d 编译为 a+(b+(c+d)) 。它应该使用 (a+b)+(c+d) ,因为后者可以乱序执行。
更广泛地说,我们应该平衡关联计算的树。
在md5block.go的第4轮中,使用针对单个计算类型的规则定制编译器,实现了15%的吞吐量提升。(详见下文。)
在我看来,是否可以通过精心设计的重写规则实现这一点,或者专用的优化是否更好,尚不清楚。但看起来在紧密的数学代码上可能有显著的性能优势。
我不打算进一步研究这个问题,但我真的希望有人能接手。
cc @randall77@martisch@FiloSottile@mmcloughlin@mdempsky
为了重现md5结果,请禁用优化的汇编程序,并添加以下重写规则:

(Add32 <t> c:(Const32) (Add32 d:(Load _ _) (Add32 x:(Xor32 _ _) a:(Add32 _ _)))) => (Add32 (Add32 <t> c d) (Add32 <t> x a))

并禁用此规则以避免无限循环:

(Add32 (Add32 i:(Const32 <t>) z) x) && (z.Op != OpConst32 && x.Op != OpConst32) => (Add32 i (Add32 <t> z x))
goucqfw6

goucqfw61#

a := float64(1<<53)
	b := float64(1)
	c := float64(1)
	d := float64(0)
	e := (a+(b+(c+d)))
	f := (a+b)+(c+d)

这对整数可能很好,因为我认为,在Go提供的保证下,加法在Go中是关联的,但对于浮点值,并非总是如此。

rta7y2nd

rta7y2nd2#

SSA后端针对不同的数据类型有不同的操作,以避免此类问题。(我们要感谢@dr2chase。)同样,这种优化也不适用于添加指针,因为中间结果可能是无效指针。

oipij1gg

oipij1gg3#

相关地,这种优化也不适用于添加指针,因为中间结果可能是无效的指针。请注意,将 (ptr + x1) + x2 重写为 ptr + (x1 + x2) 是安全的(据我所知),只是不能反过来。尽管如此,我对这种方法在实践中是否有用持怀疑态度。

hfsqlsce

hfsqlsce4#

https://go.dev/cl/493115提到了这个问题:cmd/compile: add reassociate pass to rebalance commutative operations

5cg8jx4n

5cg8jx4n5#

有趣的观点。据我所知,在其他编译器中的重新关联主要是为了协助其他优化(如sccp、gcse、loopopt)。似乎将重新关联用于“加速CPU超标量执行”是一种新的表达式,是否有相关的扩展信息/论文?也许这对其他编译器也有帮助。谢谢。

Java仅在循环中不变式参与计算时应用重新关联。GCC trunk does not 重新关联 a+b+c+d(a+b)+(c+d)Clang trunk 进行了重新关联。

uoifb46i

uoifb46i6#

是否有相关的扩展信息/论文?
@y1yang0 请参阅 https://www.agner.org/optimize/optimizing_assembly.pdf 的第9.5节(以及整章9)

mutmk8jj

mutmk8jj7#

是的,Clang通过LLVM中的Reassociate pass输出优化。

与LLVM的版本相比,这是一个非常简单的分析传递,其中一些LLVM传递已经被重写规则处理了,直到我在提交PR之后才知道这些规则的存在,所以我进一步简化了这个过程,以消除常量排序。

如果在进一步优化后再次运行此传递,它可能会有常量折叠机会,但在gcse之前完成更重要,因为它可以帮助将表达式很好地分组在一起。目前的目标只是加速无序执行,我会尽快处理这个优化带来的更多机会。

看起来Java只在循环内部进行重新关联优化的原因是自动向量化。这种类型的传递有助于整理所有依赖关系,使您可以轻松识别出4个连续的添加操作,如果模型决定这样做是经济有效的,它们可以转换为一些SIMD。

尽管如此,这个传递似乎在很多地方都有助于简化分析,所以我会研究其他编译器和LLVM,看看我们是否可以在Go中利用它。

58wvjzkj

58wvjzkj8#

https://go.dev/cl/496095提到了这个问题:cmd/compile: add ilp pass to help balance commutative expressions aiding in instruction level parallelism

相关问题