簡體   English   中英

Haskell性能:反轉計數算法

[英]Haskell performance : Inversion count algorithm

我決定使用Haskell從Standford算法課程https://class.coursera.org/algo-005解決第一個編程任務。 盡管我對語言很陌生,但我實現它的速度比c ++快得多。 我有6年以上的c ++工作經驗,所以給我留下了深刻的印象。 但性能令人失望:0.19秒(c ++)vs 9.88(haskell)版本。 如何提高Haskell實現的性能,使其可以與c ++相媲美?

這是我在Haskell中的代碼

data SortedList = SortedList {
    inversionCount :: Int,
    list :: [Int]
} deriving (Show) 

--      first   list        accumulator
packm :: Int -> SortedList -> Int -> SortedList
packm x (SortedList count xs) add =  SortedList (count + add) (x:xs)

merge2 :: [Int] -> [Int] -> SortedList
merge2 [] xs = SortedList 0 xs
merge2 xs [] = SortedList 0 xs
merge2 xlist@(x:xs) ylist@(y:ys)
    | x < y = packm x (merge2 xs ylist) 0
    | otherwise = packm y (merge2 xlist ys) $ length xlist

countAndMerge :: SortedList -> SortedList -> SortedList
countAndMerge (SortedList lcount lxs) (SortedList rcount rxs) =
    let merged = merge2 lxs rxs
    in SortedList (lcount + rcount + inversionCount merged) $ list merged

mergesort :: [Int] -> SortedList
mergesort [] = SortedList 0 []
mergesort [x] = SortedList 0 [x]
mergesort xs =
    let leftsorted = mergesort $ take halfElements xs
        rightsorted = mergesort $ drop halfElements xs
    in countAndMerge leftsorted rightsorted
    where halfElements = length xs `div` 2

main = do 
    contents <- getContents
    let intlist = [ read x :: Int | x <- (lines contents) ]
    print $ inversionCount $ mergesort intlist

最大的問題是漸近的表現是不正確的; 它是O(n ^ 2 * log n)而不是最優O(n * log n)。 罪魁禍首是merge2

    | otherwise = packm y (merge2 xlist ys) $ length xlist

length xlist是O(n)。 假設一個隨機輸入列表,我們需要在大約一半merge2調用上計算length xlist ,從而使一個級別的合並O(n ^ 2)。

otherwise = packm y (merge2 xlist ys) $ length xlist

這會平均計算合並的每個其他步驟的長度。 這使得整個業務呈二次方式。

如果您不通過計算元素來跟蹤列表的長度,而是通過從頂層向下傳遞計數,則可以恢復O(N log N)行為。 對於100000個元素的列表,這意味着執行時間從20秒減少到0.45秒(在我的機器上使用-O2)。

在不改變算法的情況下進一步擴展它是有問題的,因為它目前在線性堆棧空間中運行,並且無法使用默認RTS選項處理100萬個元素。 將mergesort更改為合並 - 鄰接對版本,它可能運行得更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM