2016-03-28 18 views
13

Tôi cố gắng chạy ví dụ đầu tiên ở đây: http://chimera.labs.oreilly.com/books/1230000000929/ch03.htmlGC thường xuyên ngăn chặn tia lửa chạy song song

Code: https://github.com/simonmar/parconc-examples/blob/master/strat.hs

import Control.Parallel 
import Control.Parallel.Strategies (rpar, Strategy, using) 
import Text.Printf 
import System.Environment 

-- <<fib 
fib :: Integer -> Integer 
fib 0 = 1 
fib 1 = 1 
fib n = fib (n-1) + fib (n-2) 
-- >> 

main = print pair 
where 
    pair = 
-- <<pair 
    (fib 35, fib 36) `using` parPair 
-- >> 

-- <<parPair 
parPair :: Strategy (a,b) 
parPair (a,b) = do 
    a' <- rpar a 
    b' <- rpar b 
    return (a',b') 
-- >> 

tôi đã xây dựng sử dụng GHC 7.10.2 (trên OSX, với một đa lõi máy) bằng cách sử dụng lệnh sau:

ghc -O2 strat.hs -threaded -rtsopts -eventlog 

Và chạy sử dụng:

./strat +RTS -N2 -l -s 

tôi mong đợi 2 fibs tính toán được chạy song song (ví dụ chương trước đã làm việc như mong đợi, vì vậy không có vấn đề thiết lập), và tôi đã không nhận được bất kỳ sự tăng tốc ở tất cả, như đã thấy ở đây:

% ./strat +RTS -N2 -l -s 
(14930352,24157817) 
    3,127,178,800 bytes allocated in the heap 
     6,323,360 bytes copied during GC 
      70,000 bytes maximum residency (2 sample(s)) 
      31,576 bytes maximum slop 
       2 MB total memory in use (0 MB lost due to fragmentation) 

            Tot time (elapsed) Avg pause Max pause 
    Gen 0  5963 colls, 5963 par 0.179s 0.074s  0.0000s 0.0001s 
    Gen 1   2 colls,  1 par 0.000s 0.000s  0.0001s 0.0001s 

    Parallel GC work balance: 2.34% (serial 0%, perfect 100%) 

    TASKS: 6 (1 bound, 5 peak workers (5 total), using -N2) 

    SPARKS: 2 (0 converted, 0 overflowed, 0 dud, 1 GC'd, 1 fizzled) 

    INIT time 0.000s ( 0.001s elapsed) 
    MUT  time 1.809s ( 1.870s elapsed) 
    GC  time 0.180s ( 0.074s elapsed) 
    EXIT time 0.000s ( 0.000s elapsed) 
    Total time 1.991s ( 1.945s elapsed) 

    Alloc rate 1,728,514,772 bytes per MUT second 

    Productivity 91.0% of total user, 93.1% of total elapsed 

gc_alloc_block_sync: 238 
whitehole_spin: 0 
gen[0].sync: 0 
gen[1].sync: 0 

-N1 nhận các kết quả tương tự (bỏ qua).

# bộ sưu tập GC có vẻ đáng ngờ, như được chỉ ra bởi những người khác trong # người mới bắt đầu sử dụng haskell, vì vậy tôi đã thử thêm -A16M khi chạy. Kết quả trông giống như mong đợi hơn:

% ./strat +RTS -N2 -l -s -A16M 
(14930352,24157817) 
    3,127,179,920 bytes allocated in the heap 
     260,960 bytes copied during GC 
      69,984 bytes maximum residency (2 sample(s)) 
      28,320 bytes maximum slop 
       33 MB total memory in use (0 MB lost due to fragmentation) 

            Tot time (elapsed) Avg pause Max pause 
    Gen 0  115 colls, 115 par 0.105s 0.002s  0.0000s 0.0003s 
    Gen 1   2 colls,  1 par 0.000s 0.000s  0.0002s 0.0002s 

    Parallel GC work balance: 71.25% (serial 0%, perfect 100%) 

    TASKS: 6 (1 bound, 5 peak workers (5 total), using -N2) 

    SPARKS: 2 (1 converted, 0 overflowed, 0 dud, 0 GC'd, 1 fizzled) 

    INIT time 0.001s ( 0.001s elapsed) 
    MUT  time 1.579s ( 1.087s elapsed) 
    GC  time 0.106s ( 0.002s elapsed) 
    EXIT time 0.000s ( 0.000s elapsed) 
    Total time 1.686s ( 1.091s elapsed) 

    Alloc rate 1,980,993,138 bytes per MUT second 

    Productivity 93.7% of total user, 144.8% of total elapsed 

gc_alloc_block_sync: 27 
whitehole_spin: 0 
gen[0].sync: 0 
gen[1].sync: 0 

Câu hỏi đặt ra là: Tại sao hành vi này? Ngay cả với GC thường xuyên, tôi vẫn trực giác mong đợi 2 tia lửa chạy song song trong 90% thời gian chạy khác.

+2

Nếu bạn không nhận được câu trả lời thỏa mãn, hãy cân nhắc mở một vé trên ghc trac. Đặc biệt là xem xét ví dụ này là từ cuốn sách của Simon, tôi chắc chắn họ sẽ quan tâm đến việc biết về điều này nếu đó là một sự hồi quy. – jberryman

Trả lời

2

Có, đây thực sự là lỗi trong GHC 8.0.1 trở về trước (tôi đang làm việc để sửa lỗi cho 8.0.2). Vấn đề là các biểu thức fib 35fib 36 không đổi và do đó GHC nâng chúng lên cấp cao nhất là CAF và RTS giả định rằng các CAF không thể truy cập được và do đó thu gom rác từ các tia lửa.

Bạn có thể làm việc xung quanh nó bằng cách làm cho các biểu thức không liên tục bằng cách thông qua các thông số trên dòng lệnh:

main = do 
    [a,b] <- map read <$> getArgs 
    let pair = (fib a, fib b) `using` parPair 
    print pair 

và sau đó chạy chương trình với ./strat 35 36.

+1

Bạn có thể giải thích thêm một chút không? Tôi có một vấn đề tương tự với thuật toán 'mergeSort' của tôi, và tôi không thể tìm ra cách làm cho nó hoạt động. Ngoài ra tôi nên đề cập rằng mặc dù thực tế là 3 tia lửa fizzle ra khỏi 4, tôi vẫn thấy song song, và mã chạy nhanh hơn đáng kể là tốt. Bất kỳ manh mối nào tại sao? – Anabra

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