【问题标题】:Profiling a partially evaluated program剖析部分评估的程序
【发布时间】:2015-01-15 00:39:45
【问题描述】:

为了对部分评估的程序进行概要分析,我有兴趣了解终止 GHC 程序的最佳方法。这对于分析需要很长时间才能运行的程序很有用,可能会一直运行。

使用 GHC 7.4.2,我能够通过启用分析 (-prof -auto-all) 并使用 +RTS -p 运行我的程序来 profile a non-terminating program。这会生成增量分析数据。该程序可以用^c 终止,并且.prof 文件将包含数据。在 GHC 7.6 及更高版本中,if 似乎可以使用单个 ^c 终止程序,然后将分析信息写入输出。但是(特别是对于较新版本的 GHC?)单个 ^c 不会杀死程序,至少在我不耐烦并再次点击 ^c 之前不会。通常两个 ^c 会终止程序,但不会将分析数据写入输出。

具体来说,考虑尝试剖析 StupidFib.hs 的问题:

fib n = fib (n - 1) + fib (n - 2)
main = print $ fib 100

使用 -prof 编译并使用 +RTS -p 运行,我可以在执行的前大约 10 秒内用 single ^c 杀死这个程序,但之后只有两个 ^c 可以工作。查看我的资源,此更改似乎与使用我所有物理内存并移动到交换空间的程序相吻合,但这可能是巧合。

为什么 ^c 有时对同一个程序有效,但有时却无效?确保在程序不会自行终止时打印分析数据的最简单方法是什么?

【问题讨论】:

  • 你是发送一次还是两次^C?
  • 通常我必须发送两次......一次似乎不会杀死程序。
  • 不管 GHC 版本如何,我一直发现如果我可以用一个 ^C 关闭它,它会写入分析数据,如果它需要两个,它不会。我不确定是否有办法解决这个问题。
  • 我认为如何杀死程序并不重要,当它仍在运行时,您实际上可以看到数据。目前我面前没有 7.4.2,但 iirc 就是这样工作的。
  • 嗯,这是我写的一个例子,它似乎以这种方式运行(我在自己的程序中也看到过这种情况)。它只是快速吃掉内存,所以用一个 ^C 杀死它是合理的,但它需要足够长的时间,你也可以使用两个 ^C。如果我启用分析,它会通过按一次 ^C 生成分析数据,但它会通过按两次 ^C 生成一个空白文件:lpaste.net/114466。我正在使用 GHC 7.8.3。我猜当 RTS 探查器收到 SIGINT 时,它会将其缓冲区写入文件并清理所有内容。我不确定第二次按下究竟会发生什么。

标签: haskell profiling ghc


【解决方案1】:

最有可能的是,第二个信号在程序完成处理第一个信号之前被传递,此时信号的动作已被重置为默认动作,即(对于 SIGINT)是终止程序。由于交换,在分析代码可以写出分析数据之前有很长的时间间隔,在此期间程序容易受到第二个 SIGINT 的攻击。

故事的寓意:要有耐心。如果您等待的时间足够长,程序将完成并写出数据。关于第二个 ^C,告诉自己,“不要这样做!” :-)

有人可能会争辩说,Haskell 运行时应该设置信号选项,以便忽略第二个 SIGINT,但这将是有风险的,因为如果在尝试处理信号时事情真的搞砸了,就没有简单的方法来终止程序.

您可能还希望避免超出物理内存并导致大量交换的程序。那时,您的计算实际上已停止,继续下去没有多大意义。使用+RTS -M 限制堆大小以避免陷入这种情况。

【讨论】:

    猜你喜欢
    • 2010-10-03
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    相关资源
    最近更新 更多