
Dear Janek,
I am reading Simon Marlow's tutorial on parallelism and I have problems with correctly using Eval monad and Strategies. I *thought* I understand them but after writing some code it turns out that obviously I don't because parallelized code is about 20 times slower. Here's a short example (code + criterion benchmarks):
Actually, (sin . sqrt) is simply too cheap. The overhead of constructing chunks (which have to be constructed on the heap) and concatenating the results far outweighs the cost of computing the list elements. If, for example, you replace sin . sqrt by f defined by f :: Double -> Double f x | x < 10 = x*x | otherwise = sin x * f (x-100) the picture will change. The loss also becomes far less dramatic if you construct the chunks outside of the benchmark: main :: IO () main = defaultMain [ bench "Seq" $ nf (map calculateSeq) xs , bench "Par" $ nf calculatePar xs ] where xs = chunk 2048 [1..16384] f, f' :: Double -> Double f x = sqrt (sin x) f' x | x < 10 = x*x | otherwise = sin x * f' (x-100) calculateSeq :: [Double] -> [Double] calculateSeq [] = [] calculateSeq (x:xs) = f x : calculateSeq xs calculatePar :: [[Double]] -> [[Double]] calculatePar xss = runEval $ parList (rdeepseq . calculateSeq) xss chunk :: Int -> [a] -> [[a]] chunk _ [] = [] chunk n xs = as : chunk n bs where !(as, bs) = splitAt n xs The parallel version (with f = sqrt . sin) is still somewhat slower than the sequential version with -N1 -- probably due to rdeepseq. Best regards, Bertram