Reputation: 365
I am having trouble getting parallel computation done in Haskell. I just tried a very simple computation in parallel and non-parallel forms, and the non-parallel one was a few seconds faster. Am I doing something wrong? Any ideas why this is the case? Thanks in advance.
This is the parallel version of my test code:
-- par.hs
import Control.Parallel
a = sum [1, 3 .. 99999999]
b = sum [2, 4 .. 100000000]
main = (a `par` b) `pseq` print (a + b)
and this is the non-parallel version:
-- nopar.hs
a = sum [1, 3 .. 99999999]
b = sum [2, 4 .. 100000000]
main = print (a + b)
but when I tried it, parallelization had no, or even negative, effects:
➜ ghc par.hs
[1 of 1] Compiling Main ( par.hs, par.o )
Linking par ...
➜ ghc nopar.hs
[1 of 1] Compiling Main ( nopar.hs, nopar.o )
Linking nopar ...
➜ time ./par
5000000050000000
./par 35.02s user 12.83s system 92% cpu 51.501 total
➜ time ./nopar
5000000050000000
./nopar 31.33s user 6.44s system 98% cpu 38.441 total
Upvotes: 2
Views: 154
Reputation: 76297
IIUC, the combination of the comments by @Carl and @Zeta address this:
$ ghc -threaded -O2 par.hs && time ./par
50000005000000
real 0m2.303s
user 0m2.124s
sys 0m0.176s
$ ghc par.hs && ./par +RTS -N2
Linking par ...
par: the flag -N2 requires the program to be built with -threaded
par:
par: Usage: <prog> <args> [+RTS <rtsopts> | -RTS <args>] ... --RTS <args>
par:
par: +RTS Indicates run time system options follow
par: -RTS Indicates program arguments follow
par: --RTS Indicates that ALL subsequent arguments will be given to the
par: program (including any of these RTS flags)
$ ghc -threaded -O2 par.hs && time ./par +RTS -N2
50000005000000
real 0m1.572s
user 0m2.816s
sys 0m0.296s
To see why, here are some excerpts from Real World Haskell
By default, GHC generates programs that use just one core, even when we write explicitly concurrent code. To use multiple cores, we must explicitly choose to do so. We make this choice at link time, when we are generating an executable program. ... If we pass the
-threaded
option to the compiler, it will link our program against the threaded runtime library.
and
We can pass options to GHC's runtime system on the command line of our program. Before handing control to our code, the runtime scans the program's arguments for the special command line option +RTS. ... The threaded runtime accepts an option -N. This takes one argument, which specifies the number of cores that GHC's runtime system should use.
Upvotes: 4