GPU-вычисления: когда графы и эмбеддинги считают на видеокарте
Два GPU-пути RAGRAF (эмбеддинги и тензорный обход графов), измеренные пороги переключения, backend-каскад и честная экономика ускорения.
Два независимых GPU-пути #
RAGRAF умеет использовать GPU в двух разных задачах, и их экономика отличается на порядок. Путать их — главная ошибка при планировании железа.
| Путь | Где живёт | Что ускоряет | Порог включения |
|---|---|---|---|
| Эмбеддинги | compute.py (sentence-transformers + torch) | пакетное векторизование чанков при индексации | ~1 800 текстов за проход |
| Обход графов | graph_algo.py (torch.sparse, CSR) | батч-достижимость/срезы на больших графах | ~5 000 вершин |
Оба пути опциональны: без torch/CUDA продукт полностью функционален на CPU (backend-каскад torch-gpu → torch-cpu → none выбирается автоматически и записывается в метаданные ревизии с полем reason — никогда не подразумевается).
Путь 1: эмбеддинги (compute.py) #
Базовый путь продукта — fastembed/ONNX Runtime (CPU, без torch). GPU-путь включается, когда torch+ CUDA присутствуют и объём текста превышает порог окупаемости:
GPU-режим: подготовка карты устройства — ~15 с (разово на процесс)
Порог окупаемости: ~1 800 текстов за индексацию
Ниже порога: CPU быстрее (накладные GPU не окупаются)Практический смысл: на пилотном корпусе (457 чанков) GPU медленнее — 15-секундная подготовка карты съедает выигрыш. На корпусе в 5–10 тысяч файлов (десятки тысяч чанков) GPU-индексация даёт кратное ускорение векторизации. Одиночные поисковые запросы GPU почти не ускоряет (один эмбеддинг запроса — микросекунды работы против 15 с подготовки); поэтому search остаётся ~1 с на CPU — доминирует не устройство, а отсутствие кэша запросов (R-PERF-3).
Измерения пишутся честно: last_seconds и reason (почему выбран путь) — в метаданные; панель показывает их во вкладке качества.
Путь 2: тензорный обход графов (graph_algo.py) #
Достижимость и срезы на больших графах — это матричные операции. При ≥ ~5 000 вершин граф перекладывается в CSR-представление torch.sparse и обходится батчами:
| Backend | Когда | Что это даёт |
|---|---|---|
torch-gpu | CUDA + большой граф | impact/slice батчами на видеокарте; латентность p95 укладывается в контракт ≤1 с на графах, где CPU-обход выходит за рамки |
torch-cpu | torch без CUDA | тот же тензорный код на CPU — всё равно быстрее наивного обхода на больших графах |
none | без torch | рекурсивные CTE SQLite — контракт производительности выполняется на пилотных размерах (487 узлов: impact ≤ 1 с с запасом) |
Ограничение CSR (документировано честно): CSR-представление не любит мутаций — добавление рёбер на лету требует пересборки матрицы. Отсюда следствие: CPG пересобирается полным прогоном, а «живой граф» (мутации между ревизиями) — не цель архитектуры (ревизия иммутабельна, принцип P1).
Конфигурация #
embedding:
device: auto # auto | cpu | cuda — auto выбирает по порогам и наличию torch
compute:
gpu_vector_threshold: 1800 # текстов; ниже — CPU
gpu_graph_threshold: 5000 # вершин; ниже — обычный обходПороги настраиваются, потому что «окупаемость» зависит от конкретной карты и корпуса; значения по умолчанию — измерены, не взяты с потолка (config.py, секция compute). Переменные окружения: RAGRAF_JOERN_HEAP_GB (Joern), стандартные CUDA_VISIBLE_DEVICES (torch).
Экономика ускорения: сводная таблица #
| Задача | CPU (пилот: 123 файла / 457 чанков / 487 узлов) | GPU | Вердикт |
|---|---|---|---|
| Полная индексация | 71 с (CPG 64 с, эмбеддинги ~5 с) | подготовка карты 15 с + эмбеддинги ~1 с | CPU — Joern доминирует, GPU не помогает |
| Индексация 10k файлов | десятки минут (эмбеддинги) | кратное ускорение векторизации | GPU |
impact/callers (487 узлов) | 0,7 мс — 1 с | нет смысла | CPU |
slice на графе 50k+ вершин | выходит за контракт | батч-обход в контракте | GPU |
Одиночный search | ~1 с | ~1 с (подготовка не окупается) | CPU (кэш запросов — R-PERF-3) |
Границы и roadmap #
- torch не объявлен в зависимостях (осознанно: базовый продукт обязан ставиться без 2 ГБ фреймворка). Формализация — extras
ragraf[gpu](R-PKG-1 в roadmap). - CUDA-версии не пинятся — совместимость torch/CUDA/dрайвера остаётся на стороне окружения;
selftestсообщает фактический backend. - Смешанных режимов нет: эмбеддинги и граф выбираются независимо, но «половина индексации на GPU, половина на CPU» внутри одного этапа не балансируется динамически (перспектива — см. future).
- Измерения порогов выполнены на пилотном оборудовании; на других картах пороги стоит перепроверить
--json-таймингами (last_seconds/reason).
Как проверить свой режим #
ragraf -p cfg.yaml status --json
# → "compute": {"embedding_backend": "fastembed-cpu", "graph_backend": "none",
# "reason": "gpu_vector_threshold не достигнут (457 < 1800)"}Панель администратора показывает backend и reason во вкладке качества; эмулятор панели демонстрирует оба состояния (CPU/GPU-корпус) на реальных числах пилота.
Смежное: CPG/Joern → · конфигурация → · замеры →