Skip to content

Conversation

treeowl
Copy link
Contributor

@treeowl treeowl commented Jun 14, 2018

  • Lift the result to avoid always reducing to WHNF.
  • Rewrite the documentation of rparWith.

Fixes #35

@treeowl
Copy link
Contributor Author

treeowl commented Jun 14, 2018

Now that I understand rparWith better, I think I also understand why some of those RULES were important. But I still think we can do better by using "low-level" rules and letting high-level constructs inline enough. In addition to the evaluation rules

runEval (r0 a) = a
runEval (rpar a) = a
runEval (rseq a) = a

we need

rparWith r0 = r0
rparWith rpar = rpar
rparWith rseq = rpar
rparWith (rparWith strat) = rparWith strat

-- rparWith strat x
-- @
--
-- will spark a thread to perform @strat x@ in parallel. Note
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's not use the terminology "thread" here to avoid confusion. How about "will spark @strat x@".

-- WHNF, while @rparWith strat@ need not.
--
-- > rparWith r0 = r0
-- > rparWith rpar = rpar
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LHS creates two sparks, I'm not sure I'd call them equal. It depends what equality you're using, but as I argued elsewhere the only sensible notions of equality here are ones that care about sparks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rparWith rpar is actually a quite weird thing: it creates a spark, who creates a spark, who evaluates to WHNF.

However one can probably replace that law with rparWith rseq = rpar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does one replace the other? What we probably actually want is some sort of equivalence relation that equates "essentially equivalent" things. rpar x >>= rseq is effectively the same as rseq x, but I don't know how to express that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@simonmar, my intuition suggests that we're never going to find all the relations (Eval is a very large structure), but that we should document some of the more useful ones. It's easy to think you're getting more parallelism than you are when composing things. Speaking of relations,

runEval (m >>= rpar) = runEval m

rpar x >>= \x' -> rpar y >>= f  =  rpar y >>= \y' -> rpar x >>= f
-- when x' is not free in y and y' is not free in x.

@treeowl
Copy link
Contributor Author

treeowl commented Jun 15, 2018 via email


data Lift a = Lift a
#else
rparWith s a = do l <- rpar (s a); return (case l of Done x -> x)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, we can also use the GHC >= 7.2 version here, saving some code dupling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

-- `rseq` in `rparWith`. In particular, we want rparWith r0 = r0, not
-- rparWith r0 = rpar.
rparWith s a = do
l <- rpar r
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates (nearly) always a fizzled spark, because l is immediately pattern matched. A lazy pattern match is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pattern match is lazy (it's in the argument to return). Try your test!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moreover, if you inline everything manually (including the runRW#) you'll end up with the same thing as the old implementation. We just shouldn't do that because inlining the realWorld# is like asking the optimizer to completely mangle our intentions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI, search the bytestring source code for accursedUnutterablePerformIO if you want a more detailed explanation.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I was wrong with my comment.

Borgvall and others added 2 commits June 17, 2018 21:39
It does not pass with the current implementation of `rparWith`.
* Lift the result to avoid always reducing to WHNF.

* Rewrite the documentation of `rparWith`.

Fixes haskell#35
@simonmar simonmar merged commit e7a7d7a into haskell:master Jun 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants