Performance 改进treap实现

Performance 改进treap实现,performance,optimization,data-structures,haskell,garbage-collection,Performance,Optimization,Data Structures,Haskell,Garbage Collection,下面是我对一种treap的实现(使用隐式键和一些存储在节点中的附加信息): 根据分析数据,此程序GC占用80%的时间。据我所知,这是因为每次“修改”节点时,都会重新创建根路径上的每个节点 我可以在这里做些什么来提高性能,还是我必须进入圣莫纳德的领域?使用GHC 7.0.3,我可以重现您的重GC行为: $ time ./A +RTS -s %GC time 92.9% (92.9% elapsed) ./A +RTS -s 7.24s user 0.04s system

下面是我对一种treap的实现(使用隐式键和一些存储在节点中的附加信息):

根据分析数据,此程序GC占用80%的时间。据我所知,这是因为每次“修改”节点时,都会重新创建根路径上的每个节点


我可以在这里做些什么来提高性能,还是我必须进入圣莫纳德的领域?

使用GHC 7.0.3,我可以重现您的重GC行为:

  $ time ./A +RTS -s
  %GC time      92.9%  (92.9% elapsed)
  ./A +RTS -s  7.24s user 0.04s system 99% cpu 7.301 total
我花了10分钟看完这个节目。以下是我所做的,为了:

  • 设置GHC的-H标志,增加GC中的限制
  • 开箱检查
  • 改进内联
  • 调整第一代分配区域
导致10倍的加速,GC大约45%的时间


因此,使用GHC的magic
-H
标志,我们可以大大减少运行时间:

  $ time ./A +RTS -s -H
  %GC time      74.3%  (75.3% elapsed)
  ./A +RTS -s -H  2.34s user 0.04s system 99% cpu 2.392 total
不错

节点上的UNPACK pragma不会做任何事情,因此请删除它们

内联
update
减少了更多的运行时间:

 ./A +RTS -s -H  1.84s user 0.04s system 99% cpu 1.883 total
内联
height

 ./A +RTS -s -H  1.74s user 0.03s system 99% cpu 1.777 total
所以,虽然它很快,但GC仍然占主导地位——毕竟我们正在测试分配。 我们可以做的一件事是增加第一代的规模:

 $ time ./A +RTS -s -A200M
 %GC time      45.1%  (40.5% elapsed)
 ./A +RTS -s -A200M  0.71s user 0.16s system 99% cpu 0.872 total
正如约翰尔所建议的,增加展开阈值有一点帮助

 ./A +RTS -s -A100M  0.74s user 0.09s system 99% cpu 0.826 total
比我们开始的速度快10倍?不错


使用,您可以将运行时视为
-a
-H
的函数

有趣的是,最佳运行时间使用非常大的
-A
值,例如

$ time ./A +RTS -A500M   
./A +RTS -A500M  0.49s user 0.28s system 99% cpu 0.776s

@adamax:这种行为(从根开始重新创建一切)在不可变结构中很常见,你读过Chris Okasaki的纯函数数据结构吗?他就此写了几篇论文。也许你应该通过使用
+RTS-s-RTS
运行你的程序来验证这一点,因为我看不到你在使用7.0.1快速运行程序时提到的80%,我看到大约16%的时间花在GC上。@ScottWest:我用ghc-O2-prof编译它,用make test.hs运行。/test+RTS-s-RTS,它说%GC时间77.4%(77.4%已过去),总时间是8.7秒。但我的ghc版本是6.12.1。只是出于兴趣,您的系统的总时间是多少?@adamax,我的结果与您大致相同。对于ghc-7.0.1和-O2,运行时间是8.027s,生产率是16.8%。如果我使用-O2-funfolding use threshold=256编译,运行时间是3.863s,生产率是24.9%。我尝试了很少有其他选项和内联功能,但这是迄今为止我拥有的最好的。别忘了GHC的垃圾收集选项:哇,这太不可思议了!我在GHC 6.12.1中也有类似的行为,内联
update
和设置第一代大小是最大的加速。有一个问题,你忘了包括
size
optio吗n代表-H?只是-H似乎没有任何作用,而-H64m则起作用。对于GHC 7,-H更精确地增加了GCC的所有限制,-H是一种“自动-a”,它会增加-A设置,但不会增加总体内存使用。这是可能的,因为我们正在复制GC,因此在主要GC之间有大量内存未使用。增加-A并不总是一个好主意-在某些程序中,由于缓存未命中的增加,它会使事情变得更糟。