far memory

Please note that most parts of documentation for this project are in Ukrainian because I am working on this in scope of my thesis at Kyiv Polytechnic Institute and I need to be able to refer to this documentation when talking to thesis supervisors and other people from the university. I will probably add English translation later.

Віддалена памʼять

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

Ціллю віддаленої памʼяті є підвищення рівню використання оперативної памʼяті у датацентрах (у сучасному датацентрі рівень використання RAM становить близько 60%). Більш високий рівень використання памʼяті забезпечується наданням доступу до памʼяті вузлів з вільною памʼяттю вузлам які її можуть використати.

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

Формалізація задачі

Для прикладного програмного забезпечення, в яке інтегрована віддалена памʼять, максимізувати частку даних що зберігається у віддаленій памʼяті при умові дотримання вимог швидкодії.

Наприклад, цікаво розглянути популярне в даний момент часу програмне забезпечення для генерації тексту за допомогою великих мовних моделей (LLM). Інтеграція віддаленої памʼяті у цьому випадку є привабливою через його особливості: необхідність тримати у опретивній памʼяті великий обʼєм даних (тільки ваги нейронної мережі займають десятки гігабайт), не до усіх даних потрібен доступ одночасно, але у запитах до памʼяті є певні закономірності, під які можна оптимізувати параметри работи віддаленої памʼяті. Якщо взяти просту реалізацію Llama2-7B, то час обробки запиту (генерації токену тексту) становить 4.95c у середньому, при використанні приблизно 26Гб оперативної памʼяті. При умові що час обробки запиту не повинен погіршитись більше ніж на 10%, то задача віддаленої памʼяті у цьому випадку - мінімізувати використання оперативної памʼяті на вузлі, при цьому час обробки запиту не повинен перевищити 5.45c.

Крім цього, можна розглянути програмне забезпечення що виконує аналітику на великому обʼємі даних (наприклад, у AIFM для оцінки роботи використовується аналіз даних поїздок таксі на датасеті розміром ~16Гб). У цьому випадку, віддалена памʼять дозволяє обробляти більше даних ніж обʼєм оперативної памʼяті на одному вузлі. У доступі до даних зазвичай є закономірності, які можна використовувати, а вимоги до швидкодії для такого програмного забезпечення не є жорсткими.

Підзадачі

Нижче наведені підзадачі які потрібно виіршити для реалізації віддаленої памʼяті у порядку їх важливості.

Зниження затримки доступу (latency)

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

затримка доступу до даних у віддаленій памʼяті

Способи зниження затримки, які можна розглянути для використання:

- групування обʼєктів таким чином, щоб обʼєкти доступ до яких відбувається частіше, знаходились в "гарячих сторінках (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). Ці частини даних розміщуються на різних вузлах, при виході з ладу будь-якого з них, дані можна відновити з інших вузлів. На відміну від реплікації, використовує менше памʼяті для забезпечення надлишковості для відновлення. Кількість частин даних може бути обрана користувачем в залежності від вимог до відмовостікйості.

розміщення частин данних на різних вузлах при використанні erasure coding

Розміщення частин даних на різних вузлах також дозволяє знизити час доступу до данних, оскільки достатньо отримати дані лише з частини вузлів для відновлення сторінки памʼяті у локальній памʼяті.

Інтеграція у існуюче та нове програмне забезпечення

Для інтеграції у нове програмне забезпечення (те, де є можливість змінювати реалізацію) доцільним є використання розумних покажчиків (з існуючих реалізацій так робить Carbink та AIFM). В межах цієї роботи створюється бібліотека на мові програмування Rust, яка надає можливість розробнику обирати які дані будуть зберігатися у віддаленій памʼяті. Бібліотека керує переміщенням даних у та з віддаленої памʼяті автоматично. Створення реалізацій структур даних призначених для роботи з віддаленою памʼяттю (як у AIFM) не розглядається, оскільки їх використання можна уникнути, якщо автоматичне завантаження сторінок паʼяті працює достатньо ефективно.

використання розумного покажчика для розміщення даних у віддаленій памʼяті

Для інтеграції у існуюче програмне забезпечення, або те, яке написане на інших мовах програмування можна використовувати механізм підкачки (swapping) памʼяті у операційній системі. На відміну від звичайного swap, який розміщується на диску, в цьому випадку swap розміщується на віртуальному блоковому пристрої, блоки якого відповідають сторінкам у віддаленій памʼяті. Реалізація блокового пристрою використовує ту ж реалізацію переміщення сторінок між локальною та віддаленою памʼяттю, що і для інтеграції на основі розмуних покажчиків.

Задача вибору блоків памʼяті для переміщення

page replacement algorithm

задача заміщення сторінок

Коли під час роботи програмного забезпечення виникає потреба звільнити локальну памʼять через переміщення даних у віддалену (swap out), то системі потрібно обрати які саме блоки памʼяті будуть переміщені. Ефективним є переміщення тих блоків, доступ до яких не очікується у найближчий час (холодні дані). Крім цього, система у фоновому режимі обирає які блоки памʼяті перемістити у локальну памʼять (swap in) до того, як вони будуть потрібні (prefetching).

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

В залежності від того, як програмне забезпечення працює з памʼяттю, можливість коректно визначати завчасно доступ до блоків памʼяті може бути обмеженою. Кожен доступ до даних, яких немає у локальній памʼяті уповільнує виконання. Тому ціллю є зниження кількості таких випадків.

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

Вхідні дані:

\(S_{n}\) - блок памʼяті до якого відбувся доступ під час виконання програми (ідентифікується номером).

\(T_{n}\) - час коли відбувся доступ до блоку памʼяті з моменту запуску програми.

Вхідні дані містять інформацію про доступ до блоків памʼяті як з поточного, так і з попередніх запусків програми.

Вихідні дані:

\(P_{n}\) - коефіцієнти що відповідають ймовірностям доступу до відповідних блоків памʼяті у наступну одиницю часу.

приклад роботи моделі, яка визначає запит на доступ до яких блоків памʼяті може бути отриманий під час подальшого виконання програмного забезпечення

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

Можливі методи вирішення:

- евристичний підхід - наприклад, рахувати кількість доступів у деякому вікні часу для визначення гарячих та холодних блоків памʼяті.

- побудова скінченного автомату (недетрмінованого) - станами можуть бути наприклад запити до блоків памʼяті, переходи між ними - послідовність доступів. Передбачення визначається поточним станом та вагою на ребрах.

- стохастичні моделі (Марковська модель) - моделювання системи на основі поточного стану та попередньої послідовності подій (доступів до даних).

- моделі машинного навчання (згорткові нейронні мережи, трансформери та ін.) - застосування таке ж, як до задачі передбачення послідовності.

приклад роботи програмного забезпечення, де помітна закономірність у доступі до блоків памʼяті

Існуючі реалізації та їх недоліки

- carbink - найбільш розвинена реалізація. Має закритий код, привʼязана до інфраструктури Google та не є доступною для використання ззовні. Використовує прості евристики для оптимізації розташування обʼєктів у памʼяті. Не має методів інтеграції без зміни коду програмного забезпечення.

- hydra - вимагає використання спеціалізованого апаратного забезпечення (rdma).

- aifm - робота з одним віддаленим вузлом, не забезпечує відмовостійкість.

- far memory in warehouse scale computers - використовує zswap для зберігання памʼяті на диску, а не у оперативній памʼяті віддалених вузлів.

Посилання

The Unsafe Rust Programming Language