Вступление

27 января вышла LM Studio версии 0.4.0 и это обновление принесло долгожданную функцию параллельной обработки запросов через continuous batching. Это критически важное обновление для production-использования локальных LLM, которое обещает значительное увеличение пропускной способности. Теперь можно не просто "крутить модельку для себя", а разворачивать реальные multi-user сервисы.

Но как это работает на практике? Я провел комплексное исследование на своем домашнем ПК, сравнив производительность ROCm и Vulkan, а также влияние количества потоков на пропускную способность (TPS).

Спойлер: Разница между ROCm и Vulkan оказалась шокирующей — до 2 раз в пользу ROCm, а правильная настройка потоков дает +50% бесплатной производительности.

Что изменилось в LM Studio 0.4

До версии 0.4.0 LM Studio обрабатывал запросы последовательно — каждый новый запрос вставал в очередь и ожидал завершения предыдущего. Версия 0.4 на базе llama.cpp 2.0.0 внедряет continuous batching, позволяющий обрабатывать до N запросов параллельно (по умолчанию 4).

Ключевые параметры:​

  • Max Concurrent Predictions — максимальное количество одновременных запросов

  • Unified KV Cache — динамическое распределение ресурсов между запросами без жесткого разделения

Методология тестирования

В этом тесте я использовал метрику TPS (Tokens Per Second), так как она честнее отражает пропускную способность сервера под нагрузкой.

Конфигурация:

  • GPU: AMD Radeon RX7800XT 16Гб (тесты на ROCm и Vulkan)

  • CPU: AMD Ryzen 5700X3D

  • RAM: 64Гб 3200МГц

  • OS: Windows 11

  • Сервер: LM Studio 0.4.0 (Local API), 4, либо 8 параллельными потоками

  • Нагрузка: Асинхронные запросы (Python aiohttp) с конкуренцией от 1 до 64 потоков​ одновременно

  • Промпт: Генерация короткого стихотворения

Тестовый стенд

Для стресс-тестирования я использовал асинхронный подход на Python с библиотекой aiohttp, отправляя все запросы одновременно.

import asyncio
import aiohttp
import time

async def fetch_tokens(session, url, model, prompt):
    """Выполняет одиночный запрос к LM Studio API"""
    payload = {
        "model": model,
        "system_prompt": "You are a helpful assistant.",
        "input": prompt
    }
    start_time = time.perf_counter()

    async with session.post(url, json=payload) as response:
        data = await response.json()
        end_time = time.perf_counter()

        total_time = end_time - start_time
        stats = data.get("stats", {})
        output_tokens = stats.get("total_output_tokens", 0)

        return {
            "tokens": output_tokens,
            "time": total_time,
            "tps": output_tokens / total_time if total_time > 0 else 0
        }

async def run_benchmark(url, model, prompt, concurrency):
    """Запускает параллельные запросы и собирает метрики"""
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_tokens(session, url, model, prompt) for _ in range(concurrency)]
        results = await asyncio.gather(*tasks)

    # Анализ результатов
    successful = [r for r in results if r is not None]
    total_tokens = sum(r['tokens'] for r in successful)
    batch_wall_time = max(r['time'] for r in successful)
    total_tps = total_tokens / batch_wall_time

    print(f"Concurrency: {concurrency}")
    print(f"  Total TPS: {total_tps:.2f}")
    print(f"  Success Rate: {len(successful)/concurrency:.1%}")

    return total_tps

# Использование
async def main():
    url = "http://localhost:8000/api/v1/chat"
    model = "qwen3-vl-2b-instruct@q8_0"
    prompt = "Write a 50-word poem about artificial intelligence."

    for concurrency in [1, 2, 4, 8, 16, 32, 64]:
        await run_benchmark(url, model, prompt, concurrency)

asyncio.run(main())

Тестируемые модели

Я протестировал пять различных конфигураций:​

Модель

Параметры

Архитектура

Кванцизация

Qwen3 0.6B

0.6B

Dense

Q8_0

Qwen3 VL 2B

2B

Vision-Dense

Q8_0

Ministral 3B

4B

Dense

Q8_0

Qwen3 4B 2507

4B

Dense

Q8_0

Ministral 8B

8B

Dense

Q8_0

Nemotron 9B

9B

Dense

Q4_K_M

GPT OSS 20B

20B

MoE

MXFP4

Метрики производительности

  • Общий TPS = сумма всех токенов генерации / время выполнения пачки

  • TPS на запрос = общий TPS / количество параллельных запросов в LMStudio

  • Рост эффективности = общий TPS / TPS при одном запросе

  • Среднее время до 1 токена = сумма TTFT всех запросов / количество успешных запросов

Результаты тестов

Самый наглядный результат (Qwen3 VL 2B, ROCm, 8 параллельных запросов)

Requests

Total TPS

TPS / req

Эффективность

Avg TTFT

1

84.21

84.21

1.00x

0.054s

2

182.27

91.14

2.16x

0.026s

4

331.43

82.86

3.94x

0.030s

8

484.20

60.52

5.75x

0.038s

16

564.01

70.50

6.70x

0.033s

32

597.13

74.64

7.09x

0.035s

64

609.52

76.19

7.24x

0.037s

Как можно заметить, TPS относительно 1 запроса вырос в 7+ раз, при этом средний TPS на запрос не сильно упал: с 84 до 76, что при работе будет практически незаметно.

Теперь перейдем к ключевым инсайтам.

Инсайт №1: ROCm уничтожает Vulkan

Для владельцев карт AMD выбор бэкенда является критическим. ROCm не просто быстрее — он находится в другой лиге.​

Модель

ROCm Peak TPS

Vulkan Peak TPS

Разница

Ministral 3B

455

246

+85% 🚀

Ministral 8B

266

