
How do I compile and run this parallel program?
Michael
===========================
import Control.Parallel
nfib :: Int -> Intnfib n | n <= 1 = 1 | otherwise = par n1 (seq n2 (n1 + n2 + 1)) where n1 = nfib (n-1) n2 = nfib (n-2)
{-nfib :: Int -> Intnfib n | n <= 1 = 1 | otherwise = nfib (n-1) + nfib (n-2)-}
main = do putStrLn $ show $ nfib 39
===========================
[michael@hostname ~]$ ghc --make -threaded nfib.hs[michael@hostname ~]$ ./nfib +RTS -N3nfib: the flag -N3 requires the program to be built with -threadednfib: nfib: Usage: <prog> <args> [+RTS <rtsopts> | -RTS <args>] ... --RTS <args>nfib: nfib: +RTS Indicates run time system options follownfib: -RTS Indicates program arguments follownfib: --RTS Indicates that ALL subsequent arguments will be given to thenfib: program (including any of these RTS flags)nfib: nfib: The following run time system options are available:nfib: nfib: -? Prints this message and exits; the program is not executednfib: --info Print information about the RTS used by this programnfib: nfib: -K<size> Sets the maximum stack size (default 8M) Egs: -K32k -K512knfib: -k<size> Sets the initial thread stack size (default 1k) Egs: -k4k -k2mnfib: nfib: -A<size> Sets the minimum allocation area size (default
512k) Egs: -A1m -A10knfib: -M<size> Sets the maximum heap size (default unlimited) Egs: -M256k -M1Gnfib: -H<size> Sets the minimum heap size (default 0M) Egs: -H24m -H1Gnfib: -m<n> Minimum % of heap which must be available (default 3%)nfib: -G<n> Number of generations (default: 2)nfib: -T<n> Number of steps in younger generations (default: 2)nfib: -c<n> Use in-place compaction instead of copying in the oldest generationnfib: when live data is at least <n>% of the maximum heap size set withnfib: -M (default: 30%)nfib: -c Use in-place compaction for all oldest generation collectionsnfib: (the default is to use copying)nfib: -w Use mark-region for the oldest generation (experimental)nfib: nfib: -t[<file>] One-line GC statistics (if <file> omitted, uses stderr)nfib: -s[<file>] Summary GC statistics (if <file> omitted, uses
stderr)nfib: -S[<file>] Detailed GC statistics (if <file> omitted, uses stderr)nfib: nfib: nfib: -Z Don't squeeze out update frames on stack overflownfib: -B Sound the bell at the start of each garbage collectionnfib: nfib: -hT Heap residency profile (output file <program>.hp)nfib: -i<sec> Time between heap samples (seconds, default: 0.1)nfib: nfib: -C<secs> Context-switch interval in seconds.nfib: 0 or no argument means switch as often as possible.nfib: Default: 0.02 sec; resolution is set by -V below.nfib: -V<secs> Master tick interval in seconds (0 == disable timer).nfib: This sets the resolution for -C and the profile timer -i.nfib: Default: 0.02 sec.nfib: nfib: --install-signal-handlers=

