Поддерживают ли какие-либо функциональные языки разделение и завоевание изначально?
Мне жаль, что я не мог понять способ более четко выразить вопрос в заголовке, но по существу, это так: почти все функциональные языки имеют конструкции, которые позволяют обрабатывать переменный список аргументов через хвост рекурсии, как в этом псевдокоде Erlang-ish, который суммирует список чисел:
sumup(0,A) -> A.
sumup(N,A) -> sumup(N) + A.
Однако один из больших апелляций функциональных языков для меня - это их неотъемлемый parallelism. И хотя проблема, такая как подведение списка чисел, очевидно, вполне параллелизуема и почти наверняка будет наиболее эффективно обрабатываться с помощью деления и покорения, я не знаю о языковых функциях, которые делают это естественным способом программирования. Фактически, если у языка нет функций, которые позволяют считывать количество аргументов, основанных на функции, и извлекать аргументы на основе индекса, я не вижу, как это сделать . Существуют ли какие-либо функциональные языки для поощрения программирования с разделением и победой?
Ответы
Ответ 1
Есть ли у каких-либо функциональных языков функции для поощрения программирования "разделяй и властвуй"?
Да: возможность создавать новые функции более высокого порядка в библиотеках.
Одна из самых важных таких функций в списках в любом случае foldr
, которая может быть распараллелена в принципе применительно к ассоциативному оператору, хотя это редко делается на практике. Зачем? Потому что foldr
спроектирован вокруг последовательного потока данных.
Красота функциональных языков заключается в том, что, как только эта проблема будет распознана, мы можем решить эту проблему не путем внедрения новых языковых функций, а путем более интеллектуального использования тех функций, которые у нас уже есть. Чтобы посмотреть, как, посмотрите Гай Стил поговорить с августа 2009 года, где он объясняет, почему foldr
не является правильной библиотечной функцией для параллельного функционального программирования, и он предлагает
- Новый стиль программирования
- Новое представление списков
- Новые функции более высокого порядка для библиотек
которые предназначены для поддержки программирования с разделением и победой.
То, что я так волновало в этом разговоре, состоит в том, что нет необходимости вводить новые языковые функции для поддержки программирования "разделение и покорение". Достаточно взять примитивы, которые мы уже сделали иметь и использовать их для разработки лучших библиотек.
Если у вас есть доступ к цифровой библиотеке ACM, вы можете просмотреть видеоролик Guy talk Организация функционального кода для параллельного исполнения или как точки Бена Карела вы можете увидеть видео, снятое Malcom Wallace на Vimeo.
Ответ 2
Автоматически parallelism не так просто, как может показаться. Проблема заключается в том, что если разметка выполняется автоматически, существует риск перераспределения (слишком много разделов), что добавит слишком много накладных расходов или дезадаптации, что не будет зависеть от всех основных ядер ваших процессоров.
Выяснить это статически (т.е. Во время компиляции) довольно сложно, поэтому разработчик обычно оставлял аннотировать, где распараллелить.
Примеры:
В Haskell есть par
combinator, который служит аннотацией к созданию искры, вычислению, которое превращается в поток, когда ядро центрального процессора становится доступным.
Data Parallel Haskell: определяет тип данных параллельного массива, чтобы разрешить более неявный стиль распараллеливания, но, похоже, он стоит за счет некоторые ограничения и все еще экспериментальный код.
(отказ от ответственности: я не разработчик Haskell)
Параллельная библиотека задач в .NET:
может выполнять автоматическое распараллеливание данных, или вы можете реализовать свой собственный Partitioner.
Вам все равно нужно знать, как работает распараллеливание, или вы закончите over- или underpartitioning.
Рид Corpsey имеет отличную серию статей о TPL и PLINQ.
DryadLINQ основывается на PLINQ и добавляет автоматические распределенные вычисления.
Ни один из них не является родным для языка, но они тесно интегрированы. Там даже модуль интеграции PLINQ для F #.
Ответ 3
Посмотрите Manticore, его предшественник NESL и его родственный ZPL. Все это, по крайней мере, частично функциональные языки с параллельными конструкциями для работы со всем содержимым структур данных за раз.
Ответ 4
Я не знаком с любыми языками с шаблонами типа "разделяй и властвуй". Как вы говорите, трудно представить, как бы вы указали что-то подобное.
Без дико новых нот я считаю, что классические функции, такие как partition
, - это лучшее, что мы можем сделать.
Ответ 5
В Ruby довольно легко указать такую вещь. В этом примере мы разбиваем диапазон на группы по три и отправляем метод суммы для каждой группы. Затем мы суммируем полученные частичные суммы. Вы можете легко развернуть это, чтобы сделать его многопоточным.
(1..10).each_slice(3).map{ |x| x.inject :+ }.inject(:+)
Этот пример немного отличается от вашего, но показывает принцип.