Вдохновленный вопросом от SO: /programming/6623391/how-to-gain-control-of-a-5gb-heap-in-haskell
Это может быть долгий спор о многочисленных преимуществах и недостатках FP, но сейчас я бы хотел сузить сферу до основной эффективности FP на современном оборудовании.
Тезис:
Функциональная парадигма подразумевает неизменность и отсутствие состояния (?), Но аппаратные средства, на которых мы выполняем функциональные программы, являются конечными автоматами с состоянием. Перевод «чисто функциональной» программы в представление «с аппаратным состоянием» оставляет программисту мало контроля, приводит к накладным расходам (?) И ограничивает использование аппаратных возможностей (?).
Прав ли я или нет в сомнительных заявлениях?
Можно ли доказать, что FP не предусматривает / не накладывает принципиальных потерь на производительность в современной компьютерной архитектуре общего назначения?
РЕДАКТИРОВАТЬ: Как я уже сказал в ответ на некоторые комментарии, вопрос не в производительности реализации и деталях. Речь идет о наличии или отсутствии главных издержек , которые может принести выполнение FP на автоматах с состоянием.
running FP on stateful automata
.Ответы:
Существует огромное недопонимание в неизменности.
Неизменность - это особенность семантики, но она не подразумевает неизменность в реализации.
Простым примером является реализация лени.
Когда вычисления ленивы, результатом выражения является концептуально значение, но базовой реализацией является thunk, содержащий аргументы для оценки и функцию для создания значения, а также слот для хранения значения.
Когда вы в первый раз спросите (на языке) о значении, вычисление будет фактически выполнено, его результат оценен и значение, возвращенное вам (или дескриптору).
Это прозрачно в языковой семантике, и все, что вы знаете, это то, что эта переменная была привязана к значению (или будущему значению) и что, как только это будет сделано, вы не сможете изменить значение, которое будет возвращено. Базовое представление памяти изменится, но вы не будете знать об этом.
Одинаковое различие между семантикой и реализацией существует примерно в любом языке и фактически является основой оптимизации . Каким бы ни был язык, семантика гарантирует некоторые вещи, но оставляет другие неопределенными, чтобы оставить место для оптимизации.
Теперь это правда, что практически функциональные языки не так быстры, как, например, C ++. Тем не менее,
Go
(что по-прежнему довольно шумно) медленнее, чем Haskell или Lisp, как и C # Mono ( источник ).Когда вы видите, насколько ненадежным может быть C ++ или C, чтобы получить эти исполнения, вы можете немного отпустить.
Когда вы поймете, что сегодня Haskell быстро растет, и в его компиляторе / среде выполнения еще есть много возможностей для оптимизации (например, GHC недавно переключился на LLVM, Microsoft Research активно финансирует усовершенствования среды выполнения), вы можете поспорить, что это скоро улучшится.
Удовольствие: игра на регулярных выражениях или то, как команда Haskell создала сопоставление регулярных выражений, которое превосходит
re2
библиотеку C от Google по ряду сценариев.источник
Функциональная парадигма полезна для разбиения вещи в узкой области. Это действительно хорошая вещь, учитывая, как развивается компьютер.
Многоядерные процессоры сталкиваются с большими проблемами, связанными с общими ресурсами, и затраты на синхронизацию действительно дороги. Функциональная парадигма позволяет естественным образом выражать программы, в которых нет таких проблем. Это действительно хорошо для параллелизма.
Кроме того, мы все больше и больше используем серверные фермы с SaaS и облачными вычислениями. Таким образом, одно и то же приложение должно работать на нескольких машинах. На этой позиции затраты на синхронизацию еще дороже. Google проделал определенную работу и опубликовал несколько исследовательских работ о функциональном программировании и алгоритме, которые вы можете написать. Это для них ключевой момент, потому что у них есть проблема масштабируемости.
Более того, вы можете легко сделать стек в куче компьютера, и даже не непрерывный, используя связанные списки. Это уже сделано для генерации трассировки стека во многих языках программирования. Так что это не проблема.
ОК, функциональное программирование подразумевает некоторые ограничения. Но это также дает естественный способ выразить проблематику, которую мы имеем в современной компьютерной технике, с которой чрезвычайно трудно справиться в парадигмах, к которым мы привыкли. Масштабируемость является одним из них, и это становится реальной сделкой.
Все, кто уже имеет дело со сложной параллельной системой, знают, о чем я говорю.
Так что я бы нюансировал ответ. Да, у функционала есть проблемы с современным оборудованием, но у простого старого программирования тоже есть. Как всегда, вы найдете преимущества и недостатки. Суть в том, чтобы знать, что они из себя представляют, чтобы вы могли сделать правильный выбор, когда это необходимо.
источник
На самом деле у меня нет ответа, так как я не знаю текущего состояния или даже того, насколько сложно это будет, но только потому, что компилятор обеспечит эти вещи из входных данных, не обязательно означает, что выходные данные будут иметь их , Теоретически, достаточно умный компилятор может обойти все эти проблемы, но на практике он, вероятно, всегда будет существовать.
Однако, другой способ взглянуть на это - взглянуть на историю машины Lisp. Если я правильно помню, они изначально были предназначены для преодоления тех же проблем, с которыми сталкивался Лисп, в отличие от машин того времени. Разработка этих машин в конечном итоге прекратилась, так как настольные компьютеры стали достаточно быстрыми, чтобы неэффективность обходилась дешевле, чем поддерживать другую машину.
В целом, за исключением наиболее критичного к производительности приложения, языки FP по-прежнему достаточно быстрые. Выбрав любой язык более высокого уровня, вы захотите снизить приоритет точной настройки и производительности для более безопасного, легкого, более удобного обслуживания или какого-либо другого приоритета.
В конце концов, программирование - это компромиссы, поэтому нужно просто выбрать, что важнее для проекта под рукой.
источник
Это правда, что функциональная парадигма подразумевает неизменность и отсутствие состояния, но у нас нет абсолютно чистых языков программирования. Даже самый чистый, Haskell, позволяет побочные эффекты.
Тем не менее, чтобы ответить на ваш вопрос об эффективности, я использовал и Haskell, и Clojure, и не заметил каких-либо проблем с производительностью.
источник