Main thread
- special role
- when it finishes --> entire program finishes
- no permanent deadlocks
f x y = (x + y) + g x + h y
Prelude Control.Parallel> :t par
par :: a -> b -> b
a `par` b
a in parallel with b.a --> thread for abPrelude Control.Parallel> :t pseq
pseq :: a -> b -> b
a `pseq` b
a in current thread then return bf `par` e `pseq` f + e
$ time ./B +RTS -N2
100000020000000
0.84s user 0.02s system 190% cpu 0.478 total
ghc --make -threaded -rtsopts file.hs
+RTS ... -RTS: list of runtime arguments./exec arg +RTS -N2 -RTS arg
seq and pseqPrelude> :t seq
seq :: a -> b -> b
seq is strict in both argumentspseq is strict only in the first onea `seq` b
b `seq` a `seq` b
seq compiler decides what to evaluate first (opportunity)pseq user decides what to be evaluated first (promise)import Debug.Trace
martor x = trace ("called for " ++ show x) x
list n = trace "generating list" $ map martor [1..n]
main = do
print $ trace "computing" $ list 2
let l = trace "new list" $ list 2
print $ trace "once" l
print $ trace "twice" l
let l = trace "with seq" $ let l = list 2 in l `seq` l
print $ trace "seq" l
Main> main
computing
generating list
[called for 1
1,called for 2
2]
once
new list
generating list
[called for 1
1,called for 2
2]
twice
[1,2]
seq
with seq
generating list
[called for 1
1,called for 2
2]
42
(2, "hello")
\x -> (x + 1)
1 + 2
(1 + 1, 2 + 2)
\x -> 2 + 2
'h' : ("e" ++ "llo")
(\x -> x + 1) 2
"he" ++ "llo"
seq ad pseq evaluate to WHNF($!) :: (a -> b) -> a -> b
Remember
f $ x = f x
So
f $! g x
is a strict version of
f $ g x
f x !y !z t = ...
data Complex a = !a :+ !a
import System.Environment
mySort (x:xs) = lesser ++ x:greater
where
lesser = mySort [y | y <- xs, y < x]
greater = mySort [y | y <- xs, y >= x]
mySort _ = []
main = do
args <- getArgs
let n:_ = map read args
print $ length $ mySort [n, n-1 .. 0]
$ time ./4 5000 +RTS -N2
5001
real 0m17.506s
user 0m10.619s
sys 0m2.863s
import Control.Parallel
import System.Environment
mySort (x:xs) = greater `par` (lesser `pseq` lesser ++ x:greater)
where
lesser = mySort [y | y <- xs, y < x]
greater = mySort [y | y <- xs, y >= x]
mySort _ = []
main = do
args <- getArgs
let n:_ = map read args
print $ length $ mySort [n, n-1 .. 0]
$ time ./2 5000 +RTS -N2
5001
real 0m7.559s
user 0m5.926s
sys 0m1.613s
time as a global measure is wrong:
$ ghc --make -threaded -eventlog -rtsopts 2.hs
$ ./2 5000 +RTS -ls -N2
$ threadscope 2.eventlog
instance NFData ... where
rnf = ...
Prelude Control.Concurrent> :t forkIO
forkIO :: IO () -> IO ThreadId
Prelude Control.Concurrent> :t forkOS
forkOS :: IO () -> IO ThreadId
forkOS constructs a new OS threadforkIOimport Control.Concurrent
thread x = do
putStrLn $ "Thread " ++ show x
main = do
forkIO $ thread 42
$ ./3 +RTS -N2
Thread 42
$ ./3 +RTS -N2
$
import Control.Concurrent
thread x = do
putStrLn $ "Thread " ++ show x
main = do
forkIO $ thread 1
forkIO $ thread 2
forkIO $ thread 3
forkIO $ thread 4
forkIO $ thread 5
forkIO $ thread 6
$ ./5 +RTS -N2
Thread 1
Thread 3
Thread 5
import Control.Concurrent
import Control.Monad
thread x = do
putStrLn $ "Thread " ++ show x
main = do
mapM (forkIO . thread) [1..6]
$ ./6 +RTS -N2
Thread 1
$ ./6 +RTS -N2
Thread 1
Thread 3
Thread 5
$ ./6 +RTS -N2
Thread 1
Thread 6
$ ./6 +RTS -N2
Thread 2
newMVar :: a -> IO (MVar a)
newEmptyMVar :: IO (MVar a)
putMVar :: MVar a -> a -> IO ()
takeMVar :: MVar a -> IO a
tryPutMVar :: MVar a -> a -> IO Bool
tryTakeMVar :: MVar a -> IO (Maybe a)
readMVar for example)import Control.Concurrent
thread :: Int -> MVar () -> IO ()
thread x v = do
putStrLn $ "Thread " ++ show x
putMVar v ()
main = do
v <- newEmptyMVar
forkIO $ thread 42 v
takeMVar v
import Control.Concurrent
import Control.Monad
thread :: Int -> MVar () -> IO ()
thread x v = do
putStrLn $ "Thread " ++ show x
putMVar v ()
main = do
vars <- replicateM 6 newEmptyMVar
mapM (forkIO . uncurry thread) (zip [1..6] vars)
mapM_ takeMVar vars
newChan :: IO (Chan a)
dupChan :: Chan a -> IO (Chan a)
readChan :: Chan a -> IO a
writeChan :: Chan a -> a -> IO ()
readChan from empty --> blockswriteChan never blocksimport Control.Concurrent
thread :: Int -> Chan Int -> MVar Int -> IO ()
thread x c v = do
putStrLn $ "Thread " ++ show x
threadDelay 100000
a <- readChan c
b <- readChan c
putMVar v (a + b)
return ()
main = do
v <- newEmptyMVar
c <- newChan
forkIO $ thread 42 c v
writeChan c 40
writeChan c 2
s <- readMVar v
print s
import Control.Concurrent
import Control.Monad
thread :: Int -> Chan Int -> MVar () -> IO ()
thread x c v = do
s <- readChan c
putStrLn $ "Thread " ++ show x ++ " read " ++ show s
putMVar v ()
main = do
c <- newChan
vars <- replicateM 6 newEmptyMVar
chans <- replicateM 6 (dupChan c)
mapM (forkIO . \(x,y,z) -> thread x y z) $ [(x, chans !! x, vars !! x) | x <- [0..5]]
threadDelay 1000000
writeChan c 42
mapM_ takeMVar vars
import Control.Concurrent
thread out inn v = do
modifyMVar_ out $ \x -> do
yield
modifyMVar_ inn $ \y -> return (y + 1)
return (x + 1)
putStrLn "done"
putMVar v ()
main = do
a <- newMVar 1
b <- newMVar 2
v <- newEmptyMVar
v' <- newEmptyMVar
forkIO $ thread a b v
forkIO $ thread b a v'
takeMVar v
takeMVar v'
putMVar even if in erroratomically :: STM a -> IO a
readTVar :: TVar a -> STM a
writeTVar :: TVar a -> a -> STM ()
withdraw :: Account -> Int -> STM ()
withdraw acc amount = do
bal <- readTVar acc
writeTVar acc (bal - amount)
deposit :: Account -> Int -> STM ()
deposit acc amount = withdraw acc (- amount)
import Control.Concurrent
import Control.Concurrent.STM
type Account = TVar Int
newAccount = newTVarIO 0
...
limitedWithdraw :: Account -> Int -> STM ()
limitedWithdraw acc amount = do
bal <- readTVar acc
check (amount <= 0 || amount <= bal)
writeTVar acc (bal - amount)
t1 a = atomically $ deposit a 10
t2 a = atomically $ limitedWithdraw a 6
main = do
a <- newAccount
mapM forkIO [t1 a, t2 a, t2 a, t2 a, t1 a]
threadDelay 1000000
par / seq: light, hard granularityforkIO / MVar / Chan / STM: more precise, more complexsumsq :: [: Float :] → Float
sumsq a = sumP [: x*x | x ← a :]
type Vector = [: Float :]
type Matrix = [: Vector :]
matMul :: Matrix → Vector → Vector
matMul m v = [: vecMul r v | r ← m :]
par, pseq