Ricerca…


Parametri

Tipo / Funzione Dettaglio
data Eval a Eval è una Monade che facilita la definizione di strategie parallele
type Strategy a = a -> Eval a una funzione che incarna una strategia di valutazione parallela. La funzione attraversa (parti di) il suo argomento, valutando le sottoespressioni in parallelo o in sequenza
rpar :: Strategy a sputa la sua argomentazione (per la valutazione in parallelo)
rseq :: Strategy a valuta la sua argomentazione per la forma normale della testa debole
force :: NFData a => a -> a valuta l'intera struttura del suo argomento, riducendolo in forma normale, prima di restituire l'argomento stesso. È fornito dal modulo Control.DeepSeq

Osservazioni

Il libro di Simon Marlow , Concurrent and Parallel Programming in Haskell, è eccezionale e copre una moltitudine di concetti. È anche molto accessibile anche per il nuovo programmatore Haskell. È altamente raccomandato e disponibile in PDF o online gratuitamente.

Parallelo vs Concorrente

Simon Marlow lo dice meglio :

Un programma parallelo è uno che utilizza una molteplicità di hardware computazionale (ad esempio, diversi core del processore) per eseguire un calcolo più rapidamente. L'obiettivo è di arrivare alla risposta in precedenza, delegando diverse parti del calcolo a diversi processori che eseguono contemporaneamente.

Al contrario, la concorrenza è una tecnica di strutturazione del programma in cui vi sono più thread di controllo. Concettualmente, i fili del controllo vengono eseguiti "allo stesso tempo"; cioè, l'utente vede i loro effetti intercalati. Se eseguono o meno allo stesso tempo o meno è un dettaglio di implementazione; un programma concorrente può essere eseguito su un singolo processore mediante esecuzione interlacciata o su più processori fisici.

Forma normale della testa debole

È importante essere consapevoli di come funziona la valutazione pigra. La prima sezione di questo capitolo darà una forte introduzione al WHNF e come questo si riferisce alla programmazione parallela e concorrente.

The Eval Monad

Parallelismo in Haskell può essere espresso utilizzando Eval Monade da Control.Parallel.Strategies , utilizzando i rpar e rseq funzioni (tra gli altri).

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)

Esecuzione main sopra eseguirà e "ritorno" immediatamente, mentre i due valori, a e b sono calcolati in background tramite rpar .

Nota: assicurati di compilare con -threaded per l'esecuzione parallela.

rpar

rpar :: Strategy a esegue la strategia data (richiama: type Strategy a = a -> Eval a ) in parallelo:

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..])

L'esecuzione di questo dimostrerà il comportamento concorrente:

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

Possiamo usare rseq :: Strategy a per forzare un argomento su Normal rseq :: Strategy a Debole:

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)

Questo cambia leggermente la semantica dell'esempio rpar ; mentre il secondo sarebbe tornato subito, mentre calcolando i valori sullo sfondo, questo esempio attenderà fino a quando a può essere valutata a WHNF.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow