10

我正在尝试解决 Haskell 中的算法难题,为此我需要一个相当大的数据结构。然而,我提交解决方案的问题解决站点不使用任何运行时选项来允许更大的堆栈,但我听说我可以使用编译器选项作为编译指示。我尝试在我的代码中使用以下编译指示:

{-# OPTIONS_GHC -O2 -rtsopts -with-rtsopts=-K32m #-}

然后我用ghc --make algo.hs. 但是,当我在我的机器上运行一些大型测试时,程序会因堆栈溢出而崩溃,并报告当前堆栈大小为 8MB。另一方面,当我这样编译时:

ghc -rtsopts -with-rtsopts=-K32M --make algo.hs -fforce-recomp

该程序在相同的数据上运行良好,无需添加任何+RTS参数。我使用 GHC 7.0.2,但问题解决站点使用的是 6.12.3,所以最好我正在寻找也可以与旧版本一起使用的解决方案。

4

1 回答 1

10

请记住,几乎任何类型的原生二进制文件的编译都至少包含两个步骤:实际对象编译(.hs-> .o)和链接(.o、、.a- .lib> 可执行文件.exe///等.so.dll

当你用这个编译时:

ghc -rtsopts -with-rtsopts=-K32M --make algo.hs -fforce-recomp

...幕后实际发生的事情基本上是:

# object compilation - creates algo.o
ghc -c algo.hs -fforce-recomp
# linking - links together algo.o and libHSsomepackage.a into the "algo" binary
# (we assume that `algo.hs` included some module from the package `somepackage`
#  e.g. `Data.Package.Some`)
ghc -rtsopts -with-rtsopts=-K32M -o algo -package somepackage algo.o

即该--make选项告诉 GHC 在链接结果之前自动编译目标文件,它会为您填补大量空白。请注意各个命令行标志的最终位置。

当您在文件顶部指定该编译指示时,会发生这种情况(使用ghc --make algo.hs):

ghc -c algo.hs -rtsopts -with-rtsopts=-K32M
ghc -o algo -package somepackage algo.o

OPTIONS_GHCpragma 告诉编译器在将该特定模块编译为目标文件时要添加的选项。因为-rtsopts是一个链接器选项(它告诉 GHC 链接到一组不同的命令行处理内容),所以在编译目标文件时不能指定它。您必须在链接时指定它,并且不能在模块头中指定此类选项。

有两种解决方案:

  1. 使用Cabal为您构建东西并在您的.cabal文件中指定您想要的 GHC 选项
  2. 修复您的算法,以便您不需要太多的堆栈空间,例如通过使用尾递归和更严格的折叠。有关更多信息,请参阅wiki
于 2012-05-28T16:32:07.007 回答