Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does Haskell perform so poorly when executing C-like codes? (in this instance at least)
    primarykey
    data
    text
    <p>I am trying to figure out some performance issues I have been having with Haskell. As part of that, I have written a small comparison program to compare C and Haskell. Specifically, I translated the C program to Haskell with as few changes as I could. The speed-measured part of the Haskell program is then written in a very imperative style.</p> <p>The program makes two list of random numbers in some range, and then calculates the integral of the graph formed by simply connecting those points, with one list being x-values and one list being y-values. Essentially, it is the <a href="http://en.wikipedia.org/wiki/Trapezoidal_rule" rel="nofollow noreferrer">trapezoidal rule</a>.</p> <p>Here are the two codes:</p> <p>main.c</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;time.h&gt; #define N 5000000 #define maxY 1e5f/N #define maxXgap 1 int main(){ int i; float *y, *x; float xaccum, area; clock_t begin, end; double time_spent; y = (float*)malloc(sizeof(float)*N); x = (float*)malloc(sizeof(float)*N); srand(50546345); // change seed for different numbers //populate y and x fields with random points for(i = 0; i &lt; N; i++){ y[i] = ((float)rand())/((float)RAND_MAX)*maxY; } xaccum = 0; for(i = 0; i &lt; N; i++){ x[i] = xaccum; xaccum += ((float)rand())/((float)RAND_MAX)*maxXgap; } begin = clock(); //perform a trapezoidal integration using the x y coordinates area = 0; for(i = 0; i &lt; N-1; i++){ area += (y[i+1]+y[i])/2*(x[i+1]-x[i]); } end = clock(); time_spent = (double)(end - begin) / CLOCKS_PER_SEC * 1000; printf("%i points\n%f area\n%f ms\n", N, area, time_spent); } </code></pre> <p>Main.hs</p> <pre><code>{-# LANGUAGE BangPatterns #-} module Main where import Data.Array.Unboxed import Data.Array.IO import Data.List import System.Random import System.CPUTime import Text.Printf import Control.Exception main :: IO () main = do (x,y) &lt;- initArrays area &lt;- time $ integrate x y print area n :: Int n = 5000000 maxY :: Float maxY = 100000.0/(fromIntegral n) maxXgap :: Float maxXgap = 1 --initialize arrays with random floats --this part is not measured in the running time (very slow) initArrays :: IO (IOUArray Int Float, IOUArray Int Float) initArrays = do y &lt;- newListArray (0,n-1) (randomList maxY n (mkStdGen 23432)) x &lt;- newListArray (0,n-1) (scanl1 (+) $ randomList maxXgap n (mkStdGen 5462)) return (x,y) randomList :: Float -&gt; Int -&gt; StdGen -&gt; [Float] randomList max n gen = map (abs . ((*) max)) (take n . unfoldr (Just . random) $ gen) integrate :: IOUArray Int Float -&gt; IOUArray Int Float -&gt; IO Float integrate x y = iterative x y 0 0 iterative :: IOUArray Int Float -&gt; IOUArray Int Float -&gt; Int -&gt; Float -&gt; IO Float iterative x y !i !accum = do if i == n-1 then return accum else do x1 &lt;- readArray x i x2 &lt;- readArray x (i+1) y1 &lt;- readArray y i y2 &lt;- readArray y (i+1) iterative x y (i+1) (accum + (y2+y1)/2*(x2-x1)) time :: IO t -&gt; IO t time a = do start &lt;- getCPUTime v &lt;- a end &lt;- getCPUTime let diff = (fromIntegral (end-start)) / (10^9) printf "Computation time %0.5f ms\n" (diff :: Double) return v </code></pre> <p>The C integration runs in about 7 ms and the Haskell integration in about 60 ms on my system. Of course the Haskell version will be slower, but I am wondering why it is this much slower. Obviously there is a lot of inefficiency in the Haskell code.</p> <p>Why is the Haskell code so much slower? How could one fix it?</p> <p>Thanks for any answers.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload