Дві коробки класу DGX Spark, одна модель: копія на кожній замість розподілу

Операції

Сім тижнів наша локальна мовна модель працювала, розподілена між двома машинами NVIDIA GB10 із тензорною паралелізацією. 22 жовтня ми замінили це на повну копію моделі на кожній машині та проксі з балансуванням за найменшою кількістю з'єднань попереду. Пропускна здатність зросла з приблизно 180 до 210 токенів на секунду, і тепер будь-яка машина може перезавантажуватися, не вимикаючи модель.

Чому ми її розподіляли

Кожна машина має 128 ГБ пам'яті, яку спільно використовують процесор і графічний процесор. У вересні модель вміщалася на одній машині, але її кеш — ледь: збірка vLLM, яку ми використовували, не могла зберігати KV-кеш цієї моделі у форматі FP8, тому кеш був у BF16, і на одній машині вистачало місця для 499 110 токенів. Це менше, ніж два запити при повному контексті моделі в 262 144 токени. Розподілений між обома машинами з тензорною паралелізацією через їхнє пряме мережеве з'єднання, кеш виріс до понад трьох мільйонів токенів. Ми розподіляли модель заради місця, а не швидкості.

Що змінилося

Новіша 4-бітна збірка тієї ж моделі (NVFP4, створена за допомогою дистилляції з урахуванням квантування) займає близько 71 ГіБ пам'яті, а спільнотна збірка vLLM для GB10 (eugr/spark-vllm-b12x) зберігає її кеш у FP8. Тепер одна машина вміщує всю модель і кеш на 0,76–1,08 мільйона токенів, що дає місце для 2,9–4,1 запитів при повному контексті, залежно від того, скільки пам'яті машина їй виділяє. Обидві копії використовують власне спекулятивне декодування моделі (MTP, чотири чернеткові токени). Перед переходом ми запустили наш тест виклику інструментів на новій збірці: вона набрала 86 балів, тоді як замінена збірка — 75.

Що ми виміряли

Розподіл між двома машинамиКопія на кожній машині
KV-кешпонад 3 мільйони токенів0,76 і 1,08 мільйона токенів
Запити при повному контекстіприблизно 122,9 і 4,1
Пропускна здатність під нашим навантаженнямприблизно 180 токенів/с210 токенів/с (111 + 99)
Запускприблизно 20 хвилин5–13 хвилин на копії
Перезавантаження однієї машинимодель недоступнаінша копія обслуговує запити

Одна копія сама по собі, залежно від кількості одночасних запитів: із короткими промптами 1 запит давав 36 токенів за секунду, 4 — 82, 8 — 109, а 16 — 150. Із довшими промптами нашого поштового агента 4 давали 81, 8 — 113, а 16 — лише 87: понад вісім таких запитів уповільнювали роботу.

Протягом дня одна копія обробляла щонайбільше 12 запитів одночасно, а інша — 8. Перша генерувала 91–93 токени за секунду й завершувала 26–27 запитів за хвилину; друга — 81–83 токени за секунду й 22 запити за хвилину. Зараз обидві працюють із 12 запитами.

Від чого ми відмовилися

Місце. Роздільна модель мала кеш понад три мільйони токенів; копії мають два менші кеші, і запит може використовувати лише кеш тієї копії, яка його обслуговує. Наші агенти надсилають багато коротких і середніх запитів, тому для них пропускна здатність була важливішою. Якщо ви обслуговуєте кілька дуже довгих контекстів одночасно, розділення може бути кращим вибором. Ми зберегли налаштування з розділенням, і повернення до нього — це один скрипт.

Що пішло не так під час переходу

  1. Одинадцять хвилин без моделі, потім 30 секунд помилок 502. Роздільну модель потрібно було зупинити, перш ніж копія завантажиться на тих самих машинах, тому наші агенти чекали приблизно одинадцять хвилин. Коли перша копія запустилася, проксі ще близько 30 секунд відповідав «502 no live upstreams»: він позначив бекенди як несправні, поки вони були вимкнені (max_fails=3, fail_timeout=30s), і не пробував їх знову, доки цей час не минув.
  2. Клієнт, який обійшов проксі. В одному з наших пакетних завдань у конфігурації була адреса першої машини, тому весь його навантаження пішло на одну копію, тоді як інша мала вільну потужність. Тепер усі клієнти проходять через проксі; власні адреси машин використовуються лише для перевірки стану.
  3. Стрибки метрик. Наш монітор пропускної здатності зчитував дані vLLM з /metrics через проксі. З двома бекендами послідовні зчитування надходили від різних копій, лічильники стрибали туди-сюди, і монітор повідомляв, що модель «голодує». Тепер він зчитує дані з кожної копії безпосередньо й підсумовує їх.
  4. Старий вартовий, який зупинив би нову копію. У роздільній конфігурації був вартовий, який перезапускав службу, коли модель переставала відповідати. Нова служба оголошує Conflicts= зі старою, тому такий перезапуск зупинив би нову копію. Його потрібно було вимкнути командою systemctl disable --now, а не просто зупинити, оскільки наш операційний шар перезапускає одиниці, які увімкнені, але не працюють.
  5. Пам'ять на машині, яка виконує іншу роботу. Одна машина також запускає наші бази даних і збірки сайту. При gpu-memory-utilization 0.78 для vLLM залишалося лише 5 ГіБ для всього іншого, тому ми знизили це значення до 0.74 і перезапустили лише цю копію, поки інша тримала навантаження. На цих машинах частка пам'яті, яку ви виділяєте vLLM, береться з тієї ж пам'яті, що й для всього іншого.

Якщо у вас є дві такі машини

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

Оновлено: