Чи існує парадигма для складання функцій «поступового оновлення» у чистому стилі потоку даних?


10

Я не знаю правильної термінології для того, щоб задати це питання, тому я опишу це з великою кількістю слів, майте на собі.

Передумови , так що ми знаходимося на одній сторінці: Програми часто містять кеші - компроміс часу / пам'яті. Поширена помилка програміста - забути оновити кешоване значення після зміни одного з його вихідних джерел / прецедентів. Але парадигма програмування потоку даних або FRP не захищена від таких помилок. Якщо у нас є кілька чистих функцій і з'єднаємо їх разом у графіку спрямованої залежності, то у вузлів може бути кешоване їх вихідне значення та повторне використання до тих пір, поки будь-який з входів функції не зміниться. Ця архітектура системи описана в статті Caching In Environment-based-data і в загальнообов’язковій мові є більш-менш аналогічною запам'ятовуванню.

Проблема : Коли один із входів для функції змінюється, ми все одно повинні виконати функцію в цілому, викинувши її кешований вихід і перерахувавши з нуля. У багатьох випадках це здається мені марнотратним. Розглянемо простий приклад, який генерує список "топ-5, що завгодно". Вхідні дані - це несортований список будь-якого. Він передається як вхід до функції, яка видає відсортований список. Що в свою чергу є входом до функції, яка приймає лише перші 5 елементів. У псевдокоді:

input = [5, 20, 7, 2, 4, 9, 6, 13, 1, 45]
intermediate = sort(input)
final_output = substring(intermediate, 0, 5)

Складність функції сортування становить O (N log N). Але врахуйте, що цей потік використовується в додатку, де введення лише трохи змінюється за один раз, додаючи 1 елемент. Замість того, щоб переробляти з нуля кожен раз, було б швидше, власне O (N), використовувати функцію, яка оновлює старий відсортований відсортований список, вставляючи новий елемент у правильне положення. Це лише один приклад - багато функцій "з нуля" мають такі аналоги "поступового оновлення". Крім того, можливо, щойно доданий елемент навіть не з’явиться у final_output, оскільки він знаходиться після 5-ї позиції.

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

Питання : Чи можлива наявність системи / архітектури / парадигми / мета-алгоритму, яка може підтримувати як функції FromScratch, так і їх інкрементальні аналоги, співпрацюючи за ефективністю та складаючись у великі потоки? Якщо ні, то чому? Якщо хтось уже дослідив цю парадигму і опублікував її, як вона називається, і чи можу я отримати короткий підсумок того, як вона працює?


До речі, у конкретному випадку вашого прикладу ще більш ефективним рішенням буде використання купи . Вставлення елемента тепер просто , а генерування оновленого відсортованого списку найвищих значень тепер просто . O(logn)kO(klogn)
j_random_hacker

Відповіді:


7

Це поле було винайдено багато разів і підпадає під багатьма назвами, такими як:

(І, можливо, більше.) Вони не однакові, але пов'язані між собою.

Перефразовуючи Cai та ін. (1): Є два основні способи загальної реалізації алгоритмів в Інтернеті (тобто без посилання на якусь конкретну алгоритмічну проблему):

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

  • Динамічна інкременталізація. Динамічні підходи створюють графіки динамічної залежності, поки програма працює і розповсюджує зміни по цих графах. Найвідоміший підхід - це самокоригування обчислення Acar. Ключова ідея проста: програми виконуються на вихідному вході в розширеному середовищі виконання, що відстежує залежності між значеннями в графіку динамічної залежності; проміжні результати кешуються. (Як ви можете собі уявити, це, як правило, використовує багато пам'яті, і багато досліджень у цій галузі стосуються обмеження використання пам'яті.) Пізніше зміни вхідних даних поширюються через графіки залежності від змінених входів до результатів, оновлюючи як проміжні, так і кінцеві результати; ця обробка часто є більш ефективною, ніж перерахунок. Однак створення графіків динамічної залежності накладає великі накладні витрати з постійним фактором під час виконання, коливаючись від 2 до 30 у повідомлених експериментах.

Крім того, завжди можна спробувати «підібрати вручну» онлайн-версію заданого алгоритму. Це може бути складно.


(1) Y. Cai, PG Giarrusso, T. Rendel, K. Ostermann, The Theory of Changes for High -Order Languages: Поглиблення λ-обчислень за допомогою статичної диференціації .


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