940 000 файлов, 24 часа и одна ошибка архитектуры
Представьте конвейер, который должен проглотить гору документов высотой с Эверест. Каждый день. 940 000 PDF – это не абстрактная цифра. Это 9.4 миллиона страниц, если в каждом в среднем по 10. Это 47 терабайт сырых данных, если каждый файл весит 50 МБ. Срок – 24 часа. Задержка – катастрофа.
Первая мысль? PaddleOCR. Он же лидер, эталон, open-source чудо. Вы ставите последнюю версию 3.4.1 (актуальна на апрель 2026), настраиваете, запускаете на сервере с восемью RTX 5090… и упираетесь в потолок в 3-4 изображения в секунду на карту. Математика простая: 8 карт * 4 img/s * 86400 секунд = 2.76 млн изображений в день. Даже если в PDF одна страница, до 9.4 млн не хватает в 3.4 раза. Провал.
Почему? Потому что PaddleOCR создавался для точности, а не для бешеной пропускной способности. Его архитектура – это монолит, который тяжело масштабируется горизонтально. Он жадный до памяти GPU и любит синхронные операции. В 2026 году, с появлением архитектуры Blackwell и RTX 5090, использовать PaddleOCR в сыром виде для таких задач – все равно что запрягать реактивный двигатель в телегу.
Главная ошибка – пытаться решить задачу объема одним инструментом. PaddleOCR – отличный скальпель, но вам нужен промышленный штамповочный пресс. Разница в подходе определяет успех.
Почему PaddleOCR ломается на больших объемах (и как это исправить)
Давайте разберем узкие места по косточкам. Вы запускаете ppocr-v5 модель. На бумаге она должна летать.
- Память GPU: Каждый инстанс модели на RTX 5090 с 24 ГБ GDDR7X съедает 4-5 ГБ просто для работы. Запустить больше 4-5 процессов на карту – уже риск. Контекст переключается, кеш сбрасывается, производительность падает.
- Синхронный ввод-вывод: PaddleOCR по умолчанию читает файлы синхронно. Пока одна страница загружается с диска, GPU простаивает. На SSD NVMe Gen5 это миллисекунды, но умноженные на 9.4 миллиона – это часы простоев.
- Нет настоящего батчинга: Модель обрабатывает изображения по одному или мелким батчам. Современные GPU, особенно Blackwell с их тензорными ядрами 4-го поколения, раскрываются на больших батчах. PaddleOCR этого не умеет из коробки.
- Препроцессинг на CPU: Конвертация PDF в изображения, изменение размера, нормализация – все это происходит на CPU и становится бутылочным горлышком.
Выход? Не отказываться от PaddleOCR, а превратить его из монолита в модульный конвейер. Это и есть суть Turbo-OCR – не волшебная библиотека, а архитектура.
Архитектура Turbo-OCR: Конвейер вместо монолита
Забудьте про скрипт, который берет PDF и выплевывает текст. Turbo-OCR – это система из пяти независимых, асинхронных стадий, связанных очередями. Каждая стадия масштабируется отдельно.
| Стадия | Инструмент | Масштабирование | Цель |
|---|---|---|---|
| Извлечение страниц | PDFium (C++ биндинги) | Много CPU-потоков | Конвертировать PDF → массив PNG в RAM |
| Предобработка | OpenCV + TensorRT | CUDA Streams | Ресайз, нормализация, батчинг на GPU |
| Детекция текста | PaddleOCR Det (экспорт в ONNX) | Несколько GPU, большие батчи | Найти bbox текста, передать координаты |
| Распознавание | PaddleOCR Rec (экспорт в TensorRT) | Несколько GPU, FP16/INT8 | Распознать текст из каждого bbox |
| Постобработка | Кастомные правила + fastText | Отдельные CPU-воркеры | Склеить строки, исправить ошибки, сохранить |
Магия в разделении. Детекция и распознавание – две разные модели. Их можно поставить на разные физические GPU. Предобработка идет своим потоком на GPU, не нагружая CPU. Вместо одного тяжелого процесса PaddleOCR – легкие специализированные воркеры.
1Железо: что купить или арендовать в 2026
Аппетит приходит во время еды, но бюджет нет. Вот два варианта.
Локальный кластер (капитальные затраты):
- 4 x Сервер с 2 x NVIDIA RTX 5090 (24 ГБ GDDR7X) или 2 x NVIDIA Blackwell B200 (если есть бюджет). На апрель 2026 это флагманы. Blackwell дает прирост в 2-3 раза на инференсе модели того же размера благодаря новым форматам данных (FP4).
- CPU: AMD EPYC 9654 (96 ядер) на сервер – чтобы кормить GPU данными.
- Память: 512 ГБ DDR5 на сервер. 9.4 млн изображений в буфере – это десятки терабайт в час, все должно быть в RAM.
- Хранилище: 4 x SSD NVMe Gen5 8 ТБ в RAID 0. Скорость чтения – 60+ ГБ/с. Файлы должны пролетать, не задерживаясь.
- Сеть: InfiniBand NDR 400 Гбит/с между серверами. Общие очереди задач должны синхронизироваться мгновенно.
Облако (операционные затраты): Арендуйте инстансы с теми же GPU у Google Cloud (A3 Mega) или AWS (P5e). Ключ – использовать spot/preemptible instances и автоматическое масштабирование. Как только очередь задач вырастает, система поднимает еще один инстанс. Обработал партию – умер. Это дешевле в 3-4 раза, но сложнее в управлении.
Совет: Не гонитесь за самым новым железом ради галочки. Тесты показывают, что на OCR RTX 5090 лишь на 25% быстрее RTX 4090, но в 2 раза дороже. Blackwell B200 оправдан, только если вы параллельно обучаете модели. Для инференса часто хватает прошлого поколения.
2Софт: собираем конвейер Turbo-OCR
Основа – Python, но критичные части на C++. Используем асинхронность (asyncio) и очереди (Redis или RabbitMQ).
Шаг 1. Разделяем PaddleOCR на детектор и распознаватель. Не используйте готовый pip-пакет для инференса. Экспортируйте модели в ONNX, а затем в TensorRT для максимальной скорости на NVIDIA.
# Экспорт детекторной модели PaddleOCR в ONNX (пример для версии 3.4.1)
python3 tools/export_model.py \
-c configs/det/ch_PP-OCRv5/ch_PP-OCRv5_det_cml.yml \
-o Global.pretrained_model=./ch_PP-OCRv5_det_distill_train/teacher \
Global.save_inference_dir=./inference/det_onnx \
Global.onnx_enable=True
# Конвертация ONNX в TensorRT план с оптимизацией под RTX 5090 (FP16)
trtexec --onnx=./det_model.onnx \
--saveEngine=./det_model_fp16.plan \
--fp16 \
--workspace=4096 \
--best
Шаг 2. Пишем воркер предобработки на CUDA. Берем библиотеку DALI от NVIDIA. Она умеет загружать JPEG/PNG, делать ресайз и аугментации прямо на GPU, минуя CPU.
# Упрощенный пример пайплайна DALI
from nvidia.dali import pipeline_def
import nvidia.dali.fn as fn
import nvidia.dali.types as types
@pipeline_def(batch_size=256, num_threads=4, device_id=0)
def preprocess_pipeline():
images = fn.external_source(device='cpu', name='raw_images')
images = fn.image_decoder(images, device='mixed', output_type=types.RGB) # Декодируем на GPU
images = fn.resize(images, resize_x=224, resize_y=224) # Ресайз на GPU
images = fn.crop_mirror_normalize(images,
mean=[0.485 * 255, 0.456 * 255, 0.406 * 255],
std=[0.229 * 255, 0.224 * 255, 0.225 * 255])
return images
# Этот пайплайн подает готовые батчи напрямую в модель детекции
Шаг 3. Оркестрируем очередь задач. Каждый PDF приходит в систему, разбивается на страницы. Каждая страница становится задачей в очереди Redis. Воркеры берут задачи независимо.
# Псевдокод главного координатора
import redis
import asyncio
from concurrent.futures import ProcessPoolExecutor
redis_client = redis.Redis(host='...', decode_responses=True)
async def process_pdf(pdf_path):
page_images = extract_pages_to_buffer(pdf_path) # PDFium в отдельном процессе
for img in page_images:
# Кладем задачу в очередь для детекции
task_id = generate_id()
redis_client.rpush('queue:detection', json.dumps({
'task_id': task_id,
'image_bytes': img.tobytes(), # Изображение уже в RAM
'meta': {...}
}))
# Ждем, когда все задачи по этому PDF будут выполнены
await wait_for_completion(task_ids)
Если вам интересна архитектура систем для обработки документов, почитайте наш разбор про системный дизайн против чистого AI – там те же принципы, но в меньшем масштабе.
3Тонкая настройка: выжимаем 15 img/s на RTX 5090
Цифра 15 изображений в секунду на карту – не магия. Это результат шести оптимизаций.
- Точность FP16 вместо FP32. Для OCR потеря точности минимальна (менее 0.5%), а скорость вырастает в 1.5-2 раза. В TensorRT это один флаг.
- Динамический батчинг. Воркер детекции не обрабатывает по одному изображению. Он ждет, пока накопится батч (скажем, 64 изображения), и отправляет его разом. Это лучше использует тензорные ядра.
- Кеширование моделей в GPU памяти. Не загружайте модель для каждой задачи. Один процесс-воркер живет постоянно, модель загружена один раз. Память RTX 5090 (24 ГБ) позволяет держать и детектор, и распознаватель одновременно.
- Пайплайнинг стадий. Пока детектор обрабатывает батч N, предобработка готовит батч N+1, а распознаватель работает над батчом N-1. Все стадии работают параллельно, как конвейер на заводе.
- Оптимизация под Blackwell. Если у вас новая архитектура, используйте форматы данных FP4 или INT4. Модели PaddleOCR можно квантовать с помощью инструментов NVIDIA Model Optimizer почти без потерь. Это еще x2 к скорости.
- Все в RAM. Никакой записи промежуточных изображений на диск. PDF → массив байт в памяти → результат в память → сохранение в базу. Диск только для исходников и финального вывода.
Для тех, кто работает на Apple Silicon, принципы те же, но инструменты другие. Посмотрите наш материал про локальный OCR на MacBook Pro – там фокус на эффективность на CPU.
Ошибки, которые сломают вашу систему (и как их избежать)
Я видел, как эти ошибки стоили тысяч долларов на простоях.
Что в итоге? Цифры и альтернативы
С Turbo-OCR архитектурой на 8 x RTX 5090 мы получаем:
- Детекция: 8 GPU * 15 img/s = 120 img/s.
- Распознавание: можно распараллелить еще больше, поставив отдельный пул GPU. Пропускная способность ~100 img/s.
- Итог: ~100 страниц в секунду устойчиво. 100 * 86400 = 8.64 млн страниц в день.
Это близко к цели в 9.4 млн. Добавьте еще одну карту – и вы у цели.
А если хочется революции, а не эволюции? Присмотритесь к диффузионным подходам, таким как MinerU-Diffusion. В 2026 году они уже показывают в 3 раза большую скорость на CPU, но требуют специфичной доработки под production.
Финальный совет: Не начинайте с покупки железа. Соберите прототип конвейера на одной RTX 5090 (или даже 4090). Замерьте производительность на реальной выборке в 10 000 PDF. Поймите, где узкое место – в чтении PDF, в детекции или в распознавании. Масштабируйте только ту стадию, которая тормозит. Иногда проблема решается не добавлением GPU, а переходом на более быструю библиотеку для конвертации PDF (с Poppler на PDFium) или кешированием моделей.
940 000 PDF за день – это инженерная задача, а не магический ритуал. Делите, распараллеливайте, профилируйте. И не бойтесь выкинуть часть кода PaddleOCR, если он мешает скорости. В конце концов, в production важны только два метрика: время и точность. Все остальное – детали.