
I've uploaded my CMonad package to Hackage. It allows you to write Haskell code in a C style. Unfortunately, GHC lacks certain optimizations to make efficient code when using CMonad, so instead of C speed you get low speed. Example: Computing some Fibonacci numbers: fib = do { a <- arrayU[40]; i <- auto 0; a[0] =: 1; a[1] =: 1; for (i =: 2, (i :: EIO Int) < 40, i += 1) $ do { a[i] =: a[i-1] + a[i-2]; }; retrn (a[39]); } Example: Copying stdin to stdout: cat = do { c <- auto 0; while ((c =: getchar()) >= 0) $ do { putchar(c); }; return (); } -- Lennart

Well, yes and no. GHC actually does a decent job when given very
imperative code with references and mutable arrays.
Now the type I use to wrap the references to get type safe l-values
and r-values makes it tricker, and ghc lacks a crucial optimization
for specialization of constructor returns.
With that in place I think the code could be quite performant.
-- Lennart
On Sun, Mar 29, 2009 at 3:13 PM, Jason Dusek
2009/03/29 Lennart Augustsson
: ...GHC lacks certain optimizations to make efficient code when using CMonad, so instead of C speed you get low speed.
Is this surprising to anyone?
-- Jason Dusek

Nested constructed product returns? Or constructed sums? lennart:
Well, yes and no. GHC actually does a decent job when given very imperative code with references and mutable arrays. Now the type I use to wrap the references to get type safe l-values and r-values makes it tricker, and ghc lacks a crucial optimization for specialization of constructor returns. With that in place I think the code could be quite performant.

When I looked at it a year ago or so, it was a return of one
constructor in a sum.
Looking at core, you can see several places where a function is called
and that function always returns the same constructor, so the case
analysis of the return value is not needed; it should be returned as
an unboxed tuple instead
I'll see if I can get a simple example to illustrate the problem.
I talked to Simon PJ about it and he thought an analysis and
transformation for such a thing would be a good idea, but someone has
to do the work, of course.
Another unrelated problem, I think, is that ghc needs to promote
in-memory variables to registers when possible.
Perhaps the new code generator has such a transformation?
-- Lennart
On Mon, Mar 30, 2009 at 3:28 AM, Don Stewart
Nested constructed product returns? Or constructed sums?
lennart:
Well, yes and no. GHC actually does a decent job when given very imperative code with references and mutable arrays. Now the type I use to wrap the references to get type safe l-values and r-values makes it tricker, and ghc lacks a crucial optimization for specialization of constructor returns. With that in place I think the code could be quite performant.

Lennart, | Unfortunately, GHC lacks certain optimizations to make efficient code | when using CMonad, | so instead of C speed you get low speed. ... | When I looked at it a year ago or so, it was a return of one | constructor in a sum. | Looking at core, you can see several places where a function is called | and that function always returns the same constructor, so the case | analysis of the return value is not needed; it should be returned as | an unboxed tuple instead | I'll see if I can get a simple example to illustrate the problem. That would be very helpful, thanks. Having a Trac ticket with a small reproducible test case, and a pointer to a larger example that illustrates its importance, would be great. Indeed, it is pervasive, or can you try the effect of performing the transformation by hand, and seeing if it makes a difference? That doesn't guarantee that I, or anyone else, will get to it, but it makes it much much more likely! Simon

| When I looked at it a year ago or so, it was a return of one | constructor in a sum. | Looking at core, you can see several places where a function is called | and that function always returns the same constructor, so the case | analysis of the return value is not needed; it should be returned as | an unboxed tuple instead | I'll see if I can get a simple example to illustrate the problem.
That would be very helpful, thanks. Having a Trac ticket with a small reproducible test case, and a pointer to a larger example that illustrates its importance, would be great. Indeed, it is pervasive, or can you try the effect of performing the transformation by hand, and seeing if it makes a difference?
That doesn't guarantee that I, or anyone else, will get to it, but it makes it much much more likely!
And in the meantime, it documents a possible performance trap for others who might not be able to track down the cause, or even notice that they are shooting themselves in the foot. Claus

