
Вступление
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 раза без каких-либо потерь.
Итоговые рекомендации
Используйте ROCm. Если у вас карта AMD, забудьте про Vulkan для LLM. Вы теряете до 50% производительности.
Крутите настройки. Для моделей до 8B параметров ставьте
Max Concurrent Predictions = 8. Это бесплатно даст вам +50% скорости, если потеря 20-30% TPS на отдельный запрос для вас не критична.Выбирайте модель под задачу:
Для массового сервиса (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 просто коллосальное и подобрать что-то под себя не составит труда), и просто включить сервер. Это многократно снижает порог вхождения в работу и разработки с локальными моделями.
