2013-06-11 26 views
7

Tôi có một chức năng Haskell tôi muốn đánh giá với kết quả trung gian chính xác:parBuffer đánh giá không cho tăng tốc dự kiến ​​

f 0 x = 0 
f n x = let tmp = f (n-1) x in 
     tmp + (x-tmp^2)/2 

Do (^ 2) mức độ phức tạp tăng lên theo cấp số nhân trong n. Vì tôi muốn làm một âm mưu và các tính toán cho hai x khác nhau là hoàn toàn độc lập, tôi đã có thể mong đợi gần như tối ưu tốc độ từ đánh giá song song. Mã của tôi cho điều này:

import Data.Ratio 
import Control.Parallel.Strategies 

f 0 x = 0 
f n x = let tmp = f (n-1) x in 
     tmp + (x-tmp^2)/2 

main = do 
     it <- readLn 
     let fn = fromRational . f it 
      values = map fn [0,1%2..10] :: [Double] 
      computed = values `using` parBuffer 16 rseq 
     mapM_ (putStrLn . show) computed 

Nhưng tôi ngạc nhiên điều này không thực sự mở rộng (trên i3 lõi kép của tôi với HT):

$ ghc -threaded -O f.hs 
[1 of 1] Compiling Main    (f.hs, f.o) 
Linking f ... 
$ time echo 20 | (./f +RTS -N1 > /dev/null) 

real 0m4.760s 
user 0m4.736s 
sys  0m0.016s 
$ time echo 20 | (./f +RTS -N2 > /dev/null) 

real 0m4.041s 
user 0m5.416s 
sys  0m2.548s 
$ time echo 20 | (./f +RTS -N3 > /dev/null) 

real 0m4.884s 
user 0m10.936s 
sys  0m3.464s 
$ time echo 20 | (./f +RTS -N4 > /dev/null) 

real 0m5.536s 
user 0m17.028s 
sys  0m3.888s 

Tôi đang làm gì sai ở đây? Có vẻ như nó dành khá nhiều thời gian trong khóa (sys?) Thay vì làm công việc hữu ích.

+0

Có vẻ như bạn cần 'parList' rồi' parBuffer' – Ankur

Trả lời

6

Tôi nghĩ rằng khi thời gian chạy tổng thể là tương đối nhỏ, bạn đang phải chịu rất nhiều từ việc thay đổi kích thước ban đầu của đống trong bộ sưu tập rác. Bạn có thể thử làm cho vùng phân bổ ban đầu lớn hơn bằng cách đi qua +RTS -A100M.

+0

Cảm ơn bạn, tăng tốc với chuỗi <= cores giờ đây là hoàn hảo và vẫn ổn định cho nhiều chuỗi hơn. – Tobias

+0

Ngoài ra, hãy xem xét sử dụng Threadscope để xem những gì đang xảy ra trên mỗi lõi của bạn. –