I am studying the Haskell to the thread part. I try to create 2 threads to do the different calculation. This is a really simple function just for practice. The code like this:
import Control.Concurrent (forkIO)
task4 a b = do
forkIO $ a^b
forkIO $ b^a
if (a^b) > (b^a) then putStrLn ([a] ++ "^"++[b] ++ "=" ++ [a^b] ++ "is bigger!")
else putStrLn ([b] ++ "^"++[a] ++ "=" ++ [b^a] ++ "is bigger!")
I don't know how to dual with the type inside the do block. And am I right to create threads like this?
Since some time has passed, here's how you would do it with threads:
-- helper function for all other methods
message a b = (show a) ++ " ? " ++ (show b) ++ " " ++ (show . compare a $ b)
threads a b = do
abVar <- newEmptyMVar
baVar <- newEmptyMVar
forkIO $ putMVar abVar (a^b)
forkIO $ putMVar baVar (b^a)
ab <- takeMVar abVar
ba <- takeMVar baVar
putStrLn $ message ab ba
That's a mouthful. Even worse, it's not pure anymore. After all, your program is basically nothing more than
simple a b = message (a^b) (b^a)
-- IO version
simpleIO :: Integer -> Integer -> IO ()
simpleIO a b = putStrLn $ simple a b
Or at least it should behave the same. If you want to do this in parallel, there's no need for IO
, using par
and pseq
:
parAB a b = force ab `par` force ba `pseq` message ab ba
where ab = a^b
ba = b^a
-- IO version
parABIO a b = putStrLn $ parAB a b
But in the end, using parallel or concurrent techniques on such simple tasks as a^b
won't gain you anything:
par
is generally used when the value ofa
is likely to be required later, but not immediately. Also it is a good idea to ensure thata
is not a trivial computation, otherwise the cost of spawning it in parallel overshadows the benefits obtained by running it in parallel.
This can be checked by using Criterion:
import Control.Concurrent
import Control.Parallel
import Control.DeepSeq
import Criterion.Main
message a b = (show a) ++ " ? " ++ (show b) ++ " " ++ (show . compare a $ b)
simple, parAB :: Integer -> Integer -> String
simpleIO, parABIO, threads :: Integer -> Integer -> IO ()
simple a b = message (a^b) (b^a)
simpleIO a b = putStrLn $ simple a b
parAB a b = force ab `par` force ba `pseq` message ab ba
where ab = a^b
ba = b^a
parABIO a b = putStrLn $ parAB a b
threads a b = do
abVar <- newEmptyMVar
baVar <- newEmptyMVar
forkIO $ putMVar abVar (a^b)
forkIO $ putMVar baVar (b^a)
ab <- takeMVar abVar
ba <- takeMVar baVar
putStrLn $ message ab ba
main = defaultMain [
bgroup "simpleIO"
[ bench "1531235 123152123" $ whnf (simpleIO 1531235) 123152123
, bench "2 121351356" $ whnf (simpleIO 2) 121351356
, bench "12346 415" $ whnf (simpleIO 12346) 415
],
bgroup "parABIO"
[ bench "1531235 123152123" $ whnf (parABIO 1531235) 123152123
, bench "2 121351356" $ whnf (parABIO 2) 121351356
, bench "12346 415" $ whnf (parABIO 12346) 415
],
bgroup "threads"
[ bench "1531235 123152123" $ whnf (threads 1531235) 123152123
, bench "2 121351356" $ whnf (threads 2) 121351356
, bench "12346 415" $ whnf (threads 12346) 415
]
]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.