Haskell'de paralel "herhangi bir" veya "tümü"


9

Şimdi birkaç kez karşılaştığım bir desen, üzerinde bir test eşleştirerek ve öğelerin herhangi birinin veya tamamının geçip geçmediğini görerek bir değer listesinin kontrol edilmesi gereken modeldir. Tipik çözüm sadece kullanışlı dahili ins kullanmaktır allve any.

Sorun, bunların seri olarak değerlendirilmesi. Birçok durumda, herhangi bir iş parçacığı için bir "Yanlış" veya "Doğru" bulduktan sonra işlemin tamamlanmasına paralel olarak değerlendirmek çok daha hızlı olacaktır . İşlemler arası iletişim gerektirdiğinden ve Control.Concurrent'ı henüz uygulamak için yeterince yakın bir yerde anlamadığım için kısa devre davranışının Control.Parallel kullanılarak uygulanamayacağından eminim.allany

Matematikte oldukça yaygın bir örüntüdür (örneğin Miller-Rabin Primality) Bu yüzden birisi muhtemelen bunun için bir çözüm bulmuş gibi hissediyorum, ancak bariz nedenlerden dolayı "paralel veya / ve / / herhangi bir / listede herhangi bir google araması yapmak haskell "birçok alakalı sonuç döndürmez.


1
Paralel ve Eşzamanlı Programlamayı Haskell'de , özellikle Bölüm 2 , 3 ve 4'te yararlı bulabilirsiniz .
bradrn

2
Bu unambkütüphane ile mümkündür
luqui

1
@luqui Büyüleyici; Bununla uğraşacağım. Eğer bununla iyi bir paralel yazarsam cevap olarak gönderirim.
Arcuritech

11
Herhangi bir şeyi paralelleştirmeye çalışmadan önce, yeni bir işlemi çatallamak için gereken süre içinde kaç koşulu test edebileceğinizi düşünün.
chepner

2
@ chepner sen neden bahsediyorsun Burada bash hakkında konuşmuyoruz! İş parçacıklarıyla eşzamanlılık ve paralellik yapabiliriz ( pthreadsHaskell'de C veya yeşil iş parçacıkları olsun) Eşzamanlı web isteklerini işlemek için birden çok web sunucusu başlatmazsınız, bunun yerine tek bir işlemde birden çok iş parçacığı çalıştırırsınız! Aynı şey paralellik için de geçerlidir. CPU'larınız kadar çok iş parçacığını döndürür ve işinizi eşit olarak böldüğünüzde, CPU'ya bağlı görevlerle ilgilenirsiniz. Kendinizi ikna etmek için bu kütüphaneyi deneyin github.com/lehins/haskell-scheduler
lehins

Yanıtlar:


2

Birçok gerçekçi programda, bu amaç için paralel stratejiler kullanabilirsiniz. Çünkü gereksiz hesaplamaları iptal etmek için açık bir mekanizma olmasa da, bu, çöp toplayıcı çalıştığında örtük olarak gerçekleşecektir. Somut bir örnek olarak, aşağıdaki programı göz önünde bulundurun:

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)

Bu, waldo = 0her biri 40 milyon sayıdan oluşan 100 PRNG akışının çıkışında (asla bulunmayacak) arama yapmak için paralel bir liste stratejisi kullanır . Derleyin ve çalıştırın:

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

ve yaklaşık 16 saniye boyunca dört çekirdek mandallar, sonunda baskı False. İstatistiklerde, 100 kıvılcımın hepsinin "dönüştürüldüğünü" ve bu nedenle tamamlanacağını unutmayın:

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

Şimdi, waldoerken bulunabilecek bir değere geçin:

waldo = 531186389   -- lcgs 5 !! 50000

ve mainipliği 10 saniye canlı tutacak şekilde değiştirin :

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

TrueNeredeyse anında yazdırdığını gözlemleyeceksiniz , ancak 4 çekirdek% 100 CPU'da sabit kalmaya devam ediyor (en azından bir süreliğine), gerekmeyen hesaplamaların çalışmaya devam ettiğini ve korktuğunuz gibi kısa devre olmadığını gösteriyor.

AMA , yanıtı aldıktan sonra bir çöp toplama zorlarsanız işler değişir:

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

Şimdi, CPU'nun yazdırıldıktan kısa bir süre sonra boşta kaldığını göreceksiniz Trueve istatistikler, hesaplamaların çoğunun çalıştırmadan önce toplandığını gösteriyor:

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

Gerçekçi programlarda, performGCGC'ler elbette düzenli olarak gerçekleştirileceğinden açık bir şeye ihtiyaç duyulmayacaktır. Bazı gereksiz hesaplamalar, cevap bulunduktan sonra çalışmaya devam edecektir, ancak birçok gerçekçi senaryoda, gereksiz hesaplamaların oranı özellikle önemli bir faktör olmayacaktır.

Özellikle, liste büyükse ve bir liste öğesinin her bir testi hızlıysa, paralel stratejiler mükemmel gerçek dünya performansına sahip olacak ve pazarlığa uygulanması kolaydır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.