haskell array access
Shawn P. Garbett
Shawn@Garbett.org
Fri, 27 Jun 2003 12:10:55 -0500
=2D----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On Thursday 26 June 2003 05:46 pm, Lex Stein wrote:
> Great, thanks. Those suggestions narrow the gap from GHC -O being 330x
> slower than GCC -O3 to it being 20x slower. Here are the new results:
>
> gcc -O3 0.54s
> ocamlopt 1.11s
> ghc -O 10.76s
> ocamlc 14.10s
>
> GHC is still pretty slow for native x86 instruction code. Is there any way
> to further explain the performance gap ? (new code below)
I redid both programs to make them equivalent in action. The haskell progra=
m=20
was not actually summing the results, the C program was not checking array=
=20
bounds (Haskell does), the C program did not initialize the array and the C=
=20
program didn't print the result.
Times on my laptop (Crusoe 933):
62.061s : Haskell (Array -O2) Note: lot's 'o disk grinding!
18.231s : Haskell (UArray -O2)
18.108s : Haskell (UArray -O2 -fvia-c)
17.443s : Haskell (UArray -O2 -funfolding-update-in-place)
0.807s : C (-O3 without bound check)
1.127s : C (-O3 with bound check)
At best case for Haskell, 15.5 times slower. The thing about bounds checkin=
g,=20
in Haskell it's always there. In C, you might have it, you might not there =
is=20
no certainty by the language, only by design and implementation. So with C,=
=20
one is free to live dangerously.
I changed the "mod" value to 17, so that out of bound access takes place in=
=20
the Haskell program. It gives me the following:
=46ail: Ix{Int}.index: Index (16) out of range ((0,15))
I did the same to the C program (without the bounds checking), it spits out=
a=20
value and give no indication that anything improper was done.
=2D ---------------------------------------------
Haskell Original (redone to be funtionally equivalent)
=2D ----------------------------------------------
import Array
a :: Array Int Int
a =3D array (0,15) [(i, i) | i <- [0 .. 15] ]
acc :: Int -> Int -> Int
acc s 0 =3D s
acc s n =3D acc (s + (a ! (n `mod` 16))) (n-1)
main :: IO ()
main =3D do
print $ acc 0 100000000
=2D -----------------------------------------------------
C Version with some modifications as well
=2D ----------------------------------------------------------
#include <stdio.h>
int main ()
{
int i;
int k;
int idx;=20
int a[16];
for (i=3D0; i<16; ++i)
{
a[i] =3D i;
}
for (k=3D0, i=3D100000000; i>0; --i)
{
idx =3D i % 16;
if((idx > 15) || (idx < 0))
{
fprintf(stderr, "Out of range access (0,15) value is %d\n", idx);
exit(1);
}
=20
k +=3D a [idx];=20
}
printf("%d\n", k);
}
=2D --------------------------------------
New Haskell version with Unboxed Array
Note:it was a simple change of import and type
=2D -----------------------------------------
import Data.Array.Unboxed
a :: UArray Int Int
a =3D array (0,15) [(i, i) | i <- [0 .. 15] ]
acc :: Int -> Int -> Int
acc s 0 =3D s
acc s n =3D acc (s + (a ! (n `mod` 16))) (n-1)
main :: IO ()
main =3D do
print $ acc 0 100000000
=2D----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)
iEYEARECAAYFAj78eqEACgkQDtpPjAQxZ6AgPQCePRrgaAmxMzfW7d2akvaXLJU7
SxAAnj7wO7vx6zXQwRVBXpMrbqw2wZDF
=3DoMhR
=2D----END PGP SIGNATURE-----