Duncan and I have thought about this too, exactly as you describe. (Just !x) => (# tag#, x# #) -- Don lennart:
When I looked at it a year ago or so, it was a return of one constructor in a sum. Looking at core, you can see several places where a function is called and that function always returns the same constructor, so the case analysis of the return value is not needed; it should be returned as an unboxed tuple instead I'll see if I can get a simple example to illustrate the problem.
I talked to Simon PJ about it and he thought an analysis and transformation for such a thing would be a good idea, but someone has to do the work, of course.
Another unrelated problem, I think, is that ghc needs to promote in-memory variables to registers when possible. Perhaps the new code generator has such a transformation?
-- Lennart
On Mon, Mar 30, 2009 at 3:28 AM, Don Stewart
wrote: Nested constructed product returns? Or constructed sums?
lennart:
Well, yes and no. GHC actually does a decent job when given very imperative code with references and mutable arrays. Now the type I use to wrap the references to get type safe l-values and r-values makes it tricker, and ghc lacks a crucial optimization for specialization of constructor returns. With that in place I think the code could be quite performant.

2009/3/30 Don Stewart
Duncan and I have thought about this too, exactly as you describe.
(Just !x) => (# tag#, x# #)
It would be nice to generalize this to arbitrary sum types, but doing so plays hell with the type checker - I think the most straightforward way would be to extend Core with a type-level case statement on tag values similar to \Pi\Sigma. BTW you can manually apply the worker/wrapper transform to arrayU to realise this optimisation in todays GHC. However, I couldn't get GHC to inline the definitions of (-) etc from Ops though - seems to be an issue with it throwing away INLINE annotations on the appropriate dictionary members of Num. If both of these things were fixed you would /still/ get bad code, because mapM (used in arrayU) does not produce a fusible list, so the resulting program still builds the lists that masquerade as array indexes and then folds over them. Disappointing, but this can also be solved, as long as you apply the monadic stream technology from Roman's vector package. Apologies for the brevity of these notes, but perhaps they make some of the issues clearer. GHC really should be doing much better here :-( Cheers, Max

Max,
If you want to look at a simple example, look at the Inf.hs example
included in the package.
It's very simple, and ghc generates fantastically bad code for it.
It would be great if you could nail down why it's so amazingly unoptimal.
Even with everything inlined and no overloading left, ghc seems to
ignore the INLINE directives and use dictionaries left and right.
-- Lennart
On Mon, Mar 30, 2009 at 11:20 PM, Max Bolingbroke
2009/3/30 Don Stewart
: Duncan and I have thought about this too, exactly as you describe.
(Just !x) => (# tag#, x# #)
It would be nice to generalize this to arbitrary sum types, but doing so plays hell with the type checker - I think the most straightforward way would be to extend Core with a type-level case statement on tag values similar to \Pi\Sigma.
BTW you can manually apply the worker/wrapper transform to arrayU to realise this optimisation in todays GHC. However, I couldn't get GHC to inline the definitions of (-) etc from Ops though - seems to be an issue with it throwing away INLINE annotations on the appropriate dictionary members of Num.
If both of these things were fixed you would /still/ get bad code, because mapM (used in arrayU) does not produce a fusible list, so the resulting program still builds the lists that masquerade as array indexes and then folds over them. Disappointing, but this can also be solved, as long as you apply the monadic stream technology from Roman's vector package.
Apologies for the brevity of these notes, but perhaps they make some of the issues clearer. GHC really should be doing much better here :-(
Cheers, Max

On Sunday 29 March 2009, Lennart Augustsson wrote:
I've uploaded my CMonad package to Hackage. It allows you to write Haskell code in a C style.
Now I've heard that Haskell makes a fine (if not the finest) imperative language, but isn't this taking that thought a bit too far ;)
Unfortunately, GHC lacks certain optimizations to make efficient code when using CMonad, so instead of C speed you get low speed.
I mean as a proof-of-concept this is cool, but if your primary concern is performance then I think you're barking up the wrong tree with this. Cheers! Marcin Kosiba

If my primary concern is speed I'll write in C.
2009/3/29 Marcin Kosiba
On Sunday 29 March 2009, Lennart Augustsson wrote:
I've uploaded my CMonad package to Hackage. It allows you to write Haskell code in a C style.
Now I've heard that Haskell makes a fine (if not the finest) imperative language, but isn't this taking that thought a bit too far ;)
Unfortunately, GHC lacks certain optimizations to make efficient code when using CMonad, so instead of C speed you get low speed.
I mean as a proof-of-concept this is cool, but if your primary concern is performance then I think you're barking up the wrong tree with this.
Cheers! Marcin Kosiba
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Sun, Mar 29, 2009 at 11:16 AM, Lennart Augustsson
I've uploaded my CMonad package to Hackage. It allows you to write Haskell code in a C style.
Nice! A nice addition would be to output a C AST from language-c: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/language-c regards, Bas

On Mar 30, 2009, at 3:30 PM, Bas van Dijk wrote:
On Sun, Mar 29, 2009 at 11:16 AM, Lennart Augustsson
wrote: I've uploaded my CMonad package to Hackage. It allows you to write Haskell code in a C style.
Nice!
A nice addition would be to output a C AST from language-c:
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/language-c
regards,
Bas
And compile and link that back into your program! Nice toys indeed. Lennart, what is the next language DSL you are going to build? Prolog? XSLT? -- Sebastiaan

Declarative 3D scene construction? ;-)
+1
On Mon, Mar 30, 2009 at 3:16 PM, Andrew Coppin
Sebastiaan Visser wrote:
Lennart, what is the next language DSL you are going to build? Prolog? XSLT?
Declarative 3D scene construction? ;-)
(What? I can wish, can't I?)
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- /jve

John Van Enk wrote:
Declarative 3D scene construction? ;-)
+1 On Mon, Mar 30, 2009 at 3:16 PM, Andrew Coppin
mailto:andrewcoppin@btinternet.com> wrote: Sebastiaan Visser wrote:
Lennart, what is the next language DSL you are going to build? Prolog? XSLT?
Declarative 3D scene construction? ;-)
(What? I can wish, can't I?)
I was going to write an email about this anyway, so... POV-Ray already has a very nice scene description language: http://www.haskell.org/haskellwiki/POV-Ray_SDL_project Originally it was just for *describing* scenes. However, it slowly mutated and became a Turing-complete scene *construction* language. Unfortunately, it does this using macro-style textual substitution, so it's slow as hell, and maddening to debug. Obviously Haskell is a far superior _programming language_. No need to elaborate further on that. It simply remains to come up with a good set of abstractions and a convinient syntax for a scene description DSL and you're golden. (The question then becomes, "what do you do with this description?" Obvious answers include pretty printing it as POV-Ray SDL or writing your own ray tracer and feeding it to that.) Initially I was focusing on taking POV-Ray's existing SDL and simply removing the macros and putting in something more elegant (i.e., Haskell). But now I'm thinking it might be better to design an entire new language from scratch instead. POV-Ray's SDL has a few limitations: - Messy stuff that exists only for backwards compatibility. - Each primitive can be described in only one way. (E.g., a cylinder can only be described by a radius and two endpoints. Not by, say, a center point, a length, and a diammeter.) There is no particular reason for such a limitation to exist. - There is no support for "inspecting" things which have already been constructed. E.g., you can't take an existing object, remove its texturing and replace it. You can only add another texture layer on top. - Given a powerful language like Haskell, you could go crazy and start trying to do parametric moddelling, physical simulations, etc. So there you have it. A typical hobby project: tonnes of ideas, few concrete design plans.

On 30 Mar 2009, at 20:16, Andrew Coppin wrote:
Lennart, what is the next language DSL you are going to build? Prolog? XSLT?
Declarative 3D scene construction? ;-)
The ICFP programming contest in year 2000 was to write a ray tracer for a given declarative 3D scene construction language (CSG - constructive solid geometry). A team from Galois wrote a decent entry in Haskell, which did not win (those were the glory days of O'Caml), but it was placed in the top three. I believe with some careful googling, you should still be able to find a copy of the source code. I'm sure that if someone were to return to the idea now, the DSL for CSG could be improved in many ways, since the original language was simply given in the contest description, and there was no point in altering it. Regards, Malcolm

malcolm.wallace:
On 30 Mar 2009, at 20:16, Andrew Coppin wrote:
Lennart, what is the next language DSL you are going to build? Prolog? XSLT?
Declarative 3D scene construction? ;-)
The ICFP programming contest in year 2000 was to write a ray tracer for a given declarative 3D scene construction language (CSG - constructive solid geometry). A team from Galois wrote a decent entry in Haskell, which did not win (those were the glory days of O'Caml), but it was placed in the top three. I believe with some careful googling, you should still be able to find a copy of the source code.
I'm sure that if someone were to return to the idea now, the DSL for CSG could be improved in many ways, since the original language was simply given in the contest description, and there was no point in altering it.
I believe the Galois 2000 ray tracer is now part of the GHC multicore benchmark suite.

A nice addition would be to output a C AST from language-c: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/language-c And compile and link that back into your program! Nice toys indeed. Lennart, what is the next language DSL you are going to build? Prolog? XSLT? Maybe SQL over HDBC? For exampl:
Sebastiaan Visser wrote: main = do curs <- selectSQL FirstName, LastName, Age from Peoples putStrLn . unlines $ map show curs Where curs :: [(String, String, Int)]

First, BASIC, now C. What's next, Haskell? =)
-Edward Kmett
On Sun, Mar 29, 2009 at 5:16 AM, Lennart Augustsson
I've uploaded my CMonad package to Hackage. It allows you to write Haskell code in a C style. Unfortunately, GHC lacks certain optimizations to make efficient code when using CMonad, so instead of C speed you get low speed.
Example: Computing some Fibonacci numbers: fib = do { a <- arrayU[40]; i <- auto 0; a[0] =: 1; a[1] =: 1; for (i =: 2, (i :: EIO Int) < 40, i += 1) $ do { a[i] =: a[i-1] + a[i-2]; }; retrn (a[39]); }
Example: Copying stdin to stdout: cat = do { c <- auto 0;
while ((c =: getchar()) >= 0) $ do { putchar(c); }; return (); }
-- Lennart _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

I think my brain just exploded. On Mar 30, 2009, at 1:29 PM, Edward Kmett wrote:
First, BASIC, now C. What's next, Haskell? =)
-Edward Kmett
On Sun, Mar 29, 2009 at 5:16 AM, Lennart Augustsson
wrote: I've uploaded my CMonad package to Hackage. It allows you to write Haskell code in a C style. Unfortunately, GHC lacks certain optimizations to make efficient code when using CMonad, so instead of C speed you get low speed.
Example: Computing some Fibonacci numbers: fib = do { a <- arrayU[40]; i <- auto 0; a[0] =: 1; a[1] =: 1; for (i =: 2, (i :: EIO Int) < 40, i += 1) $ do { a[i] =: a[i-1] + a[i-2]; }; retrn (a[39]); }
Example: Copying stdin to stdout: cat = do { c <- auto 0;
while ((c =: getchar()) >= 0) $ do { putchar(c); }; return (); }
-- Lennart _______________________________________________ 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

As it goes, it'd probably be Forth. On 30 Mar 2009, at 21:29, Edward Kmett wrote:
First, BASIC, now C. What's next, Haskell? =)
-Edward Kmett
On Sun, Mar 29, 2009 at 5:16 AM, Lennart Augustsson
wrote: I've uploaded my CMonad package to Hackage. It allows you to write Haskell code in a C style. Unfortunately, GHC lacks certain optimizations to make efficient code when using CMonad, so instead of C speed you get low speed.
Example: Computing some Fibonacci numbers: fib = do { a <- arrayU[40]; i <- auto 0; a[0] =: 1; a[1] =: 1; for (i =: 2, (i :: EIO Int) < 40, i += 1) $ do { a[i] =: a[i-1] + a[i-2]; }; retrn (a[39]); }
Example: Copying stdin to stdout: cat = do { c <- auto 0;
while ((c =: getchar()) >= 0) $ do { putchar(c); }; return (); }
-- Lennart _______________________________________________ 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
participants (16)
-
Alexandr N. Zamaraev
-
Andrew Coppin
-
Bas van Dijk
-
Claus Reinke
-
Don Stewart
-
Edward Kmett
-
Jason Dusek
-
John Van Enk
-
Lennart Augustsson
-
Malcolm Wallace
-
Marcin Kosiba
-
Max Bolingbroke
-
Miguel Mitrofanov
-
Ross Mellgren
-
Sebastiaan Visser
-
Simon Peyton-Jones