2015-10-01 20 views
6

Tôi cố gắng để đẩy nhanh tiến độ các chức năng sau:Khả năng tăng tốc chức năng này là gì?

{-# LANGUAGE BangPatterns #-} 

import Data.Word 
import Data.Bits 
import Data.List (foldl1') 
import System.Random 
import qualified Data.List as L 

data Tree a = AB (Tree a) (Tree a) | A (Tree a) | B (Tree a) | C !a 
    deriving Show 

merge :: Tree a -> Tree a -> Tree a 
merge (C x) _    = C x 
merge _ (C y)    = C y 
merge (A ta) (A tb)   = A (merge ta tb) 
merge (A ta) (B tb)   = AB ta tb 
merge (A ta) (AB tb tc)  = AB (merge ta tb) tc 
merge (B ta) (A tb)   = AB tb ta 
merge (B ta) (B tb)   = B (merge ta tb) 
merge (B ta) (AB tb tc)  = AB tb (merge ta tc) 
merge (AB ta tb) (A tc)  = AB (merge ta tc) tb 
merge (AB ta tb) (B tc)  = AB ta (merge tb tc) 
merge (AB ta tb) (AB tc td) = AB (merge ta tc) (merge tb td) 

Để nhấn mạnh hiệu quả của nó, tôi đã thực hiện loại sử dụng merge:

fold ab a b c list = go list where 
    go (AB a' b') = ab (go a') (go b') 
    go (A a')  = a (go a') 
    go (B b')  = b (go b') 
    go (C x)  = c x 

mergeAll :: [Tree a] -> Tree a 
mergeAll = foldl1' merge 

foldrBits :: (Word32 -> t -> t) -> t -> Word32 -> t 
foldrBits cons nil word = go 32 word nil where 
    go 0 w !r = r 
    go l w !r = go (l-1) (shiftR w 1) (cons (w.&.1) r) 

word32ToTree :: Word32 -> Tree Word32 
word32ToTree w = foldrBits cons (C w) w where 
    cons 0 t = A t 
    cons 1 t = B t 

toList = fold (++) id id (\ a -> [a]) 

sort = toList . mergeAll . map word32ToTree 

main = do 
    is <- mapM (const randomIO :: a -> IO Word32) [0..500000] 
    print $ sum $ sort is 

Việc thực hiện đã đưa ra khá tốt từ đường đi , chậm hơn khoảng 2,5x so với sort của Data.List. Không có gì mà tôi đã tăng tốc thêm nữa, mặc dù: nhấn mạnh một số chức năng, ghi chú bằng giọng nói ở nhiều nơi, UNPACK trên C !a. Có cách nào để tăng tốc độ chức năng này không?

+0

Bạn có bao gồm chi phí 'map word32ToTree' trong chi phí' sắp xếp' không? Làm thế nào nhanh chóng là 'mergeAll' nếu bạn buộc' bản đồ word32ToTree' đầu tiên? Làm thế nào nhanh là nó nếu bạn buộc kết quả với một cái gì đó khác hơn là 'toList'? – Cirdec

+0

Tôi không biết về tốc độ, nhưng như một vấn đề về phong cách, bạn có thể thực hiện các typeclass "Có thể gập lại" để bạn có thể gọi chức năng cơ bản mà không cần chuyển đổi thành danh sách – Bruno

+0

@Cirdec Tôi đã không nghĩ về bất kỳ điều đó. – MaiaVictor

Trả lời

8

Bạn chắc chắn có quá nhiều lượt được phân bổ. Tôi sẽ chỉ cách phân tích mã:

merge (A ta) (A tb)   = A (merge ta tb) 

Ở đây bạn phân bổ hàm tạo A với một đối số, đó là một đoạn. Bạn có thể nói khi đoạn merge ta tb bị ép buộc không? Có lẽ chỉ ở cuối cùng, khi cây kết quả được sử dụng. Cố gắng thêm một tiếng nổ cho mỗi đối số của mỗi Tree constructor để đảm bảo nó là cột sống-nghiêm ngặt:

data Tree a = AB !(Tree a) !(Tree a) | A !(Tree a) | B !(Tree a) | C !a 

Ví dụ tiếp theo:

go l w !r = go (l-1) (shiftR w 1) (cons (w.&.1) r) 

Ở đây bạn được phân bổ một thunk cho l-1, shifrR w 1cons (w.&.1) r . Người đầu tiên sẽ bị buộc phải lặp lại lần tiếp theo khi so sánh l với o, lần thứ hai sẽ bị buộc khi buộc đoạn thứ ba trong lần lặp tiếp theo (w được sử dụng tại đây) và đoạn thứ ba bị buộc phải lặp lại tiếp theo vì một tiếng nổ trên r. Vì vậy, có lẽ điều khoản cụ thể này là OK.

+0

Tốt. Thêm chú thích bang trên cột sống của cây cải thiện hiệu suất gần gấp hai lần. Tôi đã được nói trước khi các quy tắc của ngón tay cái là nghiêm ngặt trên lá, lười biếng trên cột sống. Bất kỳ lý do trường hợp cụ thể này không tuân theo quy tắc? – MaiaVictor

+2

@Viclib Tôi không biết bất kỳ nghiên cứu chính thức nào về cột sống nghiêm ngặt so với cấu trúc cột sống lười biếng. Nhưng tôi nghĩ rằng nó phụ thuộc chủ yếu vào mô hình sử dụng. Thay vì làm cho cột sống nghiêm ngặt, bạn có thể sửa 'merge' để buộc cột sống. – Yuras

+0

@Viclib Ở góc nhìn thứ hai, bạn có thể tăng hiệu suất từ ​​cây lười cột sống. Ví dụ. thay vì tạo 500000 cây trước khi hợp nhất chúng, bạn có thể tạo kết quả chỉ bắt buộc các phần cần thiết của cây. Bằng cách đó bạn có thể phân bổ thời gian sống ngắn. Nhưng điều đó đòi hỏi thiết kế cẩn thận về 'sắp xếp'. – Yuras

Các vấn đề liên quan