Функциональное программирование имеет неизменные структуры данных и не имеет побочных эффектов, которые по своей природе подходят для параллельного программирования.
Это распространенное заблуждение.Параллелизм связан исключительно с производительностью, а чистота снижает производительность.Так что чисто функциональное программирование не является хорошей отправной точкой, если ваша цель - добиться достойной производительности.В общем, чистота означает большее распределение и худшую местность.В частности, чисто функциональные структуры данных заменяют массивы деревьями, что приводит к гораздо большему выделению ресурсов и значительно увеличивает нагрузку на сборщик мусора.
Например, измерьте производительность элегантной чисто функциональной «быстрой сортировки»в Хаскеле .Последнее, что я проверял, это было в тысячи раз медленнее, чем обычное императивное решение на моей машине.
Кроме того, никому никогда не удавалось реализовать эффективную структуру словарных данных (чистую или нечистую) или эффективную чисто функциональную сортировку.в Haskell и никто не придумал, как написать эффективную эффективную структуру данных постоянного непересекающегося множества , и не существует известного способа реализации других базовых структур данных, таких как чисто функциональные слабые словари!
Более того, хотя теоретически возможно писать нечистый код в Haskell, GC сильно оптимизирован для чистого кода за счет производительности мутации.Например, хэш-таблица GHC по-прежнему в 26 раз медленнее, чем в .NET.Исторически, производительность мутации считалась настолько незначительной в Haskell, что запись одного указателя на массив была операцией O ( n ) в GHC в течение пяти лет .
Я исследую, как использовать многоядерные вычисления на функциональном языке, и нацеливаю производственный код на некоторые числовые приложения.
Лучший способ, который я нашел, - научиться писать достойные параллельные программы длямногоядерные в императивном стиле (изучите, в частности, Cilk ), а затем разложите код, используя первоклассные функции и исключение хвостовых вызовов, в функциональный стиль impure .
Это означает кэширование забытых структур данных и алгоритмов.Никто никогда не делал этого в Хаскеле.Действительно, ни одно из исследований, опубликованных на параллельном Haskell на сегодняшний день, даже не упомянуло существенную концепцию сложности кеша .Кроме того, хотя широко известно, что нестрогая (иначе говоря, «ленивая») оценка делает использование пространства непредсказуемым, пока широко не признается, что эта же проблема делает масштабируемость крайне непредсказуемой на многоядерных процессорах.
F # имеет Microsoftза его спиной и его параллельными конструкциями, такими как PLINQ, TPL, Async Workflow, были хорошо документированы и показаны некоторые потенциалы.
Они значительно превосходят потенциальные возможности.Тысячи коммерческих приложений построены на этих основополагающих принципах промышленного развития.
Тем не менее, исследования о параллелизме в Haskell в настоящее время очень активны, и он обладает многими приятными функциями, которые еще не поддерживаются F #:
Почему вы предполагаете, что они "хорошие функции"?
Я предлагаю прочитать последнюю статью Саймона Марлоу об этом:
"... сочетание практического опыта и исследований привело нас к выводу, что этот подход не лишен недостатков. В двух словах, проблема заключается в следующем: достижение параллелизма с par
требует, чтобы программист понимал операционные свойства языка, которыйв лучшем случае определяется реализацией (а в худшем - неопределенно). Это делает par
трудным для использования, а ловушек предостаточно - новые пользователи имеют высокую частоту отказов ... "
Мой вопрос: какой языкя должен выбрать для функционального параллелизма?
Я бысоветовать против параллельного чисто функционального кода для производства, потому что это полный джокер. Предполагая, что вы готовы пожертвовать некоторой чистотой ради достижения конкурентных результатов, я использую и рекомендую F #.