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

Как создать стратегию в Haskell Control.Parallel.Strategies?

Обновление: я нашел эту страницу документации. Желание было ссылкой на него из документации, которую я использовал, которая, казалось, была окончательным документом 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?

4b9b3361

Ответ 1

Хорошо, я получил код. Я получил его для компиляции с помощью rwhnf вместо rseq:

| otherwise      = results `using` (parListChunk parChunkSize rwhnf)

В соответствии с этот исходный код, rwhnf был переименован в rseq в версии 3. Поэтому я предполагаю, что моя версия Parallel пакет устарел по отношению к этой документации.: -S

Я предполагаю, что часть цены использования "экспериментальных" пакетов.

В любом случае код компилируется и запускается. Будет ли это делать что-нибудь полезное с parallelism, это еще один вопрос...