Re: [Haskell-cafe] A first glimps on the {-# NOUPDATE #-} pragma

Hi,
upd_noupd n = let l = myenum' 0 n in last l + length l
This could be rewritten as
upd_noupd n = let l n = myenum' 0 n in last (l n) + length (l n)
Or a special form of let could be introduced to define locally-scoped macros:
upd_noupd n = let# l = myenum' 0 n in last l + length l
What's the strength of the {-# NOUPDATE #-} approach? Regards, Facundo
Date: Wed, 29 Aug 2012 10:20:21 +0200 From: Joachim Breitner
Subject: Re: [Haskell-cafe] A first glimps on the {-# NOUPDATE #-} pragma To: haskell-cafe@haskell.org Message-ID: <1346228421.4271.9.camel@kirk> Content-Type: text/plain; charset="iso-8859-15" Hi,
Am Dienstag, den 28.08.2012, 18:16 -0400 schrieb Carter Schonwald:
On Tuesday, August 28, 2012, Yves Par?s wrote: Monad? Simple strictness anotation is enough in that case:
upd_noupd n = let l = myenum' 0 n h = head l in h `seq` last l + h
darn, I though I changed my examples before posting to:
upd_noupd n = let l = myenum' 0 n in last l + length l
("head" was a bad example because actually due to strictness analysis and worker/wrapper transformation, GHC would yield good code even without "`seq`").
In this case (which is actually the benchmarked case), reordering or strictness annotations do not help.
Greetings and sorry for the confusion, Joachim
-- Dipl.-Math. Dipl.-Inform. Joachim Breitner Wissenschaftlicher Mitarbeiter http://pp.info.uni-karlsruhe.de/~breitner

Hi Facundo, Am Mittwoch, den 29.08.2012, 10:26 -0300 schrieb Facundo Domínguez:
upd_noupd n = let l = myenum' 0 n in last l + length l
This could be rewritten as
upd_noupd n = let l n = myenum' 0 n in last (l n) + length (l n)
Or a special form of let could be introduced to define locally-scoped macros:
upd_noupd n = let# l = myenum' 0 n in last l + length l
What's the strength of the {-# NOUPDATE #-} approach?
it does not require refactoring of the code. There is not always a parameter handy that you can use to prevent sharing, and using () for that sometimes fails due to the full-lazyness-transformation. And a locally-scoped macros would not help in this case: test g n = g (myenum' 0 n) Now you still might want to prevent the long list to be stored, but here it cannot be done just by inlining or macro expansion. Greetings, Joachim -- Dipl.-Math. Dipl.-Inform. Joachim Breitner Wissenschaftlicher Mitarbeiter http://pp.info.uni-karlsruhe.de/~breitner

And of course the biggest reason for this change, is we want GHC to continue
to become "smarter". Remember, Haskell is a high level language. The
original promise, is that the code should be algebraically optimizable by
the compiler itself. Yes, of course many Haskell coders have learned to
deal with the places where Haskell is all to close to the metal. But we
hope that this will not always be the case. The interesting part, may not
be that you can add the pragma yourself, but that in the future, you won't
have to change anything at all.
Tim
---------- Původní zpráva ----------
Od: Joachim Breitner
upd_noupd n = let l = myenum' 0 n in last l + length l
This could be rewritten as
upd_noupd n = let l n = myenum' 0 n in last (l n) + length (l n)
Or a special form of let could be introduced to define locally-scoped macros:
upd_noupd n = let# l = myenum' 0 n in last l + length l
What's the strength of the {-# NOUPDATE #-} approach?
it does not require refactoring of the code. There is not always a parameter handy that you can use to prevent sharing, and using () for that sometimes fails due to the full-lazyness-transformation. And a locally-scoped macros would not help in this case: test g n = g (myenum' 0 n) Now you still might want to prevent the long list to be stored, but here it cannot be done just by inlining or macro expansion. Greetings, Joachim -- Dipl.-Math. Dipl.-Inform. Joachim Breitner Wissenschaftlicher Mitarbeiter http://pp.info.uni-karlsruhe.de/~breitner (http://pp.info.uni-karlsruhe.de/%7Ebreitner)"

On 29 August 2012 15:21, Joachim Breitner
Hi Facundo,
Am Mittwoch, den 29.08.2012, 10:26 -0300 schrieb Facundo Domínguez:
upd_noupd n = let l = myenum' 0 n in last l + length l
This could be rewritten as
upd_noupd n = let l n = myenum' 0 n in last (l n) + length (l n)
Or a special form of let could be introduced to define locally-scoped macros:
upd_noupd n = let# l = myenum' 0 n in last l + length l
What's the strength of the {-# NOUPDATE #-} approach?
it does not require refactoring of the code. There is not always a parameter handy that you can use to prevent sharing, and using () for that sometimes fails due to the full-lazyness-transformation.
And a locally-scoped macros would not help in this case:
test g n = g (myenum' 0 n)
Now you still might want to prevent the long list to be stored, but here it cannot be done just by inlining or macro expansion.
Syntactically, I'd prefer something that looks more like a function. With a pragma it's difficult to see what expression it actually affects. For example, we already have the special functions "lazy" and "inline". Since avoiding updates essentially turns lazy evaluation into call-by-name you could call it "cbn". Perhaps that suggests a different use case, though, so "nonstrict", "unshared", or "nonlazy" might be more self-explanatory. I'd also like to point out that avoiding updates can dramatically improve the kind of speedups my tracing JIT can achieve. In particular, on some benchmarks, it can optimise idiomatic Haskell code to the same level as stream fusion. I can simulate that by avoiding *all* updates (i.e., use call-by-name), but that would break some programs badly. (Technically, that's all legal, but I'm pretty sure it breaks any "tying-the-knot" tricks.)

Hi, Am Mittwoch, den 29.08.2012, 17:16 +0100 schrieb Thomas Schilling:
Syntactically, I'd prefer something that looks more like a function. With a pragma it's difficult to see what expression it actually affects. For example, we already have the special functions "lazy" and "inline". Since avoiding updates essentially turns lazy evaluation into call-by-name you could call it "cbn". Perhaps that suggests a different use case, though, so "nonstrict", "unshared", or "nonlazy" might be more self-explanatory.
thanks for the feedback. I only made it a pragma because it seemed to be simpler at first, but now the branch also supports GHC.Prim.noupdate (better name to be found before it reaches any official GHC branch, if that ever happens).
I'd also like to point out that avoiding updates can dramatically improve the kind of speedups my tracing JIT can achieve. In particular, on some benchmarks, it can optimise idiomatic Haskell code to the same level as stream fusion. I can simulate that by avoiding *all* updates (i.e., use call-by-name), but that would break some programs badly. (Technically, that's all legal, but I'm pretty sure it breaks any "tying-the-knot" tricks.)
If you can make use of my code in Lambdachine I’d be very happy to help fixing bus and to hear about your results (but from a first glance it seems that you are not using that part of GHC in your project, right?). Greetings, Joachim -- Dipl.-Math. Dipl.-Inform. Joachim Breitner Wissenschaftlicher Mitarbeiter http://pp.info.uni-karlsruhe.de/~breitner

On 30 August 2012 09:34, Joachim Breitner
but from a first glance it seems that you are not using that part of GHC in your project, right?
No, I don't think I can make use of your work directly. Lambdachine uses GHC up until the CorePrep phase (the last phase before conversion to STG, I think). I'll probably need a dynamic tagging mechanism to keep track of what's potentially shared. Not sure what the overhead of that will be. / Thomas
participants (4)
-
Facundo Domínguez
-
Joachim Breitner
-
Thomas Schilling
-
timothyhobbs@seznam.cz