Когда 1 триллион параметров помещается в оперативку
Это звучит как шутка. Или безумие. Или и то, и другое сразу. Но на 06.02.2026 это реальность: модель Kimi-k2.5 с 1.03 триллионами параметров работает на обычном CPU. Без видеокарт. Без специализированных ускорителей. Просто AMD EPYC 9175F и 512 ГБ оперативной памяти.
Секрет? Квантование. Тот самый трюк, который превращает гигантские модели в что-то управляемое. Но не простое Q4, а Q4_K_S - специальный формат llama.cpp, который сохраняет качество лучше, чем кажется возможным.
Почему именно CPU, а не GPU?
Потому что VRAM - это роскошь. Даже 8xH100 дадут вам только 640 ГБ. А тут нужно 400+ ГБ только для модели в Q4. Добавьте контекст, батчинг - и вы уже за пределами возможного.
CPU с 512 ГБ DDR5? Это дешевле. Намного. Особенно если у вас уже есть сервер. Или если вы арендуете в Hetzner. Или если вы просто не хотите заниматься распределенным инференсом между 10 видеокартами.
Есть нюанс: скорость. 10-12 токенов в секунду - это не для чата. Это для batch-обработки. Для асинхронных задач, где можно поставить 100 запросов в очередь и уйти пить кофе.
Квантование: магия сжатия
Исходная модель весит около 2 ТБ в FP16. Абсурд. Даже для сервера. Квантование Q4_K_S сжимает это до 400-450 ГБ. Как?
| Формат | Размер модели | Качество | Скорость |
|---|---|---|---|
| FP16 | ~2 ТБ | Эталонное | Невозможно |
| Q4_K_S | ~420 ГБ | -1-2% к FP16 | 10-12 tok/s |
| Q3_K_S | ~315 ГБ | -3-5% к FP16 | 14-16 tok/s |
Q4_K_S - это не просто 4-битное квантование. Это "K-quants" от llama.cpp, где разные части матриц квантуются с разной точностью. Веса, которые важнее, получают больше бит. Гениально просто.
Для сравнения: если вы возьмете GPT-OSS 120B, то он в Q4_K_S займет около 60 ГБ. Kimi-k2.5 в 8 раз больше. Но и в 8 раз умнее? Не всегда. MoE модели капризны.
Железо: AMD EPYC 9175F и его особенности
9175F - это 32 ядра, 64 потока, 256 МБ L3 кэша. Звучит мощно. Но для LLM важнее не количество ядер, а память. И ее организация.
512 ГБ DDR5-4800 - это 8 каналов по 64 ГБ. Пропускная способность: около 300 ГБ/с. Много? Для GPU - смешно. Для CPU - достаточно. Главное - правильно настроить NUMA.
Не делайте ошибку: запуск такой модели без учета NUMA убьет производительность. Если у вас 2 сокета, а модель загружена в память одного - готовьтесь к 2-3 tok/s вместо 10.
Кстати, если у вас нет EPYC, но есть что-то поменьше - посмотрите гайд по Minisforum AI X1 Pro. Там те же принципы, только масштаб другой.
Запуск через podman: изоляция и контроль
Docker? Устарел. Podman - это rootless, безопасно, и работает без демона. Для сервера - идеально.
Сначала собираем llama.cpp с поддержкой AVX-512 и всех оптимизаций:
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make LLAMA_CUBLAS=0 LLAMA_VULKAN=0 LLAMA_AVX512=1 -j32
Зачем отключаем CUBA и Vulkan? Потому что на CPU они не нужны. А AVX-512 дает прирост 15-20% на EPYC.
Создаем Dockerfile:
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y \
build-essential \
git \
wget \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY llama.cpp /app/llama.cpp
WORKDIR /app/llama.cpp
RUN make LLAMA_AVX512=1 -j$(nproc)
VOLUME ["/models"]
EXPOSE 8080
CMD ["./server", "-m", "/models/kimi-k2.5.Q4_K_S.gguf", "-c", "8192", "--port", "8080", "--host", "0.0.0.0"]
Собираем и запускаем:
podman build -t kimi-server .
podman run -d \
--name kimi-k2.5 \
-p 8080:8080 \
-v /path/to/models:/models:Z \
--memory=480g \
--memory-swap=480g \
--cpus=32 \
kimi-server
Обратите внимание на memory=480g. Оставляем 32 ГБ для системы. И memory-swap равен memory - отключаем своп, иначе все умрет.
Настройка сервера: флаги, которые меняют все
Вот где большинство обламывается. Берут дефолтные настройки и удивляются, почему 1 токен в секунду.
Правильная команда для server:
./server -m kimi-k2.5.Q4_K_S.gguf \
-c 8192 \
-ngl 0 \
-t 56 \
-b 512 \
--ctx-size 8192 \
--batch-size 512 \
--parallel 4 \
--cont-batching \
--cache-type-k q8_0 \
--cache-type-v q8_0 \
--host 0.0.0.0 \
--port 8080
Разберем по костокам:
- -ngl 0 - ВСЕ на CPU. Даже кэш. Да, можно часть на GPU, но тогда теряется смысл.
- -t 56 - 56 потоков из 64. 8 оставляем системе. Если поставить 64 - будет хуже.
- --batch-size 512 - Огромный батч. Для асинхронной обработки. Не для чата!
- --cont-batching - Непрерывный батчинг. Новая фича llama.cpp 2025 года. Ускоряет обработку очереди.
- --cache-type-k q8_0 - Ключи кэша в 8 битах. Важнее, чем кажется.
Про cache-type-k отдельный разговор. K и V кэши в attention можно хранить в другом формате, чем сама модель. q8_0 для кэша дает +5-7% скорости почти бесплатно.
Если хотите глубже в аргументы llama.cpp - есть отдельная статья про все флаги.
Производительность: 10-12 tok/s - это много или мало?
Для чата - смешно. Для batch-обработки - нормально. Представьте: вы отправляете 1000 запросов на суммаризацию документов. Сервер берет их батчами по 512. Обрабатывает за 40-50 секунд на батч. Итого 2 минуты на 1000 документов.
Вручную это 100 часов работы. Здесь - 2 минуты. Разница?
Но есть ограничения:
- Контекст 8192 токена - это максимум. Дальше производительность падает экспоненциально.
- Память: каждый параллельный запрос добавляет overhead. 4 параллельных - это +50 ГБ к памяти.
- Нагрев: 32 ядра на 100% - это 500+ ватт. Кондиционер обязателен.
Для сравнения: EPYC 9175F против M3 Max в тестах показывает, что Apple чипы иногда быстрее на маленьких моделях. Но на 1T параметрах - только EPYC.
Асинхронный workflow: как не сойти с ума
Вы не будете сидеть и ждать 10 токенов в секунду. Это безумие. Вместо этого настройте очередь.
Пример на Python с aiohttp:
import aiohttp
import asyncio
from typing import List
class KimiBatchProcessor:
def __init__(self, url: str = "http://localhost:8080"):
self.url = url
self.session = None
async def process_batch(self, prompts: List[str]) -> List[str]:
if not self.session:
self.session = aiohttp.ClientSession()
tasks = []
for prompt in prompts:
payload = {
"prompt": prompt,
"n_predict": 512,
"temperature": 0.1,
"stop": ["\n\n"]
}
task = self.session.post(
f"{self.url}/completion",
json=payload,
timeout=300 # 5 минут на запрос
)
tasks.append(task)
responses = await asyncio.gather(*tasks, return_exceptions=True)
results = []
for resp in responses:
if isinstance(resp, Exception):
results.append("ERROR")
else:
data = await resp.json()
results.append(data["content"])
return results
async def close(self):
if self.session:
await self.session.close()
Отправляете 1000 промптов, получаете 1000 ответов. Пока модель думает над одним батчем, вы готовите следующий. Конвейер.
Таймаут 300 секунд - не случайно. Иногда модель "задумывается" на 2-3 минуты на сложных запросах. Если поставить 30 секунд - потеряете половину запросов.
Кому это вообще нужно?
Не всем. Это специфический инструмент для специфических задач:
- Исследовательские институты - для обработки научных статей партиями
- Юридические компании - анализ тысяч договоров одновременно
- Контент-агентства - генерация или суммаризация больших объемов текста
- Энтузиасты с сервером - потому что могут
Если вам нужно 30 токенов в секунду для чата - берите Qwen3-VL-8B. Или даже меньшую модель. 1T параметров - это overkill для диалога.
Что будет дальше?
К 2027 году такие модели будут работать на ноутбуках. Нет, серьезно. AMD Strix Halo уже обещает 128 ГБ unified memory. Добавьте квантование Q2_K (его пока нет для MoE, но будет) - и 1T модель поместится в 200 ГБ.
Скорость? 5-6 токенов в секунду на ноутбуке. Смешно сегодня. Нормально завтра.
А пока - если у вас есть доступ к серверу с 512 ГБ ОЗУ, попробуйте. Хотя бы чтобы понять, где границы возможного сегодня. И где они окажутся завтра.
Главное - не пытайтесь использовать это для чата. Ваши пользователи возненавидят вас. А сервер - перегреется.