[Haskell-cafe] A tale of Project Euler
Andrew Coppin
andrewcoppin at btinternet.com
Tue Nov 27 14:34:56 EST 2007
Hi guys.
Somebody just introduced me to a thing called "Project Euler". I gather
it's well known around here...
Anyway, I was a little bit concerned about problem #7. The problem is
basically "figure out what the 10,001st prime number is". Consider the
following two programs for solving this:
First, somebody else wrote this in C:
int n = 2 , m , primesFound = 0;
for( n=0;n < MAX_NUMBERS;n++ )
if( prime[n] )
{
primesFound++;
if( primesFound == 10001 )
cout << n << " is the 10001st prime." << endl;
for(m=2*n;m<MAX_NUMBERS;m+=n)
prime[m]=false;
}
Second, my implementation in Haskell:
primes :: [Integer]
primes = seive [2..]
where
seive (p:xs) = p : seive (filter (\x -> x `mod` p > 0) xs)
main = print (primes !! 10000)
Well, we know who's winning the beauty contest. But here's the worrying
thing:
C program: 0.016 seconds
Haskell program: 41 seconds
Eeeps! o_O That's Not Good(tm).
Replacing "primes :: [Integer]" with "primes :: [Word32]" speeds the
Haskell version up to 18 seconds, which is much faster but still a joke
compared to C.
Running the Haskell code on a 2.2 GHz AMD Athlon64 X2 instead of a 1.5
GHz AMD Athlon drops the execution time down to 3 seconds. (So clearly
the box I was using in my lunch break at work is *seriously* slow...
presumably the PC running the C code isn't.)
So, now I have a Haskell version that's "only" several hundred times
slower. Neither program is especially optimised, yet the C version is
drastically faster. This makes me sad. :-(
By the way... I tried using Data.List.Stream instead. This made the
program about 40% slower. I also tried both -fasm and -fvia-c. The
difference was statistically insignificant. (Hey guys, nice work on the
native codegen!) The difference in compilation speed was fairly drastic
though, needless to say. (The machine is kinda low on RAM, so trying to
call GCC makes it thrash like hell. So does linking, actually...)
Also, I'm stuck with problem #10. (Find the sum of all primes less than
1 million.) I've let the program run for well over 15 minutes, and still
no answer is forthcomming. It's implemented using the same primes
function as above, with a simple filter and sum. (The type has to be
changed to [Word64] to avoid overflowing the result though.) The other
guy claims to have a C solution that takes 12 ms. There's a hell of a
difference between 12 ms and over half an hour...(!) Clearly something
is horribly wrong here. Uh... help?
More information about the Haskell-Cafe
mailing list