Віддалена памʼять - клас памʼяті, дані якого зберігаються на пристроях з часом доступу більшим ніж у оперативної памʼяті (диски, віддалені вузли - у цій роботі розглядається останнє) та методи які забезечують доступ до цих даних з рівнем затримки, відмовостійкістю та легкістю використання прийнятним для використання у прикладному програмному забезпеченні.
Ціллю віддаленої памʼяті є підвищення рівню використання оперативної памʼяті у датацентрах (у сучасному датацентрі рівень використання RAM становить близько 60%). Більш високий рівень використання памʼяті забезпечується наданням доступу до памʼяті вузлів з вільною памʼяттю вузлам які її можуть використати.
Віддалена памʼять є актуальною навіть при віртуалізації та надмірній підписці (oversubscription) ресурсів, тому що вільна памʼять залишається навіть при дуже ефективному планувальнику задач. Крім цього, використання віддаленої памʼяті дозволяє працювати з обсягом даних що перевищує фізичний обʼєм памʼяті на вузлі без значних змін у код програмного забезпечення.
Для прикладного програмного забезпечення, в яке інтегрована віддалена памʼять, максимізувати частку даних що зберігається у віддаленій памʼяті при умові дотримання вимог швидкодії.
Наприклад, цікаво розглянути популярне в даний момент часу програмне забезпечення для генерації тексту за допомогою великих мовних моделей (LLM). Інтеграція віддаленої памʼяті у цьому випадку є привабливою через його особливості: необхідність тримати у опретивній памʼяті великий обʼєм даних (тільки ваги нейронної мережі займають десятки гігабайт), не до усіх даних потрібен доступ одночасно, але у запитах до памʼяті є певні закономірності, під які можна оптимізувати параметри работи віддаленої памʼяті. Якщо взяти просту реалізацію Llama2-7B, то час обробки запиту (генерації токену тексту) становить 4.95c у середньому, при використанні приблизно 26Гб оперативної памʼяті. При умові що час обробки запиту не повинен погіршитись більше ніж на 10%, то задача віддаленої памʼяті у цьому випадку - мінімізувати використання оперативної памʼяті на вузлі, при цьому час обробки запиту не повинен перевищити 5.45c.
Крім цього, можна розглянути програмне забезпечення що виконує аналітику на великому обʼємі даних (наприклад, у AIFM для оцінки роботи використовується аналіз даних поїздок таксі на датасеті розміром ~16Гб). У цьому випадку, віддалена памʼять дозволяє обробляти більше даних ніж обʼєм оперативної памʼяті на одному вузлі. У доступі до даних зазвичай є закономірності, які можна використовувати, а вимоги до швидкодії для такого програмного забезпечення не є жорсткими.
Нижче наведені підзадачі які потрібно виіршити для реалізації віддаленої памʼяті у порядку їх важливості.
Затримка доступу до памʼяті має прямий вплив на швидкодію програмного забезпечення, тому її потрібно мінімізувати. Час читання даних з оперативної памʼяті нижчий за час читання даних по мережі, тому зниження затримки базується на тому, що потрібні дані вчасно переміщуються з памʼяті віддалених вузлів до оперативної памʼяті.
Способи зниження затримки, які можна розглянути для використання:
- групування обʼєктів таким чином, щоб обʼєкти доступ до яких відбувається частіше, знаходились в "гарячих сторінках (spans)". Обʼєкти, доступ до яких відбувається рідше, попадають у "холодні сторінки". Таким чином, у локальній памʼяті знаходиться більше гарячих обʼєктів і кількість запитів до інших вузлів знижається. Такий підхід використовується у Carbink, де окремий потік переміщує обʼєкти між локальними сторінками для більш ефективного групування.
- запит сторінок наперед. Наприклад у AIFM структури даних оптимізвані завчасно завантажувати наступні сторінки. Наприклад, у масиві або списку під час ітерації завантажується наступни сторінки.
- зниження фрагментації. При більш щільному розміщенні обʼєктів у сторінках, кількість сторінок що потрібно держати у памʼяті знижується, що також позитивно впливає на затримку. У Carbink це вирішується за допомогою використання size classes для обʼєктів, як у TCMalloc. Крім цього, розповсюдженим підходом є compaction, тобто пересення обʼєктів з менш завантажених на більш завантажені сторінки.
Існуючі реалізації спираються на прості евристики: рахування кількості доступів до обʼєктів для їх групування, запит наступної сторінки для структури даних. Розвитком цього може бути використання більш складних моделей для керування групуванням обʼєктів, переміщення сторінок у віддалену памʼять та з неї, вирішення проблеми фрагментації. Методи які слід розглянути: евристичні підходи, побудова FSM за зібраною статистикою, ML моделі (у тому числі RNN) та ін.
Також привабливим є збір статистики під час роботи програмного забезпечення та оптимізація моделей у реальному часі на її основі. Зібрана статистика може використовуватись як для побудови моделей, оптимізації їх гіперпараметрів під час роботи а також для оцінки якості роботи віддаленої памʼяті. Такий підхід використовується наприклад у "Software-defined far memory in warehouse-scale computers", де зібрана статистика використовується для оптимізації параметрів zswap (віддалена памʼять у цьому випадку - памʼять на диску, а не на віддалених вузлах).
Оскільки сторінки памʼяті зберігаються на віддалених вузлах, то віддалені вузли становляться частиною домену збою (failure domain) для програмного забезпечення, у яке інтегрована віддалена памʼять. Для того, щоб обмежити негативний вплив на надійність програмного забезпечення, можна використовувати наступні методи для сторінок памʼяті у віддаленій памʼяті:
- копія памʼяті на диску. При відмові віддаленого вузла, відновлення даних відбувається з диску. Недоліком цього підходу є повільне відновлення, та необхідність доступу до диску.
- реплікація. Сторінки памʼяті копіюються на декілька вузлів. При відмові одного з них, дані відновлюються з будь-якого з інших. Недоліком є надмірне використання памʼяті (більше на фактор реплікації).
- кодування стиранням (erasure coding). Наприклад, використовується код Ріда-Соломона для кодування сторінки у 5 частин (3 data shards, 2 parity shards). Ці частини даних розміщуються на різних вузлах, при виході з ладу будь-якого з них, дані можна відновити з інших вузлів. На відміну від реплікації, використовує менше памʼяті для забезпечення надлишковості для відновлення. Кількість частин даних може бути обрана користувачем в залежності від вимог до відмовостікйості.
Розміщення частин даних на різних вузлах також дозволяє знизити час доступу до данних, оскільки достатньо отримати дані лише з частини вузлів для відновлення сторінки памʼяті у локальній памʼяті.
Для інтеграції у нове програмне забезпечення (те, де є можливість змінювати реалізацію) доцільним є використання розумних покажчиків (з існуючих реалізацій так робить Carbink та AIFM). В межах цієї роботи створюється бібліотека на мові програмування Rust, яка надає можливість розробнику обирати які дані будуть зберігатися у віддаленій памʼяті. Бібліотека керує переміщенням даних у та з віддаленої памʼяті автоматично. Створення реалізацій структур даних призначених для роботи з віддаленою памʼяттю (як у AIFM) не розглядається, оскільки їх використання можна уникнути, якщо автоматичне завантаження сторінок паʼяті працює достатньо ефективно.
Для інтеграції у існуюче програмне забезпечення, або те, яке написане на інших мовах програмування можна використовувати механізм підкачки (swapping) памʼяті у операційній системі. На відміну від звичайного swap, який розміщується на диску, в цьому випадку swap розміщується на віртуальному блоковому пристрої, блоки якого відповідають сторінкам у віддаленій памʼяті. Реалізація блокового пристрою використовує ту ж реалізацію переміщення сторінок між локальною та віддаленою памʼяттю, що і для інтеграції на основі розмуних покажчиків.
Коли під час роботи програмного забезпечення виникає потреба звільнити локальну памʼять через переміщення даних у віддалену (swap out), то системі потрібно обрати які саме блоки памʼяті будуть переміщені. Ефективним є переміщення тих блоків, доступ до яких не очікується у найближчий час (холодні дані). Крім цього, система у фоновому режимі обирає які блоки памʼяті перемістити у локальну памʼять (swap in) до того, як вони будуть потрібні (prefetching).
Якщо завчасне переміщення блоків памʼяті працює максимально ефективно та потрібні дані завжди потрапляють у локальну памʼять до того, як доступ до них буде потрібен, то вплив на швидкодію буде мінімальним (так як уникається блокування виконання програмного забезпечення через очікування даних з віддаленої памяʼті).
В залежності від того, як програмне забезпечення працює з памʼяттю, можливість коректно визначати завчасно доступ до блоків памʼяті може бути обмеженою. Кожен доступ до даних, яких немає у локальній памʼяті уповільнує виконання. Тому ціллю є зниження кількості таких випадків.
У цій роботі не накладається ніяких обмежень на програмне забезпечення, в яке інтегрується віддалена памʼять. Але чим більше закономірностей у доступі до даних, тим більш ефективною буде віддалена памʼять. Також для інтеграції віддаленої памʼяті краще підходить програмне забезпечення яке виконує багато обчислень (інших операцій) на кожен доступ до памʼяті.
Вхідні дані:
\(S_{n}\) - блок памʼяті до якого відбувся доступ під час виконання програми (ідентифікується номером).
\(T_{n}\) - час коли відбувся доступ до блоку памʼяті з моменту запуску програми.
Вхідні дані містять інформацію про доступ до блоків памʼяті як з поточного, так і з попередніх запусків програми.
Вихідні дані:
\(P_{n}\) - коефіцієнти що відповідають ймовірностям доступу до відповідних блоків памʼяті у наступну одиницю часу.
Блоки з найбільшим значенням коефіцієнту слід першою чергою переміщати у локальну памʼять у фоновому режимі. Блоки з найнижчим - навпаки, переміщувати у віддалену памʼять.
Можливі методи вирішення:
- евристичний підхід - наприклад, рахувати кількість доступів у деякому вікні часу для визначення гарячих та холодних блоків памʼяті.
- побудова скінченного автомату (недетрмінованого) - станами можуть бути наприклад запити до блоків памʼяті, переходи між ними - послідовність доступів. Передбачення визначається поточним станом та вагою на ребрах.
- стохастичні моделі (Марковська модель) - моделювання системи на основі поточного стану та попередньої послідовності подій (доступів до даних).
- моделі машинного навчання (згорткові нейронні мережи, трансформери та ін.) - застосування таке ж, як до задачі передбачення послідовності.
- carbink - найбільш розвинена реалізація. Має закритий код, привʼязана до інфраструктури Google та не є доступною для використання ззовні. Використовує прості евристики для оптимізації розташування обʼєктів у памʼяті. Не має методів інтеграції без зміни коду програмного забезпечення.
- hydra - вимагає використання спеціалізованого апаратного забезпечення (rdma).
- aifm - робота з одним віддаленим вузлом, не забезпечує відмовостійкість.
- far memory in warehouse scale computers - використовує zswap для зберігання памʼяті на диску, а не у оперативній памʼяті віддалених вузлів.