我已經開始通過嘗試解決一些小問題來潛入Haskell。Haskell:代碼的兩個版本之間的速度差
我於「標準哈斯克爾友好」解決方案,我「極醜和Haskell不友好」版本之間有很大的性能差異(〜100-200x)絆倒了。
我敢肯定,對於同性戀者來說,這種表現上的差異有一個很好的理由,我錯過了,可以教我關於這個話題。
問題:查找數字串
內的最高5位數字都用在解決相同概念:產生所有5位數字,並找出最大。
優雅和快速的代碼
digit5 :: String -> Int
digit5 = maximum . map (read . take 5) . init . tails
長得醜,而且速度很慢的代碼(一旦字符串大小大)
digit5' :: String -> String -> String
-- xs - input string
-- maxim - current maximal value
digit5' xs maxim
| (length xs) < 5 = maxim
| y > maxim = digit5' (drop 1 xs) y -- use new detected maximum value
| otherwise = digit5' (drop 1 xs) maxim
where y = take 5 xs
digit5 :: String -> Int
digit5 xs
-- return the original string if the input size is smaller than 6
| length (xs) < 6 = read xs
| otherwise = read $ digit5' xs "00000"
對於小的投入,我得到大致相同的執行時間,對於大的投入我開始看到很大的差異(對於44550個元素的輸入):
Computation time for ugly version: 2.047 sec
Computation time for nice version: 0.062 sec
我的膚淺對此的瞭解是,快速代碼是使用預先提供的高階功能。對於較慢的版本遞歸使用,但我認爲咬尾應該是可能的。但在天真的水平,對我來說似乎都做同樣的事情。
而較慢的功能確實比較對字符串,而不是將它們轉換爲數字,我也試着轉換字符串整數,但沒有任何大的改善
我試着使用GHC不帶任何標誌,並與編譯下面的命令:
ghc
ghc -O2
ghc -O2 -fexcess-precision -optc-O3 -optc-ffast-math -no-
recomp
stack runhaskell
ghc -O3
對於重複性我加入的鏈接代碼contaning也測試向量的緣故:https://pastebin.com/kuS5iKgd
您有遞歸地在一個列表,並調用函數'length'在每一次迭代。長度是O(n)。您不小心向運行時添加了O(n^2)項。 – Carl
只是跳過警衛'|長度爲xs <5 = maxim'爲額外的模式'digit5'[] maxim = maxim'給我0.004秒而不是1.7秒。這比優雅的解決方案還要快。 (讀取總是會消耗部分字符串的5個字節,而字符串比較可能只需要比較第一個字符)。 – Krom