Of course I know that the list version is very unfair, but I wanted to see what was the trade off between elegance and speed.<br>Regarding
whether low level programming makes sense or not, I was just curious to
see what are the limits of Haskell. Moreover there is not much
literature on high performance Haskell programming (tricks like
unsafeWrite), at least organized in a systematic and concise way.
<br><br>My original problem was writing a&nbsp; fast library for simple
matrix computations (i.e. multiplication and inversion for small dense
matrices).&nbsp; I have not been able to make GSLHaskell work with Lapack so
far. :(<br>
<br>Anyway here are the new versions and timings, I increased the
number of times the vector is reversed, I also compiled everything with
-O2.<br><br>time ./arrayC <br>499<br>real&nbsp;&nbsp;&nbsp; 0m0.244s<br>user&nbsp;&nbsp;&nbsp; 0m0.236s<br>sys&nbsp;&nbsp;&nbsp; 
0m0.005s<br><br>time ./list<br>499<br>real&nbsp;&nbsp;&nbsp; 0m11.036s<br>user&nbsp;&nbsp;&nbsp; 0m10.770s<br>sys&nbsp;&nbsp;&nbsp; 0m0.118s<br><br>time ./IOMutArrayUnboxed <br>499<br>real&nbsp;&nbsp;&nbsp; 0m2.573s<br>user&nbsp;&nbsp;&nbsp; 0m2.408s<br>sys&nbsp;&nbsp;&nbsp; 0m0.042s<br><br>time ./IOMutUnbUnsafe 
<br>499<br>real&nbsp;&nbsp;&nbsp; 0m2.264s<br>user&nbsp;&nbsp;&nbsp; 0m2.183s<br>sys&nbsp;&nbsp;&nbsp; 0m0.025s<br><br>------------------------------<div id="mb_3">--------------------------------------------------<br><br>//compile with g++ -O2 -o arrayC arrayC.cc 
<span class="q"><br>#include &lt;
stdio.h&gt;<br>#include &lt;math.h&gt;<br><br><br><br>int main()<br>{<br>&nbsp; int array[500001];<br>&nbsp; <br>&nbsp; for (int i=0;i&lt;=500000;i++)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; array[i]=(19*i+23)%911;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; int tmp=0;<br></span>&nbsp; for (int cnt=0;cnt&lt;120;cnt++)
<span class="q"><br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int x=0;x&lt;=250000;x++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp=array[500000-x];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array[500000-x]=array[x];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; array[x]=tmp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; int result=0;<br>
&nbsp; for (int i=0;i&lt;=500000;i++)
<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result=result+(array[i]%911);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; result=result % 911;<br>&nbsp; printf(&quot;%d&quot;,result); <br>&nbsp; return 0;<br>}<br><br>--------------------------------------------------------------------------------
<br><br>
-- compile with<br></span>
-- ghc -O2 --make -o list list.hs<br><br>
module Main<br>
&nbsp;&nbsp;&nbsp; where<br>
<br>
import Data.List<span class="q"><br>
<br>
testArray = [ (19*i+23) `mod` 911 |i &lt;- [0..500000]]<br>
<br>
sumArrayMod =&nbsp; foldl (\x y -&gt; (y+x) `mod` 911) 0<br>
<br>
main = print $ sumArrayMod$<br></span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foldl (.) id&nbsp; (replicate 120 reverse) $testArray<br>
<br>
--------------------------------------------------------------------------------------<br><br>-- compile with<br>-- ghc -O2 --make -o IOMutArrayUnboxed IOMutArrayUnboxed.hs<span class="q"><br>module Main<br>&nbsp;&nbsp;&nbsp; where<br>
<br>import Monad
<br>import <a href="http://data.array.io/" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">Data.Array.IO</a><br>import Data.Array.MArray<br>import Data.Array.Unboxed<br><br>total, semiTotal ::Int<br>
total=<span class="jajahWraper"><a class="jajahLink" title="Click to call this number with JAJAH..." href="javascript:void(0)"><span class="jajahInLink"> 500000</span></a></span><br>semiTotal=250000<br><br><br>testArray :: IO (IOUArray Int Int)
<br>testArray = newListArray (0,total)&nbsp; [(19*i+23) `mod` 911 |i &lt;- [0..total]]<br><br><br>reverseArray :: IOUArray Int Int -&gt; IO ()<br>reverseArray arr = mapM_&nbsp; (\i -&gt; do oldi &lt;- readArray arr i<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; oldj &lt;- readArray arr (total-i)
<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; writeArray arr i oldj<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; writeArray arr (total-i) oldi)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0..semiTotal]<br><br>sumArrayMod :: IOUArray Int Int -&gt; IO Int
<br>
sumArrayMod arr = foldM (\s i -&gt; do x &lt;- readArray arr i<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; return&nbsp;&nbsp; $!(s+x) `mod` 911) 0 [0..total]<br><br><br>main::IO()<br>main = testArray &gt;&gt;= \a -&gt;<br></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sequence&nbsp; (replicate 120 $reverseArray a)&gt;&gt;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sumArrayMod a &gt;&gt;=&nbsp; print <br><br>------------------------------------------------------------------------------------<br><br><br>-- compile with<br>-- ghc -O2 --make -o IOMutUnbUnsafe IOMutUnbUnsafe.hs<span class="q">
<br>
module Main<br>&nbsp;&nbsp;&nbsp; where<br><br>import Monad<br>import <a href="http://data.array.io/" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">Data.Array.IO</a><br>import Data.Array.MArray<br>import Data.Array.Unboxed
<br></span>import Data.Array.Base ( unsafeWrite, unsafeRead )<span class="q"><br><br>
total, semiTotal ::Int<br>total=<span class="jajahWraper"><a class="jajahLink" title="Click to call this number with JAJAH..." href="javascript:void(0)"><span class="jajahInLink"> 500000</span></a></span><br>semiTotal=250000
<br><br><br>testArray :: IO (IOUArray Int Int)<br>testArray = newListArray (0,total)&nbsp; [(19*i+23) `mod` 911 |i &lt;- [0..total]]<br><br><br>reverseArray :: IOUArray Int Int -&gt; IO ()
<br></span>reverseArray arr = mapM_&nbsp; (\i -&gt; do oldi &lt;- unsafeRead arr i<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; oldj &lt;- unsafeRead arr (total-i)<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; unsafeWrite arr i oldj<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; unsafeWrite arr (total-i) oldi)
<span class="q"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0..semiTotal]<br><br>sumArrayMod :: IOUArray Int Int -&gt; IO Int<br></span>sumArrayMod arr = foldM (\s i -&gt; do x &lt;- unsafeRead arr i<span class="q"><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; return&nbsp;&nbsp; $!(s+x) `mod` 911) 0 [0..total]
<br><br><br>main::IO()<br>main = testArray &gt;&gt;= \a -&gt; <br></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doFromTo 1 120 (\_ -&gt; reverseArray a) &gt;&gt; sumArrayMod a &gt;&gt;=&nbsp; print<br><br><br><br>{-# INLINE doFromTo #-}<br>-- do the action for [from..to], ie it&#39;s inclusive.
<br>doFromTo :: Int -&gt; Int -&gt; (Int -&gt; IO ()) -&gt; IO ()<br>doFromTo from to action =<br>&nbsp; let loop n | n &gt; to&nbsp;&nbsp; = return ()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | otherwise = do action n<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; loop (n+1)
<br>&nbsp;&nbsp; in loop from<br><br>-----------------------------------------------------------------------</div><br><br><br>