Подтвердить что ты не робот

Параллельная карта в haskell

Есть ли какой-нибудь подменю map, который оценивает список параллельно? Мне не нужно, чтобы он ленился.

Что-то вроде: pmap :: (a -> b) -> [a] -> [b] позволяет мне pmap expensive_function big_list и иметь все мои ядра на 100%.

4b9b3361

Ответ 1

Да, см. параллельный пакет:

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

Ответ 2

Помимо использования явных стратегий самостоятельно, как описал Том, 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 задокументирован здесь.