Обновление: я нашел эту страницу документации. Желание было ссылкой на него из документации, которую я использовал, которая, казалось, была окончательным документом API. Но, возможно, это новая, невыпущенная работа.
Обновление 2. Эта документация дала мне намного лучшую идею о том, как использовать модуль Control.Parallel.Strategies. Однако я не совсем решил проблему... см. Конец вопроса.
Я пытаюсь использовать parListChunk или некоторые другие функции параллельного управления в Haskell. Но я не могу понять, как их использовать. Предупреждение: Я Haskell noob. Я узнал кое-что о функциональном программировании с Схемой около 20 лет назад (!).
Здесь моя непараллельная функция:
possibKs n r = [ (k, (hanoiRCountK n k r)) | k <- [1 .. n-1] ]
Я хочу распараллелить его, что-то вроде этой наивной попытки:
possibKs n r
| n < parCutoff = results
| otherwise = parListChunk parChunkSize results
where results = [ (k, (hanoiRCountK n k r)) | k <- [1 .. n-1] ]
Но эта структура не подходит для parListChunk. Документы говорят:
parListChunk :: Int -> Strategy a -> Strategy [a]
parListChunk последовательно применяет стратегия для кусков (подпоследовательностей) параллельный список. Полезно для увеличения размер зерна
Хорошо, что я хочу. Но как его использовать? Я не смог найти никаких примеров этого. Если я понимаю объявление типа, функция parListChunk - это функция, которая принимает Int
и Strategy<a>
(заимствование переменной типа С++ с параметризованным типом, чтобы проверить, что я действительно понимаю это право) и возвращает Strategy<[a]>
. В моем случае я имею дело с Int
для a
, поэтому parListChunk потребуется аргумент Int
и Strategy<Int>
. Итак, что такое Strategy
и как его создать? И как только я успешно использовал parListChunk, что мне делать с Strategy
, он выплевывается?
Тип стратегии определяется следующим образом:
type Strategy a = a -> Done
(И это все документация для стратегии.)
Таким образом, Strategy<Int>
- это функция, которая принимает параметр типа Int и возвращает Done. По-видимому, это заставляет его аргумент оцениваться в определенное время или что-то еще. Где я могу его получить, и какой я должен использовать?
Возвращаются следующие функции:
sPar :: a -> Strategy b
sSeq :: a -> Strategy b
r0 :: Strategy a
rwhnf :: Strategy a
Но ни один из них не позволяет вам определить параметр типа - они создают Strategy<b>
, когда вы указываете параметр a
, иначе вы не получите параметр a
! Что с этим? Помимо этого, я понятия не имею, что это значит.
Я нашел один пример аналогичной функции parList, используемой в SO:
return . maximum $ map optimize xs `using` parList
Он использует эту функцию funky using
, которая объявлена:
using :: a -> Strategy a -> a
Достаточно справедливо... в моем случае я, вероятно, хочу, чтобы a
был [Int]
, поэтому он принимает список Ints и a Strategy<[Int]>
и (что-то применяет стратегию к списку?) и возвращает список интс. Поэтому я попытался выполнить пример parList и изменил свой защитник otherwise
на:
| otherwise = results `using` parListChunk parChunkSize
но я должен признать, что я все еще стреляю в темноте... Я не могу полностью следить за типом подписей. Поэтому не удивительно, что приведенное выше дает ошибку:
Couldn't match expected type `[(Int, Integer)]'
against inferred type `a -> Eval a'
Probable cause: `parListChunk' is applied to too few arguments
In the second argument of `using', namely
`parListChunk parChunkSize'
In the expression: results `using` parListChunk parChunkSize
Может ли кто-нибудь сказать мне, что использовать для аргумента Strategy a
для parListChunk? и как использовать Strategy [a]
, возвращаемый parListChunk?
Новая часть
Глядя на Основные стратегии, мне кажется, мне нужно использовать стратегию rseq
. Вероятно. Поэтому я стараюсь
| otherwise = results `using` (parListChunk parChunkSize rseq)
Но GHC говорит, что rseq "не в масштабе".
Эти документы API говорят, что в пакете нет rseq, но sSeq, похоже, заменил его. Хорошо, поэтому я использовал sSeq, но это тоже "не по масштабу". Хотя я импортирую Control.Parallel.Strategies
.
Любые подсказки? Btw Я использовал для получения этих сообщений о загрузке пакетов:
Loading package deepseq-1.1.0.0 ... linking ... done.
Loading package parallel-2.2.0.1 ... linking ... done.
Таким образом, очевидно, что указывает, какая версия параллельного пакета у меня: 2.2.0.1. Но я не вижу информацию в API docs о том, какая версия там описана. Если я не буду использовать rseq или sSeq, что я должен использовать? Почему Эдвард смог использовать parList?