
Вступление
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 просто коллосальное и подобрать что-то под себя не составит труда), и просто включить сервер. Это многократно снижает порог вхождения в работу и разработки с локальными моделями.
Автор: MKreGGo


