Причина, по которой вы не видите здесь никакого параллелизма, заключается в том, что ваша искра была собрана мусором. Запустите программу с +RTS -s
и запишите следующую строку:
SPARKS: 1 (0 converted, 1 pruned)
искра была "подрезана", что означает, что сборщик мусора удаляет ее. В GHC 7 мы внесли изменения в семантику искр, так что искра теперь собирается мусором (GC'd), если на нее не ссылается остальная часть программы; подробности в бумаге "Seq no more" .
Почему искра GC'd в вашем случае? Посмотрите на код:
parMapFibEuler :: Int
parMapFibEuler = (forceList mapFib) `par` (forceList mapEuler `pseq` (sum mapFib + sum mapEuler))
искрой здесь является выражение forkList mapFib
. Обратите внимание, что значение этого выражения не требуется остальной части программы; он появляется только в качестве аргумента par
. GHC знает, что это не требуется, поэтому он собирает мусор.
Суть недавних изменений в пакете parallel
заключалась в том, чтобы вы могли легко избежать этой медвежьей ловушки. Хорошее правило - использовать Control.Parallel.Strategies
вместо par
и pseq
напрямую. Мой предпочтительный способ написать это будет
parMapFibEuler :: Int
parMapFibEuler = runEval $ do
a <- rpar $ sum mapFib
b <- rseq $ sum mapEuler
return (a+b)
но, к сожалению, это не работает с GHC 7.0.2, потому что искра sum mapFib
всплывает как статическое выражение (CAF), и среда выполнения не думает, что искры, указывающие на статические выражения, стоит сохранить (Я это исправлю). Конечно, этого не произойдет в реальной программе! Итак, давайте сделаем программу немного более реалистичной и победим оптимизацию CAF:
parMapFibEuler :: Int -> Int
parMapFibEuler n = runEval $ do
a <- rpar $ sum (take n mapFib)
b <- rseq $ sum (take n mapEuler)
return (a+b)
main = do [n] <- fmap (fmap read) getArgs
putStrLn (" sum : " ++ show (parMapFibEuler n))
Теперь я получаю хороший параллелизм с GHC 7.0.2. Тем не менее, обратите внимание, что комментарии @ John также применимы: как правило, вы хотите искать более детальный параллелизм, чтобы позволить GHC использовать все ваши процессоры.