views:

217

answers:

2

How is this code:

parfib :: Int -> Int
parfib 0 = 1
parfib 1 = 1
parfib n = nf2 `par` (nf1 `par` (nf1+nf2+1))
           where nf1 = parfib (n-1)
                 nf2 = parfib (n-2)

Better than this:

parfib :: Int -> Int
parfib 0 = 1
parfib 1 = 1
parfib n = nf2 `par` (nf1 `seq` (nf1+nf2+1))
           where nf1 = parfib (n-1)
                 nf2 = parfib (n-2)

I don't get the explanations I've found online that say "In order to guarantee that the main expression is evaluated in the right order (i.e. without blocking the main task on the child task) the seq annotation is used".

Why is seq used? I know it forces the interpreter to evaluate parfib (n-1) first but why is it necessary?

When executing the second program, won't the interpeter spark a new process to evaluate nf2, while evaluating nf1 of the nf1+nf2+1 expression in parallel? What is the need to tell it to specify that it should start with nf1?

+4  A: 

It doesn't make much sense to evaluate nf1 in parallel to nf1+... since the latter depends on nf1, so all it would do is block on the spark of nf1. Using seq it will only try to use nf1 once you know it has been evaluated.

nominolo
A: 

it could be because we want to minimize the number of sparks from my understanding the two vesrsion will produce the same result

but with the first option you will be sparking two additional process (nf1, nf2). But when we use seq we just spark only one additionnal process ( nf1).

Johnny Blaze