Есть ли какой-нибудь подменю map
, который оценивает список параллельно? Мне не нужно, чтобы он ленился.
Что-то вроде: pmap :: (a -> b) -> [a] -> [b]
позволяет мне pmap expensive_function big_list
и иметь все мои ядра на 100%.
Есть ли какой-нибудь подменю map
, который оценивает список параллельно? Мне не нужно, чтобы он ленился.
Что-то вроде: pmap :: (a -> b) -> [a] -> [b]
позволяет мне pmap expensive_function big_list
и иметь все мои ядра на 100%.
Да, см. параллельный пакет:
ls `using` parList rdeepseq
будет оценивать каждый элемент списка параллельно с помощью стратегии rdeepseq
. Обратите внимание, что использование parListChunk
с хорошим значением куска может дать лучшую производительность, если ваши элементы слишком дешевы, чтобы получить преимущество, оценивающее каждую из них параллельно (потому что оно экономит на искрообразовании для каждого элемента).
РЕДАКТИРОВАТЬ: Основываясь на вашем вопросе, я чувствую, что должен объяснить, почему это ответ. Это потому, что Хаскелл ленив! Рассмотрим утверждение
let bs = map expensiveFunction as
Ничего не было оценено. Вы только что создали thunk, который отображает expensiveFunction
. Итак, как мы оцениваем его параллельно?
let bs = map expensiveFunction as
cs = bs `using` parList rdeepseq
Теперь не используйте список bs
в своих будущих вычислениях, вместо этого используйте список cs
. IOW, вам не нужна параллельная карта, вы можете использовать обычные (ленивые) карты и стратегию параллельной эвакуации.
EDIT: И если вы посмотрите достаточно, вы увидите функцию parMap, которая сделает то, что я показал здесь, но обернута в одну вспомогательную функцию.
В ответ на ваш комментарий код ниже не работает для вас? он работает для меня.
import Control.Parallel.Strategies
func as =
let bs = map (+1) as
cs = bs `using` parList rdeepseq
in cs
Помимо использования явных стратегий самостоятельно, как описал Том, parallel package также экспортирует parMap
:
parMap :: Strategy b -> (a -> b) -> [a] -> [b]
где аргумент стратегии похож на rdeepseq
.
И там также parMap
в пакете par-monad (вы выходите из чистого Haskell и в параллельную монаду):
parMap :: NFData b => (a -> b) -> [a] -> Par [b]
Пакет mon-monad задокументирован здесь.