My understanding to par is that it will create a thread in another core to execution.
But I failed proof this understanding with following test code since the result showing seems only one thread is running.
Could you help me to figure out what’s wrong here?
import Control.Monad
import Control.Parallel
import Control.Concurrent
import System.IO.Unsafe
fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = (fib (n-1)) + (fib (n - 2))
test :: String -> [Int] -> IO ()
test _ [] = return ()
test name (a:xs) = do
tid <- myThreadId
print $ (show tid) ++ "==>" ++ (show a) ++ "==>" ++ (show $ fib a) ++ "==>" ++ name
x `par` y
where x = test "2" xs
y = test "3" (tail xs)
main = test "1" [10..35]
Compiled with:
ghc --make -threaded -rtsopts test-par.hs
time ./test-par +RTS -N2
The result
"ThreadId 3==>10==>89==>1"
"ThreadId 3==>12==>233==>3"
"ThreadId 3==>14==>610==>3"
"ThreadId 3==>16==>1597==>3"
"ThreadId 3==>18==>4181==>3"
"ThreadId 3==>20==>10946==>3"
"ThreadId 3==>22==>28657==>3"
"ThreadId 3==>24==>75025==>3"
"ThreadId 3==>26==>196418==>3"
"ThreadId 3==>28==>514229==>3"
"ThreadId 3==>30==>1346269==>3"
"ThreadId 3==>32==>3524578==>3"
"ThreadId 3==>34==>9227465==>3"
real 0m1.131s
user 0m0.668s
sys 0m0.492s
How many core I have?
cat /proc/cpuinfo | grep processor | wc -l
2
——————————– update
I think this paper by Simon Marlow is a good reference for such newbie question.
No,
pardoes not guarantee to create another thread.It registers a spark in the runtime, which may cause the computation to be executed in a different thread, depending on the dynamic workload of the machine.
Creating a spark is very cheap, so you can create many (1000x) more than you have threads, and the runtime will just try to keep all your cores busy.
In your case, your
xcomputation is registered as a spark, and then immediately discarded (you never refer to it again). So the garbage collector can remove it.To parallelize a recursive function, you’ll typically want to just use
parup to some depth.An example — a recursive function with a cutoff depth:
Run as:
Yields a parallel workload 1248.9% over sequential (i.e. 12.48x):
We created 597 sparks, of which 446 were converted into threads.
If you explicitly want to do manual thread creation and communication, this can be done via
forkIOandMVars.