Насколько можно раздвинуть пределы процессора?
Не миритесь с раздутыми фреймворками и зависимостью от GPU. Откройте для себя pdefa — движок инференса, созданный с нуля, который запускает модели глубокого обучения напрямую на CPU.
Насколько можно раздвинуть пределы процессора?
Годами ответ на вопрос «запустить глубокое обучение» был одним и тем же: купите GPU. Но этот ответ игнорирует фундаментальный вопрос — сколько из этого оборудования мы на самом деле используем и сколько тратим впустую на накладные расходы фреймворка?
Чтобы освободиться от раздутого программного обеспечения внешних библиотек и использовать всю мощь оборудования с максимальной эффективностью, я делюсь своим инженерным путём и проектом с открытым исходным кодом: pdefa (hasnard/pdefa).
Что такое pdefa?
pdefa — это движок для инференса глубокого обучения, который я создал с нуля, используя C++20 и архитектуру AVX2 SIMD, чтобы запускать модели напрямую на CPU — без GPU, без тяжёлой среды выполнения, без дерева зависимостей, которое нужно распутывать перед запуском одного инференса.
Моя основная мотивация была простой: испытать, как можно управлять системными ресурсами с абсолютной эффективностью, и привнести эту ультралёгкую архитектуру в экосистему под лицензией AGPL-3.0, оставаясь бескомпромиссно верным истинной философии открытого исходного кода.
Зачем вообще возиться с инференсом на CPU?
Потому что большинство реальных развёртываний не имеют роскоши выделенного GPU. Периферийные устройства, встраиваемые системы, конвейеры CI, небольшие VPS-инстансы, машины в цехах и академические кластеры — все работают на CPU. В таких средах каждый мегабайт накладных расходов фреймворка и каждая ненужная зависимость — это затраты: память, время запуска, сложность развёртывания.
Фреймворк на 300 МБ, который подтягивает дюжину разделяемых библиотек, не является «бесплатным». Это налог, который вы платите при каждом развёртывании.
Ключевые технические особенности:
- Ультралёгкий размер
Скомпилированный нативный бинарник занимает всего 320 КБ. Никаких мегабайтов раздутости, никакой среды выполнения, которую нужно сначала установить — только то, что нужно для запуска инференса.
- Ноль внешних зависимостей
Python-интерфейс полагается исключительно на встроенный модуль ctypes. Никаких pip install, никаких конфликтов версий, никакой гимнастики с виртуальными окружениями.
- Оптимизация под оборудование
Максимизирует возможности векторизованной обработки с помощью наборов инструкций AVX2 и даёт прямой контроль над количеством потоков — так что вы можете настроить его точно под ваш CPU.
- Широкая поддержка архитектур
Способен запускать YOLO (с v8 по v12), ResNet, MobileNet, EfficientNet и DeepLabV3 из коробки.
- Встроенная обработка изображений
Имеет собственный загрузчик PNG/JPEG и встроенный алгоритм постобработки YOLO, полностью исключая необходимость в тяжёлых библиотеках вроде OpenCV.
- Гибкий рабочий процесс конвертации
Экспортируйте ваши существующие модели PyTorch в стандартный формат ONNX, затем используйте встроенный конвертер движка, чтобы без проблем перевести их в собственный низколатентный формат .engine от pdefa.


План разработки:
Скоро я выпущу инструмент pytorchtoengine, который позволит пользователям PyTorch полностью обойти промежуточный шаг ONNX и конвертировать модели напрямую в нативный формат движка. На один шаг меньше, на одну вещь меньше для отладки.
Для кого это:
Надеюсь, это послужит мощной альтернативой для разработчиков, работающих с серверами с ограниченными ресурсами, периферийными устройствами или лёгкими системами — для всех, кто когда-либо думал: «Мне просто нужно запустить эту модель, мне не нужна целая экосистема для этого».
Куда двигаться дальше:
Репозиторий открыт. Отзывы об архитектуре кода искренне приветствуются — особенно от людей, которые строили похожие системы или натыкались на те же стены. И если это вам откликается, звезда очень помогает поддержать проект.
```javascript
$code = @'
import pdefa
import cv2
model = pdefa.load('D:/PROJE/yolov8s.engine')
img_path = 'D:/PROJE/bus.jpg'
boxes = model(img_path, conf_thres=0.75)
img = cv2.imread(img_path)
class_names = {0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 5: 'bus', 7: 'truck'}
for b in boxes:
cls = int(b['cls'])
conf = b['conf']
x1, y1 = int(b['x1']), int(b['y1'])
x2, y2 = int(b['x2']), int(b['y2'])
names_attr = getattr(model, 'names', {})
cls_name = class_names.get(cls, names_attr.get(cls, f'cls_{cls}'))
label = f'{cls_name} {conf:.2f}'
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.putText(img, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2, cv2.LINE_AA)
print(f'{cls_name} | conf={conf:.3f} | box=[{x1}, {y1}, {x2}, {y2}]')
cv2.imwrite('D:/PROJE/output_bus.png', img)
'@
Добро пожаловать
Войдите, чтобы использовать ИИ-помощника
Меню
Главная
Все инструменты
Редактор
Редактировать текст и фигуры
Блог
Советы и руководства
Исследования
Академические статьи и исследования
Тема
Язык
Недавние действия
Lokal Geçmiş