Recherche…


Paramètres

Type / Fonction Détail
data Eval a Eval est une Monade qui facilite la définition de stratégies parallèles
type Strategy a = a -> Eval a une fonction qui incarne une stratégie d'évaluation parallèle. La fonction parcourt son argument en évaluant les sous-expressions en parallèle ou en séquence
rpar :: Strategy a déclenche son argument (pour une évaluation en parallèle)
rseq :: Strategy a évalue son argument à la forme normale de la tête faible
force :: NFData a => a -> a évalue la structure entière de son argument en le réduisant à la forme normale avant de renvoyer l'argument lui-même. Il est fourni par le module Control.DeepSeq

Remarques

Le livre de Simon Marlow , Programmation simultanée et parallèle à Haskell, est remarquable et couvre une multitude de concepts. Il est également très accessible même pour le plus récent programmeur Haskell. Il est fortement recommandé et disponible en PDF ou en ligne gratuitement.

Parallèle vs Concurrent

Simon Marlow le dit mieux :

Un programme parallèle est un programme qui utilise une multiplicité de matériel informatique (par exemple, plusieurs cœurs de processeur) pour effectuer un calcul plus rapidement. L'objectif est d'arriver à la réponse plus tôt, en déléguant différentes parties du calcul à différents processeurs exécutant en même temps.

En revanche, la concurrence est une technique de structuration de programme dans laquelle il existe plusieurs threads de contrôle. Conceptuellement, les threads de contrôle s'exécutent «en même temps»; c'est-à-dire que l'utilisateur voit ses effets entrelacés. Qu'elles soient exécutées en même temps ou non, c'est un détail d'implémentation. un programme simultané peut s'exécuter sur un seul processeur par exécution entrelacée ou sur plusieurs processeurs physiques.

Forme normale de tête faible

Il est important de savoir comment fonctionne l'évaluation paresseuse. La première section de ce chapitre présentera une introduction solide sur le WHNF et sa relation avec la programmation parallèle et simultanée.

L'éval monade

Le parallélisme dans Haskell peut être exprimé à l'aide de l' Eval Monad de Control.Parallel.Strategies , en utilisant les fonctions rpar et rseq (entre autres).

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)

En cours d'exécution au main dessus s'exécutera et "retournera" immédiatement, tandis que les deux valeurs, a et b seront calculées en arrière-plan via rpar .

Remarque: assurez-vous de compiler avec -threaded pour que l'exécution en parallèle se produise.

rpar

rpar :: Strategy a exécute la stratégie donnée (rappel: type Strategy a = a -> Eval a ) en parallèle:

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'exécution de cette opération démontrera le comportement simultané:

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

On peut utiliser rseq :: Strategy a pour forcer un argument à Weak Head Normal Form:

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)

Cela modifie subtilement la sémantique de l'exemple rpar ; alors que celui - ci retourneraient immédiatement tout en calculant les valeurs en arrière - plan, cet exemple attendre a peut être évalué à WHNF.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow