Suche…


Parameter

Typ / Funktion Detail
data Eval a Eval ist eine Monade, die die Definition paralleler Strategien erleichtert
type Strategy a = a -> Eval a eine Funktion, die eine parallele Evaluierungsstrategie verkörpert. Die Funktion durchläuft (Teile von) ihr Argument und wertet Teilausdrücke parallel oder nacheinander aus
rpar :: Strategy a spornt sein Argument (zur parallelen Auswertung)
rseq :: Strategy a wertet sein Argument zu einer schwachen Kopfnormalform aus
force :: NFData a => a -> a wertet die gesamte Struktur des Arguments aus und reduziert es auf Normalform, bevor das Argument selbst zurückgegeben wird. Sie wird vom Control.DeepSeq-Modul bereitgestellt

Bemerkungen

Simon Marlows Buch Concurrent and Parallel Programming in Haskell ist hervorragend und deckt eine Vielzahl von Konzepten ab. Es ist auch für den neuesten Haskell-Programmierer sehr gut zugänglich. Es wird dringend empfohlen und ist kostenlos als PDF oder Online verfügbar.

Parallel gegen gleichzeitig

Simon Marlow sagt es am besten :

Ein Parallelprogramm ist eines, das eine Vielzahl von Computerhardware (z. B. mehrere Prozessorkerne) verwendet, um eine Berechnung schneller durchzuführen. Das Ziel besteht darin, zu einer früheren Antwort zu gelangen, indem verschiedene Teile der Berechnung an verschiedene Prozessoren delegiert werden, die gleichzeitig ausgeführt werden.

Im Gegensatz dazu ist Parallelität eine Programmstrukturierungsmethode, bei der es mehrere Kontrollthreads gibt. Konzeptionell werden die Kontroll-Threads „gleichzeitig“ ausgeführt. das heißt, der Benutzer sieht, dass seine Effekte verschachtelt sind. Ob sie gleichzeitig ausgeführt werden oder nicht, ist ein Implementierungsdetail. Ein gleichzeitiges Programm kann auf einem einzigen Prozessor durch verschachtelte Ausführung oder auf mehreren physischen Prozessoren ausgeführt werden.

Schwache Kopfnormalform

Es ist wichtig zu wissen, wie Lazy-Evaluation funktioniert. Der erste Abschnitt dieses Kapitels wird eine starke Einführung in WHNF und dessen Beziehung zur parallelen und gleichzeitigen Programmierung geben.

Die Eval Monad

Parallelität in Haskell kann mit der Eval Monad von Control.Parallel.Strategies ausgedrückt werden, wobei rseq Funktionen rpar und rseq werden.

f1 :: [Int]
f1 = [1..100000000]

f2 :: [Int]
f2 = [1..200000000]

main = runEval $ do
  a <- rpar (f1) -- this'll take a while...
  b <- rpar (f2) -- this'll take a while and then some...
  return (a,b)

Das Ausführen von main oben wird sofort ausgeführt und "return", während die beiden Werte a und b im Hintergrund durch rpar .

Hinweis: -threaded Sie sicher, dass Sie mit -threaded kompilieren, -threaded parallel ausgeführt werden kann.

rpar

rpar :: Strategy a führt die angegebene Strategie aus (Rückruf: type Strategy a = a -> Eval a ) parallel:

import Control.Concurrent
import Control.DeepSeq
import Control.Parallel.Strategies
import Data.List.Ordered

main = loop
  where 
    loop = do
      putStrLn "Enter a number"
      n <- getLine

      let lim = read n :: Int
          hf  = quot lim 2
          result = runEval $ do
            -- we split the computation in half, so we can concurrently calculate primes
            as <- rpar (force (primesBtwn 2 hf))
            bs <- rpar (force (primesBtwn (hf + 1) lim))
            return (as ++ bs)

      forkIO $ putStrLn ("\nPrimes are: " ++ (show result) ++ " for " ++ n ++ "\n")
      loop

-- Compute primes between two integers
-- Deliberately inefficient for demonstration purposes
primesBtwn n m = eratos [n..m]
  where
    eratos []     = []
    eratos (p:xs) = p : eratos (xs `minus` [p, p+p..])

Wenn Sie dies ausführen, wird das gleichzeitige Verhalten veranschaulicht:

Enter a number
12
Enter a number

Primes are: [2,3,5,7,8,9,10,11,12] for 12

100
Enter a number

Primes are: [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100] for 100

200000000
Enter a number
-- waiting for 200000000    
200
Enter a number

Primes are: [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200] for 200

-- still waiting for 200000000

rseq

Wir können rseq :: Strategy a , um ein Argument in die Normalform von Weak Head zu erzwingen:

f1 :: [Int]
f1 = [1..100000000]

f2 :: [Int]
f2 = [1..200000000]

main = runEval $ do
  a <- rpar (f1) -- this'll take a while...
  b <- rpar (f2) -- this'll take a while and then some...
  rseq a
  return (a,b)

Dies ändert die Semantik des rpar Beispiels auf subtile rpar . Während Letzteres sofort zurückkehrt, während die Werte im Hintergrund berechnet werden, wartet dieses Beispiel, bis a für WHNF ausgewertet werden kann.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow