Aivaro
  • Оглавление
  • Вопросы
  • Практика
  • Вики
  • Материалы сообщества
  • Тесты
  • Поиск
✈Telegram @ai_varo
RUEN中文
…
Оглавление/Вопросы/#959

Как деплоить несколько LoRA адаптеров без перезагрузки базовой модели (Punica, S-LoRA)?

Краткий тезис

Традиционный деплой LoRA-адаптеров требует перезагрузки базовой модели при каждой смене адаптера, что неприемлемо для мультитенантных сценариев. Решения S-LoRA и Punica позволяют одновременно обслуживать множество адаптеров в рамках одного батча без перезагрузки весов, а начиная с 2024 года поддержка множественных LoRA встроена в vLLM. Ключевые механизмы — динамическое переключение адаптеров на уровне батча и специализированные CUDA-ядра для эффективного применения LoRA-матриц.

-----|----------------------|--------------------------|--------| | Наивный | Полная перезагрузка | Нет | O(N) на адаптер | | S-LoRA | Динамическое переключение в батче | Да | O(1) на адаптер + кэш | | Punica | CUDA-ядра для параллельного LoRA | Да | O(1) на адаптер | | vLLM + LoRA | Встроенный менеджер адаптеров | Да | O(1) на адаптер |


2. S-LoRA: batch inference с разными адаптерами

S-LoRA (Serving Multiple LoRA Adapters) — система, предложенная в 2023 году (Chen et al.), которая решает проблему мультиадаптерного обслуживания.

2.1. Архитектура

  • Unified Paging — единое адресное пространство для ключей/значений (KV-cache) всех адаптеров. Позволяет эффективно управлять памятью при переключении.
  • Dynamic LoRA Scheduling — на этапе формирования батча система группирует запросы по идентификатору адаптера, но не ждёт, пока наберётся полный батч для одного адаптера. Вместо этого она использует блочное переключение: каждый блок батча может содержать запросы от разных адаптеров.
  • S-LoRA Kernel — оптимизированное CUDA-ядро, которое применяет LoRA-матрицы к скрытым состояниям с учётом того, что разные запросы в батче могут иметь разные адаптеры. Ядро загружает веса адаптера из кэша L2/L1 по мере необходимости.

2.2. Преимущества

  • Почти нулевые накладные расходы на переключение (менее 2% от времени инференса).
  • Поддержка до тысяч адаптеров одновременно.
  • Совместимость с любыми базовыми моделями (LLaMA, GPT и др.).

2.3. Ограничения

  • Требует модификации ядра внимания и FFN.
  • Не поддерживает динамическое добавление адаптеров без остановки сервера (но может быть расширена).

3. Punica: CUDA kernels для параллельного LoRA

Punica (Punica: Multi-Tenant LoRA Serving) — ещё один подход, фокусирующийся на эффективных CUDA-ядрах для параллельного применения LoRA.

3.1. Ключевая идея

Вместо того чтобы переключать адаптеры на уровне батча, Punica предлагает многопоточное применение LoRA внутри одного ядра. Для каждого запроса в батче ядро загружает соответствующие LoRA-матрицы (A и B) и выполняет x = x + (x @ A) @ B с учётом того, что A и B могут быть разными для разных элементов батча.

3.2. Технические детали

  • Segmented Gather/Scatter — веса адаптеров хранятся в непрерывном буфере, а ядро использует индексы для выбора нужных строк/столбцов.
  • Fused Kernel — объединение LoRA-преобразования с основным линейным слоем базовой модели, что снижает количество обращений к памяти.
  • Поддержка произвольного ранга — ядро работает для любого r (ранга LoRA) без перекомпиляции.

3.3. Сравнение с S-LoRA

ХарактеристикаS-LoRAPunica
Управление KV-cacheUnified PagingСтандартный paged attention
Переключение адаптеровНа уровне блоков батчаНа уровне отдельных запросов
ПроизводительностьВыше при большом числе адаптеров (>100)Выше при малом числе адаптеров (<10)
Сложность интеграцииТребует замены всего движкаМожет быть встроена в существующие системы

4. vLLM + LoRA с 2024

Начиная с версии 0.4.0 (2024), vLLM получил встроенную поддержку множественных LoRA-адаптеров, объединив идеи S-LoRA и Punica.

4.1. Как это работает

  • LoRA Manager — компонент, который загружает все адаптеры в память при старте сервера.
  • Dynamic LoRA Selection — каждый запрос может содержать поле lora_name или lora_id. vLLM автоматически подставляет нужные веса при обработке батча.
  • Paged LoRA Weights — веса адаптеров хранятся в страничной памяти, что позволяет обслуживать сотни адаптеров без дублирования.
  • Поддержка S-LoRA Kernel — vLLM использует оптимизированные ядра для применения LoRA, аналогичные S-LoRA.

4.2. Пример конфигурации

from vllm import LLM, SamplingParams

# Загрузка базовой модели и списка адаптеров
llm = LLM(
    model="meta-llama/Llama-2-7b-hf",
    enable_lora=True,
    max_loras=32,  # максимальное количество одновременно загруженных адаптеров
    max_lora_rank=64,
    lora_extra_vocab_size=0
)

# Инференс с разными адаптерами
prompts = [
    {"prompt": "Hello", "lora_name": "adapter1"},
    {"prompt": "World", "lora_name": "adapter2"},
]
outputs = llm.generate(prompts, sampling_params=SamplingParams())

4.3. Ограничения

  • Требуется vLLM >= 0.4.0.
  • Не все модели поддерживают LoRA (трансформеры с attention).
  • При очень большом числе адаптеров (>1000) может потребоваться дополнительная настройка памяти.

5. Пет-проект для закрепления

Задача: Развернуть два LoRA-адаптера для одной базовой модели (например, mistralai/Mistral-7B-v0.1) с помощью vLLM и протестировать параллельный инференс.

Инструменты:

  • Python 3.10+
  • vLLM >= 0.4.0
  • Hugging Face Transformers + PEFT (для создания адаптеров)
  • Docker (опционально)

Шаги:

  1. Создать два простых LoRA-адаптера с помощью PEFT (например, на датасетах imdb и sst2).
  2. Сохранить адаптеры в формате Hugging Face (папки adapter1, adapter2).
  3. Запустить vLLM сервер с параметрами --enable-lora --max-loras 2.
  4. Отправить два запроса с разными lora_name через OpenAI-совместимый API.
  5. Измерить время ответа и убедиться, что оба запроса обработаны в одном батче (проверить логи).

Ожидаемый результат:

  • Сервер обрабатывает запросы одновременно, без перезагрузки модели.
  • Время ответа для двух запросов примерно равно времени одного (с учётом накладных расходов на LoRA).
  • Можно добавить третий адаптер и убедиться, что система масштабируется.

Связь с другими вопросами

ВопросТема
952Основы LoRA: низкоранговая адаптация

Навигация

  • Предыдущий: 958
  • Следующий: 960
  • Индекс: 00. Индекс разборов