Почему эмбеддинги — отдельная статья расходов
В локальном RAG основное внимание обычно получает генеративная модель. Но до неё документы нужно разбить на фрагменты, превратить в векторы, загрузить в индекс и обновлять после каждого изменения. Запрос пользователя тоже получает вектор, а часть систем дополнительно запускает реранкер.
Эти операции выполняют модели-кодировщики. Они меньше LLM и часто хорошо работают на CPU, особенно после экспорта в ONNX или OpenVINO и квантования. GPU способен обработать большой пакет быстрее, но его преимущество зависит от размера модели, длины текста, партии, драйверов и реальной загрузки. Поэтому вопрос «что быстрее?» для бизнеса неполон. Нужен ответ на другой вопрос: какой контур выполняет требуемый объём в срок с минимальной стоимостью принятого результата.
Официальная документация Sentence Transformers прямо показывает, что рейтинг бэкендов меняется между локальным компьютером и облачной CPU-машиной, и рекомендует тестировать конфигурации на целевом железе с характерными входами. Это важнее любой универсальной таблицы: короткие товарные карточки и длинные регламенты создают разные вычислительные профили.
Сначала разделите три разных нагрузки
Одна надпись «эмбеддинги» часто скрывает три очереди с разной экономикой.
Первичная загрузка корпуса
Это большой, но редкий пакет. Для него важна общая длительность: успеет ли система обработать архив ночью или за выходные. Задержка одного документа почти не имеет значения, зато выгодны крупные партии и высокая утилизация оборудования.
Инкрементальные обновления
Новые договоры, карточки и инструкции появляются каждый час. Здесь нужен гарантированный срок свежести: например, документ должен попасть в поиск не позднее чем через 15 минут. Поток обычно неровный, поэтому важны очередь, повторная обработка и защита от дублей.
Векторизация пользовательских запросов
Это небольшие пакеты с жёстким бюджетом задержки. Даже если ночной импорт выгодно запускать на GPU, запросы сотрудников могут спокойно обслуживаться CPU. Обратное тоже возможно, если общий онлайн-поток велик и ускоритель уже загружен другими моделями.
Покупать одну схему для всех трёх очередей — всё равно что назначить фуру и курьером, и складом, и личным автомобилем. Технически поедет, финансовая модель будет менее убедительной.
Что подтверждают инструменты
Sentence Transformers поддерживает PyTorch, ONNX и OpenVINO. В документации показаны варианты FP16 для GPU, оптимизированные ONNX-модели и INT8-конфигурации для CPU. Авторы отдельно сравнивают не только скорость, но и отношение качества к базовой FP32-модели на задачах семантического сходства и поиска.
Hugging Face Text Embeddings Inference предоставляет официальные образы и для CPU, и для нескольких поколений NVIDIA GPU, принимает пакеты входов и допускает развёртывание в изолированном контуре с локально смонтированными весами. FastEmbed от Qdrant также использует ONNX Runtime, умеет распараллеливать CPU-обработку и имеет отдельный GPU-вариант.
Из этого не следует, что один бэкенд всегда дешевле. Следует другое: сравнение можно провести на одном API, одной модели и одном наборе документов, не переписывая весь RAG-контур.
Минимальный честный бенчмарк
Для выбора достаточно четырёх кандидатов:
- текущий PyTorch на CPU как базовая линия;
- ONNX или OpenVINO на CPU;
- та же модель на GPU;
- квантованный CPU-вариант, если его качество проходит порог.
Каждый вариант тестируют на одинаковом корпусе. Полезный набор должен отражать распределение продакшена, а не состоять из ста коротких предложений:
- 20–30% коротких карточек;
- основная масса обычных фрагментов;
- 10–20% длинных фрагментов у верхнего допустимого предела;
- русский язык, таблицы и смешанные алфавиты, если они есть в данных;
- повторяющиеся и почти одинаковые документы.
Перед замером нужен прогрев. Затем фиксируют размер партии, число потоков, версию модели, токенизатор, точность, библиотеку, драйвер и фактическое железо. Измеряют не только документы в секунду, но и токены в секунду: один договор и одна карточка не являются равными единицами работы.
Для онлайн-очереди отдельно нужны p50 и p95 задержки. Для пакетной — общая длительность, максимальная память и доля времени, когда устройство действительно занято. Если GPU ждёт документы 90% времени, его высокая пиковая скорость не превращается в высокую экономическую эффективность.
Считать нужно стоимость принятого вектора
Базовая формула на месяц:
**Стоимость контура = аренда или амортизация + электричество + сопровождение + хранение артефактов + стоимость повторной обработки.**
Затем стоимость делят не на число вызовов и не на число токенов, а на количество векторов, прошедших проверку качества и попавших в рабочий индекс.
Так в расчёт попадают скрытые потери:
- ошибки токенизации и пустые входы;
- повторная обработка после сбоя;
- полная переиндексация при смене модели;
- деградация поиска после квантования;
- ручная проверка проблемных коллекций;
- простой ускорителя между пакетами.
Подход соответствует логике unit economics: техническая метрика полезна, когда связана с бизнес-единицей. Для RAG такой единицей может быть обновлённый документ, принятый вектор или ответ, прошедший проверку, но определение должно оставаться стабильным.
Модельный расчёт без притворства, что это прайс-лист
Рассмотрим условную компанию. За месяц она обрабатывает 120 000 новых и изменённых фрагментов, в среднем по 750 токенов. Итого — 90 млн токенов. Замер на её данных дал:
- оптимизированный CPU: 12 000 токенов в секунду;
- GPU: 100 000 токенов в секунду;
- расчётная стоимость CPU-ресурса: 60 рублей за час;
- расчётная стоимость GPU-ресурса: 500 рублей за час.
Это не рыночные цены и не обещание производительности, а допущения для демонстрации метода.
Чистое вычислительное время без накладных расходов:
- CPU: 90 000 000 / 12 000 = 7 500 секунд, или около 2,08 часа;
- GPU: 90 000 000 / 100 000 = 900 секунд, или 0,25 часа.
Переменная стоимость одной месячной партии получается почти одинаковой:
- CPU: около 125 рублей;
- GPU: около 125 рублей.
Но вывод меняется после добавления реальности. Если GPU арендуется минимум на час, его партия стоит уже 500 рублей. Если ускоритель куплен и большую часть месяца простаивает, к задаче нужно отнести долю амортизации, питания и администрирования. Если же тот же GPU уже обслуживает локальную LLM и пакет эмбеддингов запускается в свободное окно, его предельная стоимость может оказаться ниже.
Поэтому точка безубыточности определяется не только скоростью. Для переменной аренды её можно оценить так:
**Объём × стоимость часа CPU / скорость CPU = объём × стоимость часа GPU / скорость GPU.**
Если обе стороны равны, решающими становятся срок выполнения, минимальный период тарификации и доступность ресурса. Для собственного оборудования вместо почасовой цены используют полностью нагруженную месячную стоимость и долю времени, реально занятую полезной работой.
Качество может съесть всю экономию
Переход с FP32 на INT8 способен ускорить CPU, но менять конфигурацию только по графику throughput опасно. Нужно повторить проверку поиска на размеченном наборе: recall@k, nDCG@k, доля правильных документов в первых позициях и итоговое качество ответов RAG.
Даже небольшое снижение retrieval-метрики может увеличить число ручных исправлений или пропущенных документов. Если быстрый вариант создаёт больше непринятых результатов, его стоимость на полезную единицу растёт.
Особенно осторожно следует менять саму embedding-модель. Векторы разных моделей обычно несовместимы: понадобится новый индекс, параллельный прогон и план переключения. Стоимость миграции нужно учитывать заранее, а старый индекс не удалять до проверки нового.
Практичная архитектура для малого бизнеса
Часто выигрывает не «CPU против GPU», а гибридная очередь:
- запросы пользователей и небольшие обновления идут на CPU постоянно;
- большие импорты накапливаются в очереди и уходят на GPU в доступное окно;
- одинаковый API скрывает выбор бэкенда от RAG-приложения;
- идентификатор модели и версии сохраняется с каждым вектором;
- повторная задача идемпотентна и не создаёт дубликат;
- метрики показывают токены, принятые векторы, p95, ошибки и загрузку оборудования.
Если отдельного GPU нет, начинать стоит с оптимизированного CPU. Это использует уже знакомую инфраструктуру и даёт базовую стоимость. Ускоритель добавляют только после измерения очереди, нарушения SLA или доказанного снижения цены на принятую единицу.
Пилот за одну неделю
1. Выгрузите репрезентативные 10–50 тысяч фрагментов и сохраните их длины.
2. Зафиксируйте одну модель и один токенизатор.
3. Сравните базовый CPU, оптимизированный CPU и доступный GPU.
4. Проверьте скорость, память, p95 и качество поиска на одном наборе.
5. Посчитайте полностью нагруженную стоимость, включая простой и переиндексацию.
6. Выберите контур отдельно для онлайн-запросов, обновлений и больших импортов.
Главный результат такого пилота — не победитель в соревновании железа, а прозрачная граница применимости. CPU может быть экономичнее при умеренном потоке и уже оплаченной инфраструктуре. GPU оправдан при больших пакетах, жёстком сроке или совместном использовании с другими моделями. Решение принимает очередь и стоимость принятого вектора, а не наклейка на сервере.
