<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;">Hi, Simon.<br><br>I ported the array benchmark to a slower machine, in order to detect smaller variations in speed. Clean compiler does not show huge differences in speed when one switches from boxed to unboxed arrays, or from lazy to strict arrays. As you can see below, adding unboxed annotation, or strictness annotation does not change performance noticeably. This is a feature that I like in Clean, and I would like to see in Haskell. Correct programs are almost equally fast. Therefore, the programmer does not need to worry about boxed, unboxed, strict or lazy applications. What I miss in Clean is an interpreter, like GHCi. I am writing a somewhat large genetic programming system to&nbsp; diagnostic electric installations, and electronic circuits.&nbsp; I mean, I am working for people who are writing the programs and designing the circuits. The programs are
 working in Lisp and Scheme (SBCL and Gambit). The Clean version is almost functional. I am struggling with the Haskell version. I will write a private letter to you explaining how the Clean program works. I wonder whether you could give me some hints on how to port it to Haskell. Since Haskell has an interpreter, I think that it could be used to test the generated applications, and calculate the fitness function.<br><br>/* BOXED LAZY<br>D:\Clean 2.2\geneticprog\bench&gt;boxedlazy<br>280000000<br>Execution: 0.04&nbsp; Garbage collection: 0.17&nbsp; Total: 0.21<br><br>D:\Clean 2.2\geneticprog\bench&gt;boxedlazy<br>280000000<br>Execution: 0.06&nbsp; Garbage collection: 0.17&nbsp; Total: 0.23<br><br>D:\Clean 2.2\geneticprog\bench&gt;boxedlazy<br>280000000<br>Execution: 0.04&nbsp; Garbage collection: 0.17&nbsp; Total: 0.21<br>*/<br>module boxedlazy<br>import StdEnv<br><br>fn i a acc | i&lt;1 = acc<br>fn i a=:{[i]=b} acc<br>&nbsp;&nbsp; # a= {a&amp;[i]=
 b+3.0}<br>&nbsp;&nbsp; # (c, a)= a![i]<br>&nbsp;&nbsp; = fn (i-1) a (c+acc)<br><br>Start= fn 2000000 vt 0.0<br>&nbsp;where<br>&nbsp;&nbsp;&nbsp; vt:: .{Real}<br>&nbsp;&nbsp;&nbsp; vt = createArray 2000001 137.0 <br>&nbsp;&nbsp;&nbsp; <br><br>module arrays<br>import StdEnv<br><br>fn i a acc | i&lt;1 = acc<br>fn i a=:{[i]=b} acc<br>&nbsp;&nbsp; # a= {a&amp;[i]= b+3.0}<br>&nbsp;&nbsp; # (c, a)= a![i]<br>&nbsp;&nbsp; = fn (i-1) a (c+acc)<br><br>Start= fn 2000000 vt 0.0<br>&nbsp;where<br>&nbsp;&nbsp;&nbsp; vt:: .{#Real}<br>&nbsp;&nbsp;&nbsp; vt = createArray 2000001 137.0<br><br>/* unboxedlazy<br>D:\Clean 2.2\geneticprog\bench&gt;unboxedlazy.exe<br>280000000<br>Execution: 0.03&nbsp; Garbage collection: 0.00&nbsp; Total: 0.03<br><br>D:\Clean 2.2\geneticprog\bench&gt;unboxedlazy.exe<br>280000000<br>Execution: 0.04&nbsp; Garbage collection: 0.00&nbsp; Total: 0.04<br><br>D:\Clean 2.2\geneticprog\bench&gt;unboxedlazy.exe<br>280000000<br>Execution: 0.03&nbsp;
 Garbage collection: 0.00&nbsp; Total: 0.03<br>*/<br>module unboxedlazy<br>import StdEnv<br><br>fn i a acc | i&lt;1 = acc<br>fn i a=:{[i]=b} acc<br>&nbsp;&nbsp; # a= {a&amp;[i]= b+3.0}<br>&nbsp;&nbsp; # (c, a)= a![i]<br>&nbsp;&nbsp; = fn (i-1) a (c+acc)<br><br>Start= fn 2000000 vt 0.0<br>&nbsp;where<br>&nbsp;&nbsp;&nbsp; vt:: .{#Real}<br>&nbsp;&nbsp;&nbsp; vt = createArray 2000001 137.0<br><br>/* unboxedstrict<br>D:\Clean 2.2\geneticprog\bench&gt;unboxedstrict.exe<br>280000000<br>Execution: 0.03&nbsp; Garbage collection: 0.00&nbsp; Total: 0.03<br><br>D:\Clean 2.2\geneticprog\bench&gt;unboxedstrict.exe<br>280000000<br>Execution: 0.04&nbsp; Garbage collection: 0.00&nbsp; Total: 0.04<br><br>D:\Clean 2.2\geneticprog\bench&gt;unboxedstrict.exe<br>280000000<br>Execution: 0.04&nbsp; Garbage collection: 0.00&nbsp; Total: 0.04<br><br>*/<br>module unboxedstrict<br>import StdEnv<br><br>fn i a acc | i&lt;1 = acc<br>fn i a=:{[i]=b} acc<br>&nbsp;&nbsp; # a=
 {a&amp;[i]= b+3.0}<br>&nbsp;&nbsp; # (c, a)= a![i]<br>&nbsp;&nbsp; = fn (i-1) a (c+acc)<br><br>Start= fn 2000000 vt 0.0<br>&nbsp;where<br>&nbsp;&nbsp;&nbsp; vt:: !.{#!Real}<br>&nbsp;&nbsp;&nbsp; vt = createArray 2000001 137.0<br><br><br><br>--- On <b>Thu, 10/15/09, Simon Peyton-Jones <i>&lt;simonpj@microsoft.com&gt;</i></b> wrote:<br><blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px;"><br>From: Simon Peyton-Jones &lt;simonpj@microsoft.com&gt;<br>Subject: RE: [Fwd: Re: [clean-list] Clean versus Haskell]<br>To: "Adrian Hey" &lt;ahey@iee.org&gt;, "clean-list@science.ru.nl" &lt;clean-list@science.ru.nl&gt;<br>Received: Thursday, October 15, 2009, 1:22 AM<br><br><div class="plainMail">I submitted Philippos as a performance bug to GHC's trac, here:<br>&nbsp;&nbsp;&nbsp; <a href="http://hackage.haskell.org/trac/ghc/ticket/3586" target="_blank">http://hackage.haskell.org/trac/ghc/ticket/3586</a><br><br>If you follow
 the link you'll see lots of commentary, including a version that generates code twice as fast as Clean's, and is purely functional.<br><br>That said, I think it's v bad that a straightforward program runs so slowly, and it's certainly true that this is an area we could pay more attention to.&nbsp; (Trouble is, there are so many such areas!)<br><br>Meanwhile, I'm curious: are the arrays in Philippos's program strict?&nbsp; Or lazy?&nbsp; If strict, that's a pretty big difference.&nbsp; (The "STU" arrays mentioned in the above link are strict and unboxed; that's what the "U" means.)<br><br>Simon<br><br>| -----Original Message-----<br>| From: <a ymailto="mailto:clean-list-bounces@science.ru.nl" href="/mc/compose?to=clean-list-bounces@science.ru.nl">clean-list-bounces@science.ru.nl</a> [mailto:<a ymailto="mailto:clean-list-bounces@science.ru.nl" href="/mc/compose?to=clean-list-bounces@science.ru.nl">clean-list-bounces@science.ru.nl</a>] On<br>| Behalf Of
 Adrian Hey<br>| Sent: 15 October 2009 07:33<br>| To: <a ymailto="mailto:clean-list@science.ru.nl" href="/mc/compose?to=clean-list@science.ru.nl">clean-list@science.ru.nl</a><br>| Subject: [Fwd: Re: [clean-list] Clean versus Haskell]<br>| <br>| <br>| -------- Original Message --------<br>| Subject: Re: [clean-list] Clean versus Haskell<br>| Date: Thu, 15 Oct 2009 06:41:20 +0100<br>| From: Adrian Hey &lt;<a ymailto="mailto:ahey@iee.org" href="/mc/compose?to=ahey@iee.org">ahey@iee.org</a>&gt;<br>| To: Philippos Apolinarius &lt;<a ymailto="mailto:phi500ac@yahoo.ca" href="/mc/compose?to=phi500ac@yahoo.ca">phi500ac@yahoo.ca</a>&gt;<br>| References: &lt;<a ymailto="mailto:8400.82204.qm@web58803.mail.re1.yahoo.com" href="/mc/compose?to=8400.82204.qm@web58803.mail.re1.yahoo.com">8400.82204.qm@web58803.mail.re1.yahoo.com</a>&gt;<br>| <br>| Hello Philippos,<br>| <br>| GHC has a long standing performance bug for garbage collection and<br>| mutable arrays:<br>|
 <br>| <a href="http://hackage.haskell.org/trac/ghc/ticket/650" target="_blank">http://hackage.haskell.org/trac/ghc/ticket/650</a><br>| <br>| For some reason they haven't (can't?) fixed it. I guess the<br>| authors of Haskell/ghc shootout entries are aware of this so don't<br>| use native mutable arrays in their entries (at least not those that<br>| show haskell/ghc to be "fast" :-)<br>| <br>| Regards<br>| --<br>| Adrian Hey<br>| <br>| Philippos Apolinarius wrote:<br>| &gt; I wrote a very simple program to check whether Haskell improved its array<br>| processing libraries or not. Here is how to compile and run the program arr.hs in<br>| Haskell (I have used the GHC compiler):<br>| &gt;<br>| &gt;&gt; ghc -O arr.hs -o arr.exe<br>| &gt;<br>| &gt; $ time arr.exe +RTS -K32000000<br>| &gt; 2.8e8<br>| &gt;<br>| &gt; real&nbsp; &nbsp; 0m3.938s<br>| &gt; user&nbsp; &nbsp; 0m0.031s<br>| &gt; sys&nbsp; &nbsp;&nbsp;&nbsp;0m0.000s<br>| &gt;<br>| &gt; The same program
 in Clean:<br>| &gt; C:\Clean 2.2\exemplos\console&gt;arraytest.exe<br>| &gt; 280000000<br>| &gt; Execution: 0.01&nbsp; Garbage collection: 0.01&nbsp; Total: 0.03<br>| &gt;<br>| &gt; C:\Clean 2.2\exemplos\console&gt;arraytest.exe<br>| &gt; 280000000<br>| &gt; Execution: 0.01&nbsp; Garbage collection: 0.01&nbsp; Total: 0.03<br>| &gt;<br>| &gt; This means that Clean is 390 times faster than Haskell in this particular problem.<br>| These results makes me worder whether Haskell is safer than Clean. It turns out that<br>| Haskell checks index out of range at runtime, exactly like Clean. Larger problems<br>| make the difference between Clean and Haskell even worse. For instance, neural<br>| networks like the one described in Schmidtt et al. run 400 times faster in Clean.<br>| &gt;<br>| &gt; Haskell seems to be slow, and not safe. For instance, GHC compiler does not at a<br>| program trying to write into a closed handle.<br>| &gt;<br>| &gt; module Main
 where<br>| &gt;&nbsp; import System( getArgs )<br>| &gt;&nbsp; import IO<br>| &gt;<br>| &gt;&nbsp; main = do<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;args &lt;- getArgs<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;if (length args /= 2)<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;then putStr "Usage: f1a f2a &lt;n&gt;"<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;else (do<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;fromHandle &lt;- openFile (head args)&nbsp; ReadMode<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;contents&nbsp;&nbsp;&nbsp;&lt;- hGetContents fromHandle<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;toHandle &lt;- openFile (head (tail args)) WriteMode<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;hClose toHandle&nbsp; -- Comment this line<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp;hPutStr toHandle contents<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;hClose toHandle<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;putStr "Done.")<br>| &gt;<br>| &gt; The Clean equivalent program is somewhat smaller. In my opinion it is easier to<br>| understand. What is more important, Clean compiler balks at closed handles.<br>| &gt;<br>| &gt; module cleancopy<br>| &gt; import StdEnv, ArgEnv<br>| &gt;<br>| &gt; Start w<br>| &gt;&nbsp;&nbsp;&nbsp;# argv= getCommandLine<br>| &gt;&nbsp;&nbsp;&nbsp;| size argv &lt; 3 = abort "Usage, etc."<br>| &gt;&nbsp;&nbsp;&nbsp;# (ok, f, w)= fopen argv.[1] FReadText w<br>| &gt;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;(contents, f)= freads f 64000<br>| &gt;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;(ok, f, w)= fopen argv.[2] FWriteText w<br>| &gt;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;f= fwrites contents f<br>| &gt;&nbsp;&nbsp;&nbsp;= fclose f w<br>| &gt;<br>| &gt; Below you will
 find the array examples. You can check that Clean is really much<br>| faster than Haskell. I wonder why the Benchmarks Game site does not report such a<br>| large difference between Haskell and Clean performances. I believe that people who<br>| wrote Haskell benchmarks for the Benchmarks Game site cheated in using foreign<br>| pointers to access arrays.<br>| &gt;<br>| &gt; -- arr.hs<br>| &gt; import Control.Monad.ST<br>| &gt; import Data.Array.ST<br>| &gt; main = print $ runST<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;(do arr &lt;- newArray (1,2000000)<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;137.0 :: ST s<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;(STArray s<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
 &nbsp;&nbsp;&nbsp;Int Double)<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;a &lt;- readArray arr 1<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;b &lt;- readArray arr 1<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;fn 2000000 arr 0.0 )<br>| &gt;<br>| &gt;<br>| &gt; fn i a acc | i &lt; 1 = do (return acc)<br>| &gt; fn i a acc= do<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b &lt;- readArray a i<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writeArray a i (b+3.0)<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c &lt;- readArray a i<br>| &gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fn (i-1) a (acc+c)<br>| &gt;<br>| &gt; //Clean version<br>| &gt; module arraytest<br>| &gt; import StdEnv<br>| &gt; fn i a acc | i&lt;1 = acc<br>| &gt; fn i a=:{[i]=b} acc<br>| &gt;&nbsp;&nbsp;&nbsp;# a= {a&amp;[i]= b+3.0}<br>| &gt;&nbsp;&nbsp;&nbsp;# (c, a)=
 a![i]<br>| &gt;&nbsp;&nbsp;&nbsp;= fn (i-1) a (c+acc)<br>| &gt;<br>| &gt; Start= fn 2000000 vt 0.0<br>| &gt; where<br>| &gt;&nbsp; &nbsp; vt:: .{#Real}<br>| &gt;&nbsp; &nbsp; vt = createArray 2000001 137.0<br><br>_______________________________________________<br>clean-list mailing list<br><a ymailto="mailto:clean-list@science.ru.nl" href="/mc/compose?to=clean-list@science.ru.nl">clean-list@science.ru.nl</a><br><a href="http://mailman.science.ru.nl/mailman/listinfo/clean-list" target="_blank">http://mailman.science.ru.nl/mailman/listinfo/clean-list</a><br></div></blockquote></td></tr></table><br>
      <hr size=1>Be smarter than spam. See how smart SpamGuard is at giving junk email the boot with the <a href="http://ca.promos.yahoo.com/newmail/overview2/"><b>All-new Yahoo! Mail </b></a>