On Thursday 26 May 2011 13:24:09, michael rice wrote:
How do I compile and run this parallel program? Michael =========================== import Control.Parallel nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = par n1 (seq n2 (n1 + n2 + 1))
The 'seq' here should be a 'pseq' to ensure that n2 is (started to be) calculated before (n1 + n2 +1) is evaluated (iirc, currently, both work with ghc, but it's not guaranteed for seq).
where n1 = nfib (n-1) n2 = nfib (n-2) {-nfib :: Int -> Intnfib n | n <= 1 = 1 | otherwise = nfib (n-1) + nfib (n-2)-}
main = do putStrLn $ show $ nfib 39 =========================== [michael@hostname ~]$ ghc --make -threaded nfib.hs [michael@hostname ~]$ ./nfib +RTS -N3
In principle, that is the correct way to compile and run it (note that with ghc-7, you don't need the --make).
nfib: the flag -N3 requires the program to be built with -threaded
Have you previously compiled the programme without -threaded? Unless you snipped the compilation messages, their absence strongly indicates so. If that is the case, you fell victim to ghc's recompilation-avoidance which doesn't keep track of the flags a programme/module was compiled with, so it saw that nothing [as far as it knows] changed, hence didn't recompile. Then removing .o and .hi or passing -fforce-recomp will make it recompile and link with the threaded runtime.

Thank, Daniel
Multiple threads are in evidence in my system monitor, but I wonder why I'm getting two different answers, one twice the other. The first is the parallel solution and the second is the non.
Michael
===========
{-import Control.Parallel
nfib :: Int -> Intnfib n | n <= 1 = 1 | otherwise = par n1 (pseq n2 (n1 + n2 + 1)) where n1 = nfib (n-1) n2 = nfib (n-2)-}
nfib :: Int -> Intnfib n | n <= 1 = 1 | otherwise = nfib (n-1) + nfib (n-2)
main = do putStrLn $ show $ nfib 39
=============
[michael@hostname ~]$ ghc --make -threaded nfib.hs[1 of 1] Compiling Main ( nfib.hs, nfib.o )Linking nfib ...[michael@hostname ~]$ ./nfib +RTS -N3204668309[michael@hostname ~]$ ghc --make nfib.hs[1 of 1] Compiling Main ( nfib.hs, nfib.o )Linking nfib ...[michael@hostname ~]$ ./nfib102334155[michael@hostname ~]$
--- On Thu, 5/26/11, Daniel Fischer
How do I compile and run this parallel program? Michael =========================== import Control.Parallel nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = par n1 (seq n2 (n1 + n2 + 1))
The 'seq' here should be a 'pseq' to ensure that n2 is (started to be) calculated before (n1 + n2 +1) is evaluated (iirc, currently, both work with ghc, but it's not guaranteed for seq).
where n1 = nfib (n-1) n2 = nfib (n-2) {-nfib :: Int -> Intnfib n | n <= 1 = 1 | otherwise = nfib (n-1) + nfib (n-2)-}
main = do putStrLn $ show $ nfib 39 =========================== [michael@hostname ~]$ ghc --make -threaded nfib.hs [michael@hostname ~]$ ./nfib +RTS -N3
In principle, that is the correct way to compile and run it (note that with ghc-7, you don't need the --make).
nfib: the flag -N3 requires the program to be built with -threaded
Have you previously compiled the programme without -threaded? Unless you snipped the compilation messages, their absence strongly indicates so. If that is the case, you fell victim to ghc's recompilation-avoidance which doesn't keep track of the flags a programme/module was compiled with, so it saw that nothing [as far as it knows] changed, hence didn't recompile. Then removing .o and .hi or passing -fforce-recomp will make it recompile and link with the threaded runtime.

2011/5/26 michael rice
Thank, Daniel
Multiple threads are in evidence in my system monitor, but I wonder why I'm getting two different answers, one twice the other. The first is the parallel solution and the second is the non.
Why do you add n1+n2+1 in the parallel program, but only n1+n2 in the non-parallel one ?
Michael
===========
{- import Control.Parallel
nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = par n1 (pseq n2 (n1 + n2 + 1)) where n1 = nfib (n-1) n2 = nfib (n-2) -}
nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = nfib (n-1) + nfib (n-2)
main = do putStrLn $ show $ nfib 39
=============
[michael@hostname ~]$ ghc --make -threaded nfib.hs [1 of 1] Compiling Main ( nfib.hs, nfib.o ) Linking nfib ... [michael@hostname ~]$ ./nfib +RTS -N3 204668309 [michael@hostname ~]$ ghc --make nfib.hs [1 of 1] Compiling Main ( nfib.hs, nfib.o ) Linking nfib ... [michael@hostname ~]$ ./nfib 102334155 [michael@hostname ~]$

Fair question. I copied the parallel version from:
http://www.haskell.org/ghc/docs/6.6/html/users_guide/lang-parallel.html
but pulled the non-parallel version from a text.
Michael
--- On Thu, 5/26/11, David Virebayre

Are the tools of Control.Parallel comparable to OpenMP?
Michael
--- On Thu, 5/26/11, michael rice

Hi Michael, OpenMP is a very different beast, and was developed to help get over the shortcomings that languages like C and FORTRAN have with respect to parallel and concurrent programming (pthreads were about all there was before OpenMP). OpenMP lets you specify regions of code that should be run in multiple threads at once, each with a unique ID. Here is an example of (part of) a parallel merge sort I've been working on
static void pmergesort(long int * in, long int * tmp, long int n, int nthread) { long int nhalf = n/2;
if(n <= N_small) { insertsort1(in, n); return; }
if(nthread > 1) { #pragma omp parallel num_threads(2) { if(omp_get_thread_num() == 0) pmergesort(tmp, in, nhalf, nthread>>1); else pmergesort(tmp+nhalf, in+nhalf, n-nhalf, nthread>>1); } } else { mergesort3(tmp, in, nhalf); mergesort3(tmp+nhalf, in+nhalf, n-nhalf); }
merge( tmp, in, nhalf, n); }
The approach that Control.Concurrent takes is very different, preferring a style where the programmer says what things might be advantageous to run in parallel, but the runtime makes no guarantees that they will be, allowing the programmer to break work down into smaller chunks, and letting the runtime sort out which parts should be run concurrently. This allows for a much easier style of parallel programming, but is only really possible in a pure language like Haskell. On a side note, the Cilk language, which adds a small number of keywords like fork and sync to the C language takes an approach closer to what Control.Parallel does, but it's not a graceful, and IMO not as easy to use. Hope that helps. I've been having a lot of fun over the last few weeks playing with OpenMP for a university assignment, and I've got to say I greatly prefer the haskell way of doing things. Cheers, Alex Mason On 27/05/2011, at 10:23, michael rice wrote:
Are the tools of Control.Parallel comparable to OpenMP?
Michael
--- On Thu, 5/26/11, michael rice
wrote: From: michael rice
Subject: Re: [Haskell-cafe] Parallel compilation and execution? To: "David Virebayre" Cc: "Daniel Fischer" , haskell-cafe@haskell.org Date: Thursday, May 26, 2011, 9:32 AM Fair question. I copied the parallel version from:
http://www.haskell.org/ghc/docs/6.6/html/users_guide/lang-parallel.html
but pulled the non-parallel version from a text.
Michael
--- On Thu, 5/26/11, David Virebayre
wrote: From: David Virebayre
Subject: Re: [Haskell-cafe] Parallel compilation and execution? To: "michael rice" Cc: haskell-cafe@haskell.org, "Daniel Fischer" Date: Thursday, May 26, 2011, 8:56 AM 2011/5/26 michael rice
Thank, Daniel Multiple threads are in evidence in my system monitor, but I wonder why I'm getting two different answers, one twice the other. The first is the parallel solution and the second is the non.
Why do you add n1+n2+1 in the parallel program, but only n1+n2 in the non-parallel one ?
Michael
===========
{- import Control.Parallel
nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = par n1 (pseq n2 (n1 + n2 + 1)) where n1 = nfib (n-1) n2 = nfib (n-2) -}
nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = nfib (n-1) + nfib (n-2)
main = do putStrLn $ show $ nfib 39
=============
[michael@hostname ~]$ ghc --make -threaded nfib.hs [1 of 1] Compiling Main ( nfib.hs, nfib.o ) Linking nfib ... [michael@hostname ~]$ ./nfib +RTS -N3 204668309 [michael@hostname ~]$ ghc --make nfib.hs [1 of 1] Compiling Main ( nfib.hs, nfib.o ) Linking nfib ... [michael@hostname ~]$ ./nfib 102334155 [michael@hostname ~]$
-----Inline Attachment Follows-----
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Alex,
I had previously looked at OpenMP (Fortran) and when I saw par and seq in Control.Parallel I got a sense of common terminology, sections of code that can be executed in parallel and sections of code that must be executed sequentially. I haven't looked at Control.Concurrent yet.
The original reason I took a look at Haskell (and Erlang) was multi-core CPUs were becoming common and I wanted to learn to take advantage of them, but Haskell's learning curve has been so steep I've been occupied with learning other aspects of the language and only now have turned again to try my hand at its parallelizing features.
Thanks,
Michael
--- On Fri, 5/27/11, Alex Mason

On 26/05/2011 14:32, michael rice wrote:
Fair question. I copied the parallel version from:
http://www.haskell.org/ghc/docs/6.6/html/users_guide/lang-parallel.html http://www.haskell.org/ghc/docs/6.6/html/users_guide/lang-parallel.html
That is the User Guide for GHC 6.6, incidentally. If you're using a later version of GHC (highly recommended especially for parallel stuff), then you should look at the docs for your version. Cheers, Simon
http://www.haskell.org/ghc/docs/6.6/html/users_guide/lang-parallel.htmlbut pulled the non-parallel version from a text.
Michael
--- On *Thu, 5/26/11, David Virebayre /
/* wrote: From: David Virebayre
Subject: Re: [Haskell-cafe] Parallel compilation and execution? To: "michael rice" Cc: haskell-cafe@haskell.org, "Daniel Fischer" Date: Thursday, May 26, 2011, 8:56 AM 2011/5/26 michael rice
> Thank, Daniel
Multiple threads are in evidence in my system monitor, but I wonder why I'm getting two different answers, one twice the other. The first is the parallel solution and the second is the non.
Why do you add n1+n2+1 in the parallel program, but only n1+n2 in the non-parallel one ?
Michael
===========
{- import Control.Parallel
nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = par n1 (pseq n2 (n1 + n2 + 1)) where n1 = nfib (n-1) n2 = nfib (n-2) -}
nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = nfib (n-1) + nfib (n-2)
main = do putStrLn $ show $ nfib 39
=============
[michael@hostname ~]$ ghc --make -threaded nfib.hs [1 of 1] Compiling Main ( nfib.hs, nfib.o ) Linking nfib ... [michael@hostname ~]$ ./nfib +RTS -N3 204668309 [michael@hostname ~]$ ghc --make nfib.hs [1 of 1] Compiling Main ( nfib.hs, nfib.o ) Linking nfib ... [michael@hostname ~]$ ./nfib 102334155 [michael@hostname ~]$
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Oops! Guess I'm going to have to refine my searching techniques. Thanks, Simon.
Michael
--- On Fri, 5/27/11, Simon Marlow
Fair question. I copied the parallel version from:
http://www.haskell.org/ghc/docs/6.6/html/users_guide/lang-parallel.html http://www.haskell.org/ghc/docs/6.6/html/users_guide/lang-parallel.html
That is the User Guide for GHC 6.6, incidentally. If you're using a later version of GHC (highly recommended especially for parallel stuff), then you should look at the docs for your version. Cheers, Simon
http://www.haskell.org/ghc/docs/6.6/html/users_guide/lang-parallel.htmlbut pulled the non-parallel version from a text.
Michael
--- On *Thu, 5/26/11, David Virebayre /
/* wrote: From: David Virebayre
Subject: Re: [Haskell-cafe] Parallel compilation and execution? To: "michael rice" Cc: haskell-cafe@haskell.org, "Daniel Fischer" Date: Thursday, May 26, 2011, 8:56 AM 2011/5/26 michael rice
> Thank, Daniel
Multiple threads are in evidence in my system monitor, but I wonder why I'm getting two different answers, one twice the other. The first is the parallel solution and the second is the non.
Why do you add n1+n2+1 in the parallel program, but only n1+n2 in the non-parallel one ?
Michael
===========
{- import Control.Parallel
nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = par n1 (pseq n2 (n1 + n2 + 1)) where n1 = nfib (n-1) n2 = nfib (n-2) -}
nfib :: Int -> Int nfib n | n <= 1 = 1 | otherwise = nfib (n-1) + nfib (n-2)
main = do putStrLn $ show $ nfib 39
=============
[michael@hostname ~]$ ghc --make -threaded nfib.hs [1 of 1] Compiling Main ( nfib.hs, nfib.o ) Linking nfib ... [michael@hostname ~]$ ./nfib +RTS -N3 204668309 [michael@hostname ~]$ ghc --make nfib.hs [1 of 1] Compiling Main ( nfib.hs, nfib.o ) Linking nfib ... [michael@hostname ~]$ ./nfib 102334155 [michael@hostname ~]$
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

From: michael rice, Thursday, May 26, 2011 Subject: Re: [Haskell-cafe] Parallel compilation and execution?
Thank, Daniel
Multiple threads are in evidence in my system monitor, but I wonder why I'm getting two different answers, one twice the other. The first is the parallel solution and the second is the non.
Not exactly twice - (2n-1). What you get from counting all nodes in a binary tree (of function calls), compared to counting just the leaves. A program using only pure code, par, and pseq should be deterministic, so if it gets different value by building with and without threaded, changing the number of threads, or just running again, that's a bug in GHC (If it runs out of memory sometimes and not other times, that's not technically a bug, but still interesting). Replacing par with the second argument should also give an equivalent program. pseq isn't really parallel at all, but if you'd like to remove it, then replacing it with seq or just the second argument might change strictness and evaluation order, but shouldn't change the result. Brandon.
participants (6)
-
Alex Mason
-
Brandon Moore
-
Daniel Fischer
-
David Virebayre
-
michael rice
-
Simon Marlow