Song song với bất kỳ người dân hay người dân nào ở vùng Haskell


9

Một mẫu mà tôi đã bắt gặp một số lần bây giờ là một mẫu trong đó một danh sách các giá trị cần được kiểm tra bằng cách ánh xạ một số thử nghiệm qua nó và xem liệu có bất kỳ hoặc tất cả các yếu tố được thông qua không. Giải pháp điển hình là chỉ sử dụng các tiện ích tích hợp allany.

Vấn đề là những đánh giá này nối tiếp. Trong nhiều trường hợp, việc đánh giá song song với quá trình hoàn tất sẽ nhanh hơn nhiều khi bất kỳ luồng nào tìm thấy "Sai" cho allhoặc "Đúng" cho any. Tôi khá chắc chắn rằng hành vi ngắn mạch không thể được thực hiện bằng Control.Parallel vì nó yêu cầu giao tiếp giữa các quá trình và tôi không hiểu bất cứ nơi nào gần đủ Control.Conc hiện để thực hiện điều này.

Đó là một mô hình khá phổ biến trong toán học (ví dụ Miller-Rabin Primality) vì vậy tôi cảm thấy như ai đó có thể đã đưa ra một giải pháp cho điều này rồi, nhưng vì lý do rõ ràng khi thực hiện tìm kiếm google cho "song song hoặc / và / bất kỳ / tất cả trong danh sách haskell "không trả về nhiều kết quả có liên quan.


1
Bạn có thể thấy Lập trình song song và đồng thời trong Haskell hữu ích, đặc biệt là Chương 2 , 34 .
bradrn

2
Điều này là có thể với unambthư viện
luqui

1
@luqui Hấp dẫn; Tôi sẽ loay hoay với điều này. Nếu tôi viết song song tốt tất cả / bất kỳ với điều này, tôi sẽ đăng nó dưới dạng câu trả lời.
Arcuritech

11
Trước khi cố gắng song song hóa bất cứ điều gì, hãy xem xét có bao nhiêu điều kiện bạn có thể kiểm tra trong thời gian cần thiết để rẽ nhánh một quy trình mới.
chepner

2
@chepner bạn đang nói về cái gì vậy? Chúng tôi không nói về bash ở đây! Chúng tôi có thể thực hiện đồng thời và song song với các luồng (có thể là pthreadsC hoặc luồng xanh trong Haskell) Bạn không bắt đầu nhiều máy chủ web để xử lý các yêu cầu web đồng thời, thay vào đó bạn chạy nhiều luồng trong một quy trình! Áp dụng tương tự cho song song. Bạn quay nhiều luồng như bạn có CPU và chia đều công việc của bạn, do đó đảm nhiệm các nhiệm vụ ràng buộc CPU. Hãy thử thư viện này để thuyết phục bản thân github.com/lehins/haskell-scheduler
lehins

Câu trả lời:


2

Trong nhiều chương trình thực tế, bạn có thể sử dụng các chiến lược song song cho mục đích này. Đó là bởi vì, mặc dù không có cơ chế rõ ràng để hủy các tính toán không cần thiết, nhưng điều này sẽ xảy ra ngầm khi trình thu gom rác chạy. Để làm ví dụ cụ thể, hãy xem xét chương trình sau:

import Control.Concurrent
import Control.Parallel.Strategies
import Data.Int
import System.Mem

lcgs :: Int32 -> [Int32]
lcgs = iterate lcg
  where lcg x = 1664525 * x + 1013904223

hasWaldo :: Int32 -> Bool
hasWaldo x = waldo `elem` take 40000000 (lcgs x)

waldo :: Int32
waldo = 0

main :: IO ()
main = do
  print $ or (map hasWaldo [1..100] `using` parList rseq)

Điều này sử dụng chiến lược danh sách song song để tìm kiếm waldo = 0(sẽ không bao giờ được tìm thấy) trong đầu ra của 100 luồng PRNG với 40 triệu số mỗi luồng. Biên dịch và chạy nó:

ghc -threaded -O2 ParallelAny.hs
./ParallelAny +RTS -s -N4

và nó chốt bốn lõi trong khoảng 16 giây, cuối cùng là in False. Lưu ý trong thống kê rằng tất cả 100 tia lửa đều được "chuyển đổi" và cứ thế chạy đến hoàn thành:

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

Bây giờ, thay đổi waldothành một giá trị có thể được tìm thấy sớm:

waldo = 531186389   -- lcgs 5 !! 50000

và sửa đổi mainđể giữ cho chuỗi tồn tại trong 10 giây:

main :: IO ()
main = do
  print $ or (map hasWaldo [1..100] `using` parList rseq)
  threadDelay 10000000

Bạn sẽ quan sát rằng nó in Truegần như ngay lập tức, nhưng 4 lõi vẫn được gắn với CPU 100% (ít nhất là trong một thời gian ngắn), minh họa rằng các tính toán không cần thiết tiếp tục chạy và không bị đoản mạch, như bạn có thể sợ.

NHƯNG , mọi thứ sẽ thay đổi nếu bạn buộc một bộ sưu tập rác sau khi nhận được câu trả lời:

main :: IO ()
main = do
  print $ or (map hasWaldo [1..100] `using` parList rseq)
  performGC
  threadDelay 10000000

Bây giờ, bạn sẽ thấy CPU giảm xuống mức nhàn rỗi ngay sau khi in Truevà các thống kê cho thấy hầu hết các tính toán là rác được thu thập trước khi chạy:

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

Trong các chương trình thực tế, một rõ ràng performGC sẽ không cần thiết , vì các GC sẽ được thực hiện thường xuyên như một vấn đề tất nhiên. Một số tính toán không cần thiết sẽ tiếp tục chạy sau khi tìm thấy câu trả lời, nhưng trong nhiều tình huống thực tế, phần tính toán không cần thiết sẽ không phải là một yếu tố đặc biệt quan trọng.

Đặc biệt, nếu danh sách lớn và mỗi thử nghiệm riêng lẻ của một yếu tố danh sách đều nhanh, các chiến lược song song sẽ có hiệu suất thực tế tuyệt vời và dễ dàng thực hiện để mặc cả.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.