- BrainTools - https://www.braintools.ru -

27 января вышла LM Studio версии 0.4.0 и это обновление принесло долгожданную функцию параллельной обработки запросов через continuous batching. Это критически важное обновление для production-использования локальных LLM, которое обещает значительное увеличение пропускной способности. Теперь можно не просто “крутить модельку для себя”, а разворачивать реальные multi-user сервисы.
Но как это работает на практике? Я провел комплексное исследование на своем домашнем ПК, сравнив производительность ROCm и Vulkan, а также влияние количества потоков на пропускную способность (TPS).
Спойлер: Разница между ROCm и Vulkan оказалась шокирующей — до 2 раз в пользу ROCm, а правильная настройка потоков дает +50% бесплатной производительности.
До версии 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 всех запросов / количество успешных запросов
|
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, что при работе будет практически незаметно.
Теперь перейдем к ключевым инсайтам.
Для владельцев карт 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 конкурентоспособен только на очень крупных моделях, где упор идет в память [1], а не в вычисления. Более того, Vulkan показал низкую стабильность на 20B модели под нагрузкой (в тесте на 64 параллельных запроса Vulkan успешно обратотал всего 48% запросов против 64% у ROCm).
В настройках 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 запросов небольшая потеря
Как разные модели реагируют на увеличение числа одновременных пользователей?
Модель Qwen VL 2B показала феноменальную масштабируемость. Это идеальный кандидат для высоконагруженных микросервисов.
На 1 запросе: 85 TPS
На 64 запросах: 610 TPS (Efficiency Gain 7.24x)
При этом Qwen3 0.6B несмотря на меньший размер не показал такого значительного прироста эффективности как ожидалось, так как средний TPS с 178 для одного запроса упал до 45 среднего при 4 параллельных запросах. Вероятно, у этой модели есть какие-то архитектурные ограничения, которые не позволяют ей так хорошо масштабироваться.
Ministral 3B отлично держит нагрузку до 16 пользователей, выдавая 455 TPS. Дальше наступает плато — GPU загружен полностью. При 64 запросах TPS сохраняется на уровне 444, что дает комфортные 55 средних TPS на одного пользователя при 8 параллельных пользователях.
Для GPT-OSS 20B и Nemotron 9B прирост от параллелизма минимален (1.2x – 1.8x).
Для Nemotron 9B, скорее всего проблемой является архитектура самой модели, так как она значительно медленнее работает по сравнению с другими 9B моделями в целом
Для GPT-OSS 20B, скорее всего проблемой является уже недостаток доступной видеопамяти, так как модель сама по себе уже занимает более 12Гб, от чего ее масштабирование ограничено потребительским железом.
Сравнение 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 та еще головная боль [2]), искать модели с AWQ квантованием (а это тоже достаточно нетривиальная задача порой), если у вас BF16 просто не влазит.
Теперь , чтобы запустить свой сервер с LLM нужно всего лишь скачать LM Studio 0.4.0, загрузить небольшую модель (а выбор у вас будет большой, так как количество GGUF моделей под LMStudio на Hugging Face просто коллосальное и подобрать что-то под себя не составит труда), и просто включить сервер. Это многократно снижает порог вхождения в работу и разработки с локальными моделями.
Автор: MKreGGo
Источник [3]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/24991
URLs in this post:
[1] память: http://www.braintools.ru/article/4140
[2] боль: http://www.braintools.ru/article/9901
[3] Источник: https://habr.com/ru/articles/991282/?utm_source=habrahabr&utm_medium=rss&utm_campaign=991282
Нажмите здесь для печати.