【发布时间】:2015-05-19 07:35:40
【问题描述】:
_
你好,那里
my program to compute differences between files 的一部分使用标准 DP 算法来计算两个列表之间的最长公共非连续子序列。我在使用其中一些功能时遇到了性能问题,因此我运行 HPC 进行分析,发现以下结果:
individual inherited
COST CENTRE no. entries %time %alloc %time %alloc
(ommitted lines above)
longestCommonSubsequence 1 0.0 0.0 99.9 100.0
longestCommonSubsequence' 8855742 94.5 98.4 99.9 100.0
longestCommonSubsequence'' 8855742 4.2 0.8 5.4 1.6
longestCommonSubsequence''.caseY 3707851 0.6 0.6 0.6 0.6
longestCommonSubsequence''.caseX 3707851 0.6 0.2 0.6 0.2
(ommitted lines below)
这是有问题的代码:
longestCommonSubsequence' :: forall a. (Eq a) => [a] -> [a] -> Int -> Int -> [a]
longestCommonSubsequence' xs ys i j =
(Memo.memo2 Memo.integral Memo.integral (longestCommonSubsequence'' xs ys)) i j
longestCommonSubsequence'' :: forall a. (Eq a) => [a] -> [a] -> Int -> Int -> [a]
longestCommonSubsequence'' [] _ _ _ = []
longestCommonSubsequence'' _ [] _ _ = []
longestCommonSubsequence'' (x:xs) (y:ys) i j =
if x == y
then x : (longestCommonSubsequence' xs ys (i + 1) (j + 1)) -- WLOG
else if (length caseX) > (length caseY)
then caseX
else caseY
where
caseX :: [a]
caseX = longestCommonSubsequence' xs (y:ys) (i + 1) j
caseY :: [a]
caseY = longestCommonSubsequence' (x:xs) ys i (j + 1)
我发现值得注意的是,所有时间和内存使用都发生在 longestCommonSubsequence',memoizing 包装器中。因此,我得出的结论是,性能损失来自Data.Memocombinators 完成的所有查找和缓存,尽管在我使用它的许多其他时间里它的性能总是令人钦佩。
我想我的问题是……这个结论似乎是合理的;是吗?如果是这样,那么有人对实现 DP 的其他方法有任何建议吗?
作为参考,将两个 14 行长的文件与各自的内容 "a\nb\nc\n...m" 和 "*a\nb\nc\n...m*" 进行比较需要 12 秒 - 这太长了)。
提前致谢! :)
编辑:现在尝试ghc-core 的东西;如果我能让它与 Cabal 项目很好地配合并获得任何有用的信息,我会发布更新!
【问题讨论】:
-
你应该发现值得注意的数字是 8855742 和 3707851,这表明你的记忆根本不起作用。 madjar 的回答解释了原因。
标签: performance haskell profiling ghc memoization