如果我在同一個模塊中使用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