133

+100% 🚀

Qwen 4B

201

103

+95% 🚀

GPT-OSS 20B

122

118

+3%

Вывод: На моделях среднего размера (3-8B) ROCm дает двукратный прирост производительности. Vulkan конкурентоспособен только на очень крупных моделях, где упор идет в память, а не в вычисления. Более того, Vulkan показал низкую стабильность на 20B модели под нагрузкой (в тесте на 64 параллельных запроса Vulkan успешно обратотал всего 48% запросов против 64% у ROCm).

Инсайт №2: Магия 8 потоков

В настройках LM Studio (при загрузке модели) есть параметр Max Concurrent Predictions. По умолчанию он равен 4. Я проверил, что будет, если увеличить его до 8.​

Результат (ROCm):

  • Ministral 3B: 315 TPS → 455 TPS (+44%)

  • Ministral 8B: 177 TPS → 266 TPS (+50%)

  • Qwen VL 2B: 420 TPS → 610 TPS (+45%)

Просто изменив одну цифру в конфиге, мы получаем на 50% больше токенов в секунду. Это снижает TPS каждого отдельно взятого запроса, но с учетом производительности малых моделей это может быть не так критично.

Например у Qwen VL 2B средний TPS снизился со 100 до 76, что с учетом роста параллельной обработки с 4 до 8 запросов небольшая потеря

Инсайт №3: Масштабируемость и "стена" батчинга

Как разные модели реагируют на увеличение числа одновременных пользователей?

Малыши (0.6B - 2B) — Короли трафика

Модель Qwen VL 2B показала феноменальную масштабируемость. Это идеальный кандидат для высоконагруженных микросервисов.​

  • На 1 запросе: 85 TPS

  • На 64 запросах: 610 TPS (Efficiency Gain 7.24x)

При этом Qwen3 0.6B несмотря на меньший размер не показал такого значительного прироста эффективности как ожидалось, так как средний TPS с 178 для одного запроса упал до 45 среднего при 4 параллельных запросах. Вероятно, у этой модели есть какие-то архитектурные ограничения, которые не позволяют ей так хорошо масштабироваться.

Середнячки (3B - 8B) — Золотая середина

Ministral 3B отлично держит нагрузку до 16 пользователей, выдавая 455 TPS. Дальше наступает плато — GPU загружен полностью. При 64 запросах TPS сохраняется на уровне 444, что дает комфортные 55 средних TPS на одного пользователя при 8 параллельных пользователях.

Тяжеловесы (9B - 20B) — Батчинг практически не работает

Для GPT-OSS 20B и Nemotron 9B прирост от параллелизма минимален (1.2x - 1.8x).

  • Для Nemotron 9B, скорее всего проблемой является архитектура самой модели, так как она значительно медленнее работает по сравнению с другими 9B моделями в целом

  • Для GPT-OSS 20B, скорее всего проблемой является уже недостаток доступной видеопамяти, так как модель сама по себе уже занимает более 12Гб, от чего ее масштабирование ограничено потребительским железом.

Инсайт №4: CPU — практически не теряет скорости

Сравнение Qwen VL 2B на CPU и GPU (ROCm) показывает пропасть в производительности:​

  • CPU: 46 TPS (пик)

  • GPU (ROCm): 420 TPS (пик)

Разница в 9 раз. Даже мощный CPU не годится для реальной многопользовательской нагрузки.

Однако, стоит отметить, что производительность 1 потока на CPU составила 11 TPS, а при 4 параллельных запроса средний TPS упал всего лишь до 10.

Это означает, что если ваша задача не требует обработки в реальном времени, батчинг на CPU позволит вам увеличить скорость обработки данных практически в 4 раза без каких-либо потерь.

Итоговые рекомендации

  1. Используйте ROCm. Если у вас карта AMD, забудьте про Vulkan для LLM. Вы теряете до 50% производительности.​

  2. Крутите настройки. Для моделей до 8B параметров ставьте Max Concurrent Predictions = 8. Это бесплатно даст вам +50% скорости, если потеря 20-30% TPS на отдельный запрос для вас не критична.​

  3. Выбирайте модель под задачу:

  • Для массового сервиса (30+ юзеров): модели до 2B (до 600 TPS)

  • Для более сложных задач требующих больших способностей от модели (10-15 юзеров): модели до 8B (до 260-450 TPS)

  • Модели более 8B все еще остаются привилегией серверов и подходят максимум для параллельной обработки 2 запросов одновременно.

Заключение

Релиз LM Studio 0.4.0 становится революционным, если говорить относительно упрощения запуска "домашнего API сервера" с LLM. Официальное добавление в январе этого года поддержки ROCm под Windows от AMD становится вишенкой на этом торте, так как позволяет до 2 раз увеличить скорость работы параллельных запросов в LM Studio 0.4.0.

Таким образом, теперь, чтобы запустить свой сервер с LLM нужно всего лишь скачать LM Studio 0.4.0, загрузить небольшую модель и просто включить сервер.

Ключевая революционность этого заключается в том, что теперь нет необходимости устанавливать Ubuntu, приобретать железо от NVIDIA с поддержкой CUDA, заморачиваться установкой VLLM (что для владельцев AMD та еще головная боль), искать модели с AWQ квантованием (а это тоже достаточно нетривиальная задача порой), если у вас BF16 просто не влазит.

Теперь , чтобы запустить свой сервер с LLM нужно всего лишь скачать LM Studio 0.4.0, загрузить небольшую модель (а выбор у вас будет большой, так как количество GGUF моделей под LMStudio на Hugging Face просто коллосальное и подобрать что-то под себя не составит труда), и просто включить сервер. Это многократно снижает порог вхождения в работу и разработки с локальными моделями.

Ссылки: Таблица с детальными результатами