
On Saturday 20 August 2011, 10:50:00, Sunil S Nandihalli wrote:
Thanks Daniel for your response. sieve of Eratosthenes has a very elegant 1 line implementation thanks to laziness of haskell. Here is what I came up with
primesSieve = 2:3:5:7:11:(filter (\x->(all (\p-> 0/=(mod x p)) (takeWhile (\p-> p*p<=x) primesSieve))) [13..])
Umm, I meant a real sieve, using an array. It's more complicated to implement, but much faster.
But didn't seem to make a difference in performance. I had missed the most obvious of things.... that is adding -O2 when compiling..
I never think of people compiling without optimisations, of course that's the very first thing to do.
It gave a speedup of close to 100 times which was very surprising! ..
Not really, without optimisations, you get no specialisations etc, so instead of the appropriate operations for the type you use, you get the generic ones (with a dictionary lookup). The type-specific operations often allow further optimisations, so things often become orders of magnitude faster. If you write overloaded functions, it's generally a good idea to tell GHC to specialise them for the most commonly used types (say Int and Integer in this example), {-# SPECIALISE foo :: Int -> Int, Integer -> Integer #-} Then, when everything is compiled with optimisations, the specialised versions are used when there exists one. (In your case, since main is in the same module, GHC usually specialises the function for the type used in main by itself [with -O2, at least when the functions are not exported], so it's not immediately necessary to add a specialise-pragma.)
I remember people setting some compiler options in the source file itself. Can you shed some light on that?
A pragma {-# OPTIONS_GHC -O2 #-} at the top of the module.
Thanks, Sunil.