Ефективність чисто функціонального програмування


397

Хтось знає, що є найгіршим можливим асимптотичним уповільненням, яке може статися при програмуванні суто функціонально на відміну від імперативного (тобто, що дозволяє побічні ефекти)?

Пояснення з коментаря itowlson : чи є якась проблема, щодо якої найвідоміший неруйнівний алгоритм асимптотично гірший за найкращий відомий деструктивний алгоритм, і якщо так, то на скільки?


6
Те саме, що при імперативному програмуванні, що б там не було.
Р. Мартіньо Фернандес

3
@jldupont: повернути результат обчислення курсу. Існує багато безкоштовних програм для побічних ефектів. Вони просто не можуть зробити багато іншого, крім обчислення їх вкладу. Але це все-таки корисно.
jalf

24
Я можу зробити це так погано, як вам подобається, погано написавши свій функціональний код! * усмішка * Я думаю, що ви запитуєте: «чи є якась проблема, для якої найвідоміший неруйнівний алгоритм асимптотично гірший за найкращий відомий деструктивний алгоритм, і якщо так, то на скільки?» ... це правильно ?
itowlson

2
чи можете ви навести приклад типу сповільнення, яке вас цікавить. Ваше запитання трохи розпливчасте.
Пітер Рекор

5
Користувач видалив свою відповідь, але він стверджував, що функціональна версія 8-царичної проблеми працювала за хвилину протягом n = 13. Він визнав, що це було "не дуже добре", тому я вирішив написати свою власну версію 8 королеви в F #: pastebin.com/ffa8d4c4 . Потрібно сказати, що моя суто функціональна програма обчислює n = 20 трохи більше секунди.
Джульєтта

Відповіді:


531

