2012-11-12 35 views
6

Tôi tình cờ gặp sự cố với Eval đơn lẻ và rparStrategy trong Haskell. Hãy xem xét đoạn mã sau:Làm thế nào để đánh giá tuple song song bằng cách sử dụng chiến lược rpar trong Haskell?

module Main where 

import Control.Parallel.Strategies 

main :: IO() 
main = print . sum . inParallel2 $ [1..10000] 

inParallel :: [Double] -> [Double] 
inParallel xss = runEval . go $ xss 
    where 
     go [] = return [] 
     go (x:xs) = do 
     x' <- rpar $ x + 1 
     xs' <- go xs 
     return (x':xs') 

inParallel2 :: [Double] -> [Double] 
inParallel2 xss = runEval . go $ xss 
    where 
     go [] = return [] 
     go [x] = return $ [x + 1] 
     go (x:y:xs) = do 
     (x',y') <- rpar $ (x + 1, y + 1) 
     xs'  <- go xs 
     return (x':y':xs' 

tôi biên dịch và chạy nó như thế này:

ghc -O2 -Wall -threaded -rtsopts -fforce-recomp -eventlog eval.hs 
./eval +RTS -N3 -ls -s 

Khi tôi sử dụng inParallel chức năng xử lý song song hoạt động như mong đợi. Trong thống kê thời gian chạy ra tôi thấy:

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

Khi tôi chuyển sang inParallel2 chức năng xử lý song song tất cả đã biến mất:

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

Tại sao không đánh giá các bộ làm việc tại song song? Tôi đã thử buộc bộ tuple trước khi chuyển nó tới rpar:

rpar $!! (x + 1, y + 1) 

nhưng vẫn không có kết quả. Tôi đang làm gì sai?

Trả lời

11

Chiến lược rpar chú thích thuật ngữ để đánh giá có thể song song, nhưng chỉ tối đa biểu mẫu chuẩn yếu đầu bình thường, về cơ bản có nghĩa là, tới nhà xây dựng ngoài cùng. Vì vậy, cho một số nguyên hoặc gấp đôi, có nghĩa là đánh giá đầy đủ, nhưng đối với một cặp, chỉ có các nhà xây dựng cặp, không phải các thành phần của nó, sẽ được đánh giá.

Buộc cặp trước khi chuyển nó đến rpar sẽ không giúp ích gì. Bây giờ bạn đang đánh giá cặp cục bộ, trước khi chú thích tuple đã được đánh giá để đánh giá song song có thể.

Bạn có thể muốn kết hợp rpar với chiến lược rdeepseq, do đó tuyên bố rằng cụm từ phải được đánh giá hoàn toàn, nếu có thể song song. Bạn có thể làm điều này bằng cách nói

(rpar `dot` rdeepseq) (x + 1, y + 1) 

Nhà điều hành dot là dành cho chiến lược soạn thảo.

Tuy nhiên, có một vấn đề khác với mã của bạn: mẫu phù hợp với lực lượng đánh giá ngay lập tức và do đó việc sử dụng đối sánh mẫu cho rpar biểu thức được báo cáo thường là một ý tưởng tồi. Cụ thể, dòng

(x',y') <- (rpar `dot` rdeepseq) (x + 1, y + 1) 

sẽ đánh bại tất cả song song, vì trước khi tia lửa có thể được chọn để đánh giá bằng một chuỗi khác, chuỗi địa phương sẽ bắt đầu đánh giá nó để phù hợp với mẫu. Bạn có thể ngăn chặn điều này bằng cách sử dụng một mô hình lười/không thể chối cãi:

~(x',y') <- (rpar `dot` rdeepseq) (x + 1, y + 1) 

Hoặc cách khác sử dụng fstsnd để truy cập các thành phần của cặp.

Cuối cùng, đừng mong đợi tăng tốc thực sự nếu bạn tạo các tia lửa rẻ như thêm một số vào một số nguyên. Trong khi bản thân tia lửa tương đối rẻ, chúng không phải là chi phí, vì vậy chúng hoạt động tốt hơn nếu tính toán bạn đang chú thích để đánh giá song song có phần tốn kém.

Bạn có thể muốn đọc một số hướng dẫn về cách sử dụng các chiến lược, chẳng hạn như Simon Marlow Parallel and Concurrent Programming using Haskell hoặc Deterministic Parallel Programming in Haskell của riêng tôi.

+0

Cảm ơn! Vấn đề này thực sự nảy sinh khi tôi đọc hướng dẫn của Marlow và thực hiện một số bài tập của riêng tôi. Thêm 1 chỉ là một ví dụ, tôi không muốn làm phức tạp mã mẫu với một số tính toán phức tạp. –

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