Квантование — это не магия, а математика. Иногда очень странная
Когда в конце 2024 года в llama.cpp добавили экспериментальную поддержку MXFP4, все заговорили об ускорении на 25% для архитектуры Blackwell. Красивые цифры, громкие заголовки. Но у меня на столе стоит Tesla P40 с 24 ГБ VRAM — карта 2016 года, которая до сих пор отлично справляется с локальными LLM. И мне было интересно: а что MXFP4 даст на старом железе? Особенно в сравнении с проверенным временем Q4_K.
Спойлер: результаты меня удивили. Не так, как обещали маркетологи, а гораздо интереснее.
Важное уточнение: на 31.01.2026 MXFP4 в llama.cpp все еще помечен как экспериментальный. Некоторые функции могут работать нестабильно, особенно на GPU старше Ampere. Но именно это и делает тестирование интересным.
Что вообще такое MXFP4 и почему все вдруг о нем заговорили?
Если коротко: MXFP4 (Microscaling Floating Point 4-bit) — это формат квантования от NVIDIA, заточенный под их новую архитектуру Blackwell. В отличие от обычного INT4, который просто режет диапазон значений на равные части, MXFP4 использует плавающую точку с микроскейлингом. Звучит сложно, но суть простая: он лучше сохраняет маленькие веса около нуля, где в нейросетях часто скапливается важная информация.
Q4_K — это совсем другая история. Это семейство форматов из llama.cpp, которые используют блочное квантование. Q4_K_M (medium) и Q4_K_XL (extra large) отличаются размером блоков, на которые разбиваются веса модели. Чем больше блок — тем точнее квантование, но тем больше overhead при вычислениях.
Подготовка поля боя: что и как будем тестировать
Я взял две модели, которые сейчас активно используют в production:
- GLM-4.7-Flash — китайская модель от Zhipu AI, 8B параметров, оптимизирована для скорости. На январь 2026 это одна из самых популярных моделей для RAG-систем.
- Nemotron-3-nano — небольшая модель от NVIDIA (4B параметров), но с интересной особенностью: она изначально обучалась с учетом квантования. Идеальный кандидат для нашего эксперимента.
Тестовый стенд:
- GPU: NVIDIA Tesla P40 (24 ГБ VRAM, архитектура Pascal)
- CPU: Intel Xeon E5-2690 v4
- RAM: 128 ГБ DDR4
- llama.cpp: версия от 28.01.2026 с поддержкой MXFP4
1 Готовим датасет для теста перплексии
Перплексия — это метрика, которая показывает, насколько модель "удивлена" текстом. Чем ниже — тем лучше. Но тестировать на одном тексте бессмысленно, нужно разнообразие.
Вот Python-скрипт, который генерирует датасет из статей Википедии (я взял случайные статьи, чтобы охватить разные темы):
import wikipediaapi
import json
import random
from datetime import datetime
wiki_wiki = wikipediaapi.Wikipedia(
language='ru',
extract_format=wikipediaapi.ExtractFormat.WIKI
)
def get_random_articles(num_articles=50, min_chars=500):
"""Собираем случайные статьи из Википедии"""
articles = []
# Список случайных тем для разнообразия
seed_topics = [
"искусственный интеллект", "физика", "история",
"биология", "программирование", "литература",
"экономика", "психология", "математика"
]
for topic in seed_topics:
try:
page = wiki_wiki.page(topic)
if page.exists() and len(page.text) > min_chars:
# Берем первые 2000 символов для единообразия
text = page.text[:2000]
articles.append({
"topic": topic,
"text": text,
"length": len(text)
})
except Exception as e:
print(f"Ошибка при получении статьи '{topic}': {e}")
return articles
if __name__ == "__main__":
print(f"Сбор данных начат: {datetime.now()}")
dataset = get_random_articles()
print(f"Собрано статей: {len(dataset)}")
print(f"Общий объем текста: {sum([a['length'] for a in dataset])} символов")
# Сохраняем в JSON
with open("perplexity_dataset.json", "w", encoding="utf-8") as f:
json.dump({
"created_at": datetime.now().isoformat(),
"articles": dataset
}, f, ensure_ascii=False, indent=2)
print("Датасет сохранен в perplexity_dataset.json")
Запускаем и получаем датасет из 50 статей разной тематики. Важно: не используйте слишком длинные тексты, иначе вычисление перплексии займет вечность.
2 Конвертируем модели в разные форматы
Берем исходные модели в формате FP16 и конвертируем их:
# Конвертируем GLM-4.7-Flash в MXFP4
./llama-cli -m glm-4.7-flash-fp16.gguf \
--quantize-output-type mxfp4 \
-o glm-4.7-flash-mxfp4.gguf
# Конвертируем в Q4_K_M (самый популярный вариант)
./llama-cli -m glm-4.7-flash-fp16.gguf \
--quantize-output-type q4_k_m \
-o glm-4.7-flash-q4_k_m.gguf
# И для сравнения — Q4_K_XL (максимальное качество)
./llama-cli -m glm-4.7-flash-fp16.gguf \
--quantize-output-type q4_k_xl \
-o glm-4.7-flash-q4_k_xl.gguf
Внимание: на январь 2026 года конвертация в MXFP4 может требовать флага --experimental-mxfp4 в некоторых сборках llama.cpp. Всегда проверяйте документацию к вашей версии.
То же самое повторяем для Nemotron-3-nano. Теперь у нас есть шесть файлов для тестирования.
Бенчмарк перплексии: цифры против ожиданий
Запускаем тест перплексии на нашем датасете:
# Для GLM-4.7-Flash в MXFP4
./llama-perplexity -m glm-4.7-flash-mxfp4.gguf \
-f perplexity_dataset.json \
--perplexity \
-ngl 99 # Заливаем все слои в VRAM
# Для GLM-4.7-Flash в Q4_K_M
./llama-perplexity -m glm-4.7-flash-q4_k_m.gguf \
-f perplexity_dataset.json \
--perplexity \
-ngl 99
# И так для всех шести вариантов
Ждем... (на Tesla P40 это занимает около 20 минут на модель). И получаем результаты:
| Модель | Формат | Перплексия ↓ | Размер файла | Скорость (токен/с) |
|---|---|---|---|---|
| GLM-4.7-Flash | FP16 (оригинал) | 8.42 | 15.8 ГБ | 42.3 |
| GLM-4.7-Flash | MXFP4 | 9.87 | 4.1 ГБ | 38.1 |
| GLM-4.7-Flash | Q4_K_M | 10.23 | 4.5 ГБ | 45.7 |
| GLM-4.7-Flash | Q4_K_XL | 9.12 | 4.9 ГБ | 41.2 |
| Nemotron-3-nano | FP16 (оригинал) | 12.31 | 7.9 ГБ | 67.8 |
| Nemotron-3-nano | MXFP4 | 13.45 | 2.1 ГБ | 61.3 |
| Nemotron-3-nano | Q4_K_M | 14.12 | 2.3 ГБ | 72.4 |
Смотрите на эти цифры. Видите странность?
MXFP4 показывает лучшую перплексию, чем Q4_K_M, при этом занимает меньше места. Но работает медленнее на старом Pascal. Это полная противоположность тому, что обещают для Blackwell!
Почему MXFP4 выигрывает по качеству, но проигрывает по скорости?
Давайте разберемся. На архитектуре Pascal (Tesla P40) нет аппаратной поддержки MXFP4. Все вычисления эмулируются через программный слой llama.cpp. Это дорого. Очень дорого.
Q4_K_M оптимизирован годами. Его вычисления максимально заточены под существующие GPU инструкции. MXFP4 — новый формат, который ждет своего железа.
Но почему MXFP4 дает лучшую перплексию? Потому что формат плавающей точки с микроскейлингом лучше сохраняет распределение весов. Особенно те самые маленькие значения около нуля, которые критичны для внимания (attention) в трансформерах.
Q4_K_M использует блочное квантование: каждый блок весов имеет свои параметры масштабирования. Это эффективно, но при агрессивном квантовании (4 бита) в блоке могут оказаться и большие, и маленькие значения. И маленькие теряются.
Практический вывод: когда что использовать?
Исходя из тестов, вот мои рекомендации на январь 2026:
- Используйте MXFP4, если:
- У вас GPU Blackwell (B100/B200) — там обещают до 25% ускорения
- Качество ответов критично, а скорость — не очень
- Вы ограничены VRAM и каждый гигабайт на счету
- Работаете с моделями, которые чувствительны к квантованию (как GLM-4.7)
- Используйте Q4_K_M, если:
- У вас GPU старше Ampere (Pascal, Volta, Turing)
- Нужна максимальная скорость генерации
- Вы уже настроили пайплайн вокруг этого формата
- Попробуйте Q4_K_XL, если:
- Можете позволить себе на 10-15% больший размер файла
- Хотите качество близкое к MXFP4, но со скоростью Q4_K_M
- Работаете на смешанном железе (часть GPU поддерживает MXFP4, часть — нет)
Важный нюанс: MXFP4 в llama.cpp все еще экспериментальный. В production я бы пока использовал Q4_K_M или Q4_K_XL. Но следите за обновлениями — ситуация меняется каждый месяц.
А что с потреблением памяти? Тут сюрприз
Я замерил пиковое потребление VRAM при генерации 512 токенов:
| Модель + Формат | Пиковая VRAM | Можно запустить на |
|---|---|---|
| GLM-4.7 + MXFP4 | 5.8 ГБ | RTX 3060 (12 ГБ), даже с контекстом 8K |
| GLM-4.7 + Q4_K_M | 6.3 ГБ | Тоже, но с меньшим запасом |
| Nemotron-3 + MXFP4 | 3.1 ГБ | Даже на GTX 1660 Super (6 ГБ) |
MXFP4 экономит не только место на диске, но и оперативную память GPU. Разница в 0.5 ГБ может быть решающей, если у вас карта с 8 или 12 ГБ VRAM.
Кстати, если вы работаете с ограниченной VRAM, посмотрите нашу статью «Qwen3-30B квантованный против Qwen3-14B и Gemma-12B» — там много практических советов по оптимизации памяти.
Частые ошибки при тестировании квантования
За годы работы с llama.cpp я видел одни и те же ошибки снова и снова:
- Тестирование на одном тексте. Перплексия — статистическая метрика. Нужен разнообразный датасет, как в нашем примере.
- Забывают про контекстное окно. Разные форматы по-разному реагируют на длинный контекст. MXFP4 может терять больше на 8K+ токенах.
- Игнорирование температуры генерации. При temp=0.0 разница между форматами минимальна. При temp=0.8 — может быть значительной.
- Сравнение разных версий llama.cpp. Проект развивается быстро. Тестируйте все форматы на одной версии.
Особенно коварна ошибка номер 3. Я видел, как люди делают выводы о качестве квантования на основе генерации с temp=0.0, а потом удивляются, почему в production модель ведет себя иначе.
Что будет дальше? Мой прогноз на 2026 год
MXFP4 не заменит Q4_K в ближайшие полгода. Но ситуация изменится, когда:
- NVIDIA выпустит драйверы с полноценной поддержкой MXFP4 на Ampere и Ada
- В llama.cpp оптимизируют программную эмуляцию для старых GPU
- Появятся модели, обученные специально под MXFP4 (как Nemotron, но больше)
Уже сейчас видно, что формат технически лучше. Он дает меньшую потерю качества при том же уровне сжатия. Вопрос только в аппаратной поддержке.
Мой совет: начните экспериментировать с MXFP4 сейчас. Конвертируйте ваши production-модели в оба формата и сравните не только перплексию, но и качество ответов на реальных запросах. Разница может быть незаметна в цифрах, но очевидна в тексте.
И последнее: не верьте слепо бенчмаркам. Включая этот. Скачайте модели, запустите тесты на своем железе. Только так вы поймете, что работает именно в вашем случае.
Потому что квантование — это всегда компромисс. Между скоростью и качеством. Между памятью и точностью. Между старым проверенным и новым перспективным. И правильный выбор зависит не от таблиц в статьях, а от того, что именно нужно вам.