Згідно з Піппенджером [1996] , при порівнянні системи Lisp, яка є чисто функціональною (і має сувору семантику оцінювання, не лінується), та тією, яка може мутувати дані, алгоритм, написаний для нечистого Lisp, який працює в O ( n ), може бути переведений до алгоритму в чистому Lisp, який працює за O ( n log n ) часу (на основі роботи Бен-Амрама та Галіля [1992] про моделювання пам'яті з випадковим доступом за допомогою лише покажчиків). Pippenger також встановлює, що існують алгоритми, для яких це найкраще, що ви можете зробити; є проблеми, що є O ( n ) в системі нечистоти, які є Ω ( n log n ) в чистій системі.

У цьому документі слід зробити кілька застережень. Найбільш важливим є те, що він не стосується ледачих функціональних мов, таких як Haskell. Bird, Jones та De Moor [1997] демонструють, що проблема, побудована Піппенджером, може бути вирішена ледачою функціональною мовою за O ( n ) час, але вони не встановлюють (і наскільки я знаю, ні в кого немає), чи не лінива функціональна мова може вирішити всі проблеми за той самий асимптотичний час роботи, що і мова з мутацією.

Проблема, побудована Піппенджером, вимагає, щоб Ω ( n log n ) була спеціально побудована для досягнення цього результату, і не обов'язково є репрезентативною для практичних проблем у реальному світі. Існує кілька обмежень щодо проблеми, які є трохи несподіваними, але необхідними, щоб доказ працював; зокрема, проблема вимагає, щоб результати обчислювались в режимі он-лайн, не маючи доступу до майбутнього вводу, і що вхід складається з послідовності атомів з необмеженого набору можливих атомів, а не набору фіксованого розміру. А робота лише встановлює (нижню межу) результати для нечистого алгоритму лінійного часу роботи; для проблем, які потребують більшого часу роботи, можливо, додаткові O (log n) фактор, побачений в лінійній задачі, може бути здатний "поглинатися" в процесі додаткових операцій, необхідних для алгоритмів з більшим часом роботи. Бен-Амрам [1996] коротко досліджує ці роз'яснення та відкриті питання .

На практиці багато алгоритмів можуть бути реалізовані чистою функціональною мовою при тій же ефективності, що і в мові зі змінними структурами даних. Для кращого посилання на методики ефективного впровадження чисто функціональних структур даних див. « Крісті функціональні структури даних» Кріса Окасакі [Okasaki 1998] (що є розширеною версією його тези [Okasaki 1996] ).

Кожен, кому потрібно реалізувати алгоритми на суто функціональних структурах даних, повинен прочитати Окасакі. Ви завжди можете уповільнити O (log n ) уповільнення за одну операцію, імітуючи змінну пам'ять із врівноваженим бінарним деревом, але в багатьох випадках ви можете зробити це значно краще, ніж це. тимчасові, які роблять амортизовану роботу поступово. Суто функціональні структури даних можуть бути складно працювати і аналізувати, але вони надають багато переваг, таких як референсна прозорість, яка корисна в оптимізації компілятора, паралельних і розподілених обчислень, а також у реалізації таких функцій, як версія, скасування та відкат.

Зауважимо також, що все це обговорює лише асимптотичний час роботи. Багато методів реалізації суто функціональних структур даних дають вам певну кількість постійного сповільнення факторів, завдяки додатковій бухгалтерії, необхідній для їх роботи, та деталізації щодо мови, про яку йде мова. Переваги суто функціональних структур даних можуть перевищувати ці постійні уповільнення факторів, тому вам, як правило, потрібно робити компроміси на основі проблеми, про яку йдеться.

Список літератури


50
Піппінгер є безперечним авторитетом у цьому питанні. Але слід підкреслити, що його результати теоретичні , а не практичні. Що стосується того, щоб зробити функціональні структури даних практичними та ефективними, ви не можете зробити краще, ніж Окасакі.
Норман Рамзі

6
itowlson: Я мушу визнати, що я не прочитав достатньо Pippenger, щоб відповісти на ваше запитання; він був опублікований у рецензованому журналі, цитованому Окасакі, і я прочитав його досить, щоб визначити, що його твердження мають відношення до цього питання, але недостатньо, щоб зрозуміти докази. Безпосередні винос , що я отримую для реальних наслідків є те , що вона тривіальна для перетворення O ( п алгоритму) нечистого в O ( N журнал N ) чисті один, просто імітуючи змінювані пам'яті , використовуючи збалансоване бінарне дерево. Є проблеми, які не можуть зробити краще цього; Я не знаю, чи вони чисто теоретичні.
Брайан Кемпбелл

3
Результат Pippenger робить два важливих припущення, що обмежують його обсяг: він розглядає "он-лайн" або "реактивні" обчислення (не звичайна модель обчислення, що відображають кінцеві входи до одного виходу) та "символічні" обчислення, де вхідні дані є послідовностями атоми, які можна перевірити лише на рівність (тобто інтерпретація вхідних даних надзвичайно примітивна).
Кріс Конвей

2
Дуже гарна відповідь; Я хотів би додати, що для суто функціональних мов не існує загальновизнаної моделі обчислювальної складності, тоді як у чистому світі машина з оперативною пам’яттю з одиничною вартістю є відносно стандартною (тому це ускладнює порівняння речей). Також зауважте, що верхню межу різниці Lg (N) у чистому / нечистому можна легко зрозуміти інтуїтивно, дивлячись на реалізацію масивів чистою мовою (це коштує lg (n) за операцію (і ви отримуєте історію)) .
user51568

4
Важливий момент: Напружене переведення суто функціональної специфікації в більш складну ефективну чисто функціональну реалізацію мало користі, якщо ви, зрештою, автоматично або вручну - перекладете її в ще більш ефективний нечистий код. Домішки - це не така вже й велика справа, якщо ви можете тримати її в клітці, наприклад, заблокувавши її у функції, що не має зовнішнього побічного ефекту.
Робін Грін

44

Дійсно є декілька алгоритмів і структур даних, для яких не відомо жодного асимптотично ефективного чисто функціонального рішення (ti 1, реалізованого в чистому обчисленні лямбда), навіть із лінню.

  • Вищезгадана спілка-знахідка
  • Хеш-столи
  • Масиви
  • Деякі графічні алгоритми
  • ...

Однак ми припускаємо, що в "імперативних" мовах доступ до пам'яті є O (1), тоді як теоретично це не може бути настільки асимптотично (тобто для необмежених розмірів проблем), а доступ до пам'яті у величезному наборі даних завжди O (log n) , яку можна імітувати функціональною мовою.

Крім того, ми повинні пам’ятати, що фактично всі сучасні функціональні мови надають змінні дані, а Haskell навіть надає їх, не приносячи шкоди чистоті (монада ST).


3
Якщо набір даних вписується у фізичну пам'ять, доступ до нього є O (1), оскільки можна знайти абсолютну верхню межу часу, який потрібно прочитати будь-який елемент. Якщо набір даних не відповідає, ви говорите про введення / виведення, і це буде домінуючим фактором, але програма написана.
стипендіати

Ну, звичайно, я говорю про операції O (log n) доступу до зовнішньої пам'яті. Однак у будь-якому випадку я говорив, що: зовнішня пам'ять також може бути O (1)
адресною адресою

2
Я думаю, що однією з найбільших речей, яку імперативне програмування набуває порівняно з функціональним програмуванням, - це здатність зберігати посилання на багато різних аспектів одного стану та створювати новий стан таким чином, що всі ці посилання вказують на відповідні аспекти нового стану. Використання функціонального програмування вимагатиме заміни операцій прямого перенаправлення на операції пошуку, щоб знайти відповідний аспект певної версії поточного загального стану.
supercat

Навіть модель вказівника (O (log n) доступ до пам'яті, слабко кажучи) не є фізично реалістичною при надзвичайно великих масштабах. Швидкість світла обмежує те, наскільки швидко різні частини обчислювальної техніки можуть спілкуватися один з одним, тоді як в даний час вважається, що максимальна кількість інформації, яка може зберігатися в даній області, обмежена її площею поверхні.
dfeuer

36

Ця стаття стверджує, що всі відомі суто функціональні реалізації алгоритму об'єднання-пошуку мають гіршу асимптотичну складність, ніж та, яку вони публікують, яка має суто функціональний інтерфейс, але використовує змінні дані всередині.

Той факт, що інші відповіді стверджують, що різниці ніколи не може бути і що, наприклад, єдиний "недолік" чисто функціонального коду полягає в тому, що він може бути паралельний, дає уявлення про інформованість / об'єктивність спільноти функціональних програмувань з цих питань. .

Редагувати:

У коментарях нижче вказується, що упереджене обговорення плюсів і мінусів чистого функціонального програмування може не виходити з "спільноти функціональних програмувань". Гарна думка. Можливо, адвокати, яких я бачу, просто, цитуючи коментар, "неграмотні".

Наприклад, я думаю, що цю публікацію в блозі написав хтось, кого можна сказати, що є представником спільноти функціонального програмування, і оскільки це список "балів за ліниву оцінку", було б непоганим місцем згадати будь-який недолік, який ліниві і чисто функціональні програми можуть мати. Гарне місце було б замість наступного (технічно правдивого, але упередженого до того, що це не смішно) звільнення:

Якщо строга функція має складність O (f (n)) у строгій мові, то вона має складність O (f (n)) і в ледачій мові. Чому турбуватися? :)


4

З фіксованою верхньою межею щодо використання пам'яті, різниці не повинно бути.

Ескіз доказування: Враховуючи фіксовану верхню межу використання пам'яті, ви повинні мати змогу написати віртуальну машину, яка виконує імперативні набори інструкцій з такою ж асимптотичною складністю, як якщо б ви насправді виконували на цій машині. Це так, тому що ви можете керувати пам'яттю, що змінюється, як стійку структуру даних, даючи O (log (n)) читання та запис, але з фіксованою верхньою межею використання пам'яті, ви можете мати фіксований об'єм пам'яті, викликаючи їх розпад до O (1). Таким чином, функціональна реалізація може бути імперативною версією, що працює у функціональній реалізації VM, і тому вони повинні мати однакову асимптотичну складність.


6
Фіксована верхня межа використання пам'яті - це не те, як люди аналізують подібні речі; ви припускаєте довільно велику, але кінцеву пам'ять. Реалізуючи алгоритм, мене цікавить, як він буде масштабуватися від найпростішого вводу до будь-якого довільного розміру вводу. Якщо ви ставите фіксовану верхню межу використання пам'яті, чому б вам також не поставити фіксовану верхню межу на те, як довго ви будете дозволяти проводити обчислення, і сказати, що все є O (1)?
Брайан Кемпбелл

@ Брайан Кемпбелл: Це правда. Я просто припускаю, що якби ви цього хотіли, ви можете ігнорувати різницю постійного фактора у багатьох випадках на практиці. Ще слід пам’ятати про різницю, коли йдуть на компроміс між пам’яттю та часом, щоб переконатися, що використання m разів більше пам’яті зменшує час виконання хоча б на коефіцієнт журналу (м).
Брайан

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.