如果我在同一个模块中使用Criterion
进行测量,那么我有一个非递归函数来计算似乎表现良好的最长公共子序列(ghc 7.6.1
,编译时使用-O2 -fllvm
标志)。另一方面,如果我将函数转换为模块,则只导出该函数(建议使用here),然后再用Criterion进行测量,我会得到〜2x的减速(如果将标准测试移回模块,则会消失在哪里定义函数)。我尝试用INLINE
编译指示标记函数,这对跨模块性能测量没有任何影响。GHC中的交叉模块优化
在我看来,GHC可能会做一个严格分析,当函数和主函数(从中可以访问函数)在同一个模块中时,它可以很好地工作,但当它们被分割时,不会。我很感激关于如何模块化函数的指针,以便在从其他模块调用时可以很好地执行。有问题的代码太大,无法粘贴 - 如果您想尝试一下,您可以看到它here。什么我试图做一个小例子下面是(与代码片段):
-- Function to find longest common subsequence given unboxed vectors a and b
-- It returns indices of LCS in a and b
lcs :: (U.Unbox a, Eq a) => Vector a -> Vector a -> (Vector Int,Vector Int)
lcs a b | (U.length a > U.length b) = lcsh b a True
| otherwise = lcsh a b False
-- This section below measures performance of lcs function - if I move it to
-- a different module, performance degrades ~2x - mean goes from ~1.25us to ~2.4us
-- on my test machine
{--
config :: Config
config = defaultConfig { cfgSamples = ljust 100 }
a = U.fromList ['a'..'j'] :: Vector Char
b = U.fromList ['a'..'k'] :: Vector Char
suite :: [Benchmark]
suite = [
bench "lcs 10" $ whnf (lcs a) b
]
main :: IO()
main = defaultMainWith config (return()) suite
--}
尝试使用INLINEABLE。它可能会更好。 – Carl
@Carl,尝试了它的lcs功能。还是一样。 – Sal
我怀疑问题是,当它全部在一个模块中时,GHC可以将类型变量'a'专用于'Char',因为它从来没有与任何其他类型一起使用,从而消除类型类的开销。您可以尝试使用'SPECIALIZE'编译指示器(或者只是手动将其更改为'Char'),看看它是否有效。 – hammar