Являются ли функциональные языки по своей природе более параллелизуемыми, чем их OO или императивные родственники? - PullRequest
6 голосов
/ 11 марта 2009

Я читал и думал об этом немного. Похоже, что в будущем многоядерные функциональные языки станут более популярными. Я относительный нуб к функциональному программированию. Мое единственное знакомство было академическим, и ничего достаточно сложного, чтобы по-настоящему опробовать этот класс языка.

Итак, насколько я понимаю, чистые функции можно легко и прозрачно распараллелить. Это отличная функция, так как это означает, что нет проблем с написанием многопоточного кода. Однако, похоже, что он не очень помогает с серийным кодом.

Example:

fooN( ... (foo3(foo2(foo1(0)))))

Подобные последовательные вызовы кажутся распространенной, а иногда и неизбежной проблемой. Для меня это корень того, почему распараллеливание так сложно. Некоторые задачи просто (или кажутся) очень последовательными. Позволяет ли «функциональное мышление» лучше разложить некоторые, казалось бы, последовательные задачи? Есть ли в существующих функциональных языках прозрачные механизмы для лучшего распараллеливания высокосерийного кода? Наконец, функциональные языки по своей природе более параллельны, чем ОО или императивные языки, и почему?

Ответы [ 2 ]

8 голосов
/ 11 марта 2009

Функциональные языки более распараллеливаемы, чем императивные и ОО-языки, благодаря чистым функциям. Однако вы абсолютно правы: если у вас есть такие зависимости данных, вы не сможете распараллелить их. Основное значение функционального программирования заключается в том, чтобы упростить выявление параллелизма, присутствующего в вашем коде, и рассуждать о нем, потому что мешать могут только зависимости данных, а не общее изменяемое состояние.

На самом деле, поскольку большинству простых программистов-смертников трудно работать на чисто функциональных языках и поскольку драконовская политика полного запрещения изменяемого состояния может быть неэффективной, возникла некоторая идея о том, что отдельные тела функций должны быть обязательно написаны, но запретить побочные эффекты через функции. Другими словами, все функции, которые должны быть распараллелены, должны быть чистыми. Затем вы можете иметь изменяемое состояние для локальных переменных, чтобы сделать код более простым для написания и более эффективным, но при этом обеспечить безопасное и простое автоматическое распараллеливание вызовов этих чистых функций. Это исследуется, например, в ветке 2.0 языка D.

6 голосов
/ 11 марта 2009

Это в основном о побочных эффектах. Если компилятор знает, что некоторые части кода не имеют побочных эффектов, он может оптимизировать на основе структуры кода для параллельного запуска некоторых из них.

Рассмотрим linq на C # /, который полуфункциональный:

var someValues = from c in someArray
                where // some  comparisson with no side effects
                select c;

Вы указываете намерение того, что вы хотите сделать, если компилятор знал, что каждый фрагмент выражения не имеет побочных эффектов, он мог бы безопасно назначать разные части массива для обработки на разных ядрах. На самом деле, есть .AsParalell, который будет работать параллельно linq (plinq), который будет включать только это. Проблема заключается в том, что он не сможет задействовать бит без побочных эффектов (находясь на языке / фреймворке, который его не поддерживает), который может стать очень уродливым, если разработчики этого не знают. Из-за этого они сделали это явным, но вы можете видеть, что на этом пути возникают проблемы.

...