Параллельная карта в хаскеле - PullRequest
32 голосов
/ 09 апреля 2011

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

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

Ответы [ 2 ]

37 голосов
/ 09 апреля 2011

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

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. Итак, вам не нужна параллельная карта, вы можете использовать обычные (ленивые) карты и стратегию параллельной эвакуации.

РЕДАКТИРОВАТЬ: И если вы посмотрите достаточно, вы увидите функцию parMap , которая выполняет то, что я здесь показал, но обернута в одну вспомогательную функцию.

В ответ на ваш комментарий у вас не работает приведенный ниже код? это работает для меня.

import Control.Parallel.Strategies

func as =
        let bs = map (+1) as
            cs = bs `using` parList rdeepseq
        in cs
17 голосов
/ 09 апреля 2011

Помимо использования явных стратегий самостоятельно, как описал Том, пакет параллельный также экспортирует parMap:

 parMap :: Strategy b -> (a -> b) -> [a] -> [b]

где аргумент стратегии - что-то вроде rdeepseq.

И есть также parMap в пакете par-monad (вы выходите из чистого Haskell и в параллельную монаду):

 parMap :: NFData b => (a -> b) -> [a] -> Par [b]

Пакет par-monad задокументирован здесь .

...