<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;">Dear Dr. Simon.<br>I believe that I oversimplified the benchmark. However, since the suggestions improved my program a lot, I am sending you a more realistic version. Here are my comments on the link you have sent me:<br><br>1 --- The functional approach does not work for the real stuff, because I use random processes to access the array. I am sending you a more realistic program in the next email.<br><br>2 --- Although my previous example works with unboxed arrays, what I am really storing are Trees, that represent electronic circuits.<br><br>3 --- I would rather not use unsafeRead and unsafeWrite. I don't use them in Clean, and I think I should not use them in Haskell.<br><br>Here is the first program, where I replaced Double by a Tree (Windows). I will explain why I did this in a separate email, to prevent confusion. Anyway, now Haskell is 23 times slower
 than Clean, as you can check from my numbers, or repeating the benchmark. BTW, I tried to use unsafeRead, and unsafeWrite, but I got a segmentation fault when I tried to run the program.<br><br>/* Clean version<br>C:\Clean 2.2\geneticprog\bench&gt;population.exe<br>280000000<br>Execution: 0.07&nbsp; Garbage collection: 0.18&nbsp; Total: 0.26<br><br>C:\Clean 2.2\geneticprog\bench&gt;population.exe<br>280000000<br>Execution: 0.07&nbsp; Garbage collection: 0.17&nbsp; Total: 0.25<br>*/<br>module population<br>import StdEnv<br><br>:: Op = AND | OR | NOT;<br>:: Tree= L Real | T Op [Tree];<br><br>fn i a acc | i&lt;1 = acc<br>fn i a=:{[i]=b} acc<br>&nbsp; # (L n)= b<br>&nbsp; # a= {a&amp;[i]= L (n+3.0)}<br>&nbsp; # (c, a)= a![i]<br>&nbsp; # (L x)= c<br>&nbsp; = fn (i-1) a (x+acc)<br><br>Start= fn 2000000 vt 0.0<br>where<br>&nbsp;&nbsp; vt:: .{Tree}<br>&nbsp;&nbsp; vt = createArray 2000001 (L 137.0)<br><br><br>{-# Haskell version #-}<br>{-# OPTIONS -fvia-C
 -optc-O3 -fexcess-precision -optc-msse3 #-}<br><br>import Control.Monad.ST<br>import Data.Array.ST<br>import Data.Array.Base<br><br>data Op = AND | OR | NOT;<br>data Tree= L Double | T Op [Tree]<br><br>main = print $ runST<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (do arr &lt;- newArray (1,2000000)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (L 137.0) :: ST s<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (STArray s<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Int
 Tree)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; go&nbsp; arr 2000000 0.0 )<br><br>go ::&nbsp; STArray s Int Tree -&gt; Int -&gt; Double -&gt; ST s Double<br>go !a i !acc<br>&nbsp; | i &lt; 1 = return acc<br>&nbsp; | otherwise=do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b &lt;- readArray a i<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writeArray a i (setDouble ((getDouble b)+3.0))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c &lt;- readArray a i<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; go&nbsp; a (i-1) (acc+ (getDouble c))<br><br>getDouble (L r)= r<br>getDouble _ = 0.0<br><br>setDouble r= L r<br><br>{-# D:\Programs\ghc-programs\bench&gt;ghc -O2 --make \<br>&nbsp; bingo.hs -fvia-C -optc-O3 -optc-msse3 -o
 bingo.exe<br><br>D:\ghc-programs\bench&gt;bingo.exe +RTS -sstderr -K32000000<br>bingo.exe +RTS -sstderr -K32000000<br>2.8e8<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 72,392,664 bytes allocated in the heap<br>&nbsp;&nbsp;&nbsp;&nbsp; 118,966,296 bytes copied during GC<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 37,490,648 bytes maximum residency (4 sample(s))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 416,176 bytes maximum slop<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 66 MB total memory in use (1 MB lost due to fragmentation)<br><br>&nbsp; Generation 0:&nbsp;&nbsp; 119 collections,&nbsp;&nbsp;&nbsp;&nbsp; 0 parallel,&nbsp; 1.42s,&nbsp; 1.42s elapsed<br>&nbsp; Generation 1:&nbsp;&nbsp;&nbsp;&nbsp; 4 collections,&nbsp;&nbsp;&nbsp;&nbsp; 0 parallel,&nbsp; 0.14s,&nbsp; 0.16s elapsed<br><br>&nbsp; INIT&nbsp; time&nbsp;&nbsp;&nbsp; 0.03s&nbsp; (&nbsp; 0.00s elapsed)<br>&nbsp; MUT&nbsp;&nbsp; time&nbsp;&nbsp;&nbsp; 0.06s&nbsp;
 (&nbsp; 0.06s elapsed)<br>&nbsp; GC&nbsp;&nbsp;&nbsp; time&nbsp;&nbsp;&nbsp; 1.56s&nbsp; (&nbsp; 1.58s elapsed)<br>&nbsp; EXIT&nbsp; time&nbsp;&nbsp;&nbsp; 0.00s&nbsp; (&nbsp; 0.02s elapsed)<br>&nbsp; Total time&nbsp;&nbsp;&nbsp; 1.66s&nbsp; (&nbsp; 1.64s elapsed)<br><br>&nbsp; %GC time&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 94.3%&nbsp; (96.2% elapsed)<br><br>&nbsp; Alloc rate&nbsp;&nbsp;&nbsp; 772,188,416 bytes per MUT second<br><br>&nbsp; Productivity&nbsp;&nbsp; 3.8% of total user, 3.8% of total elapsed<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>
      <p class="MsoNormal"> </p>

  <tbody><tr>

    <td style="padding: 0.75pt;">

    <div class="MsoNormal" style="text-align: center;" align="center"><font face="Times New Roman" size="3"><span style="font-size: 12pt;">

    <hr align="center" size="1" width="100%">

    </span></font></div>

 

      <p class="MsoNormal"><font face="Times New Roman" size="3"><span style="font-size: 12pt;"><img id="_x0000_i1026" src="http://us.i1.yimg.com/us.yimg.com/i/ca/iotg_search.jpg" align="absbottom" border="0" height="25" hspace="4" width="25"><a href="http://ca.toolbar.yahoo.com/" target="_new"><b><span style="font-weight: bold;" lang="NO-BOK">Yahoo! 
        Canada Toolbar :</span></b><span lang="NO-BOK"> Search from anywhere on 
        the web and bookmark your favourite sites. Download it now! </span></a> 
        </span></font><span lang="NO-BOK"><o:p></o:p></span></p>