Насколько сложно многопоточность Haskell?

Я слышал, что в Haskell создание многопоточного приложения так же просто, как принятие стандартного приложения Haskell и его компиляция с флагом -threaded. Другие случаи, однако, описали использование команды par в самом исходном коде.

Каково состояние многопоточности Haskell? Насколько легко внедряться в программы? Есть ли хороший многопоточный учебник, который охватывает эти разные команды и их использование?

Ответ 1

Каково состояние многопоточности Haskell?

Зрелые. Реализация составляет около 15 лет, с транзакционной памятью на 5 лет. GHC - широко используемый компилятор с большой поддержкой с открытым исходным кодом и коммерческой поддержкой.

Насколько легко внедряться в программы?

Это зависит от алгоритма. Иногда это может быть использование одной строки par для получения parallelism. Иногда необходимо разработать новые алгоритмы. В общем, будет проще вводить безопасные parallelism и concurrency в Haskell, чем в типичных языках, и производительность хорошая.

Есть ли хороший многопоточный учебник, в котором рассматриваются эти разные команды и их использование?

В Haskell есть 3 основные параллельные и параллельные модели программирования.

  • неявный parallelism через par
  • явный concurrency и parallelism через forkIO/MVars и транзакционную память программного обеспечения
  • данные parallelism через библиотеки DPH

Это основные вещи. Во всех случаях вы компилируете с помощью -threaded, чтобы использовать многоядерную среду выполнения, но насколько легко разрешить эту проблему, зависит от используемого вами алгоритма и модели параллельного программирования, которую вы используете в этом списке.

Вот введение в основные модели параллельного программирования в Haskell, и как добиться ускорений.

Я думаю, Глава 24 Real World Haskell - хороший учебник.

Ответ 2

Существует также термин concurrency.

Без каких-либо изменений кода ваш haskell rts попытается использовать их для некоторого внутреннего процесса, но для использования в вашем приложении вы должны дать подсказку, сделанную par b (f a b), которая заставляет Haskell быть не так ленив на caculation b, даже если f не потребует его для результата.

Одна из причин не делать этого для каждой функции, для которой требуются все ее аргументы (например, a+b), заключается в том, что синхронизация (планирование вычислений и ожидание результатов) дает некоторые накладные расходы, и вы, вероятно, не хотите тратить дополнительные средства -ticks для (2*3)+(3*4) только потому, что вы можете рассчитать умножения параллельно. И вы, вероятно, потеряете некоторые кеш-хиты или что-то вроде этого или оптимизации, которые выполняются, когда вы делаете это на одном процессоре (т.е. Вы все равно должны передавать результат от одного процессора к другому).

Конечно, код, который использует par, является уродливым, и когда вы сворачиваете список или некоторые другие структуры данных со светлыми субэлементами, вы, вероятно, захотите рассчитать некоторые куски этих легких элементов, чтобы убедиться, что служебные/быть очень маленьким. Чтобы разрешить это, вы можете посмотреть parallel.

Существует также Data Parallel Haskell (DPH).

Если ваша программа больше похожа на IO monad, вам определенно нужно много изменений. См. forkIO, Программная транзакционная память (STM) и многие другие из Concurrency category