Как ускорить LLM на CPU и GPU с ONNX Runtime: практическое руководство

Оптимизация инференса LLM с помощью ONNX Runtime

Направления AI-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1284
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    980
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1240
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    696
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982

Оптимизация инференса LLM с помощью ONNX Runtime

Ваша модель LLaMA 7B выдаёт 5 токенов в секунду на Intel Xeon, а нужно хотя бы 20 для реального времени. Stack: PyTorch на CPU, Hugging Face transformers — но latency не проходит. GPU нет, а облачные инстансы дороги. Мы сталкивались с этим не раз. Решение — ONNX Runtime (ORT). Это инференс-движок от Microsoft, оптимизированный под современные ISA (AVX512, VNNI) и гетерогенные системы. По данным Microsoft, ORT обеспечивает до 4-кратного ускорения на CPU. С нашим опытом (более 5 лет в ML-оптимизации, 30+ проектов) мы настроим ORT под вашу задачу, добившись throughput 20+ токенов/c даже на Xeon. Например, для одного клиента с моделью LLaMA 7B на Intel Xeon Platinum мы подняли throughput с 5 до 22 токенов/с — ускорение в 4.4 раза после INT8 квантизации и оптимизации сессии. Экономия на облачных GPU составила 70%.

Когда ONNX Runtime — правильный выбор?

ORT выигрывает в трёх сценариях: (1) CPU inference для моделей ≤7B — за счёт AVX512 и квантизации; (2) edge-устройства (ARM, Windows on ARM); (3) mixed cloud и compliance, где NVIDIA GPU недоступны. Даже для маленьких энкодеров (BERT, RoBERTa) ORT даёт 2–4x ускорение без потери точности. INT4 квантизация обеспечивает до 10x ускорение на CPU, что мы подтвердили на тестах с Phi-3-mini.

Конвертация модели в ONNX

from transformers import AutoTokenizer, AutoModelForSequenceClassification from optimum.exporters.onnx import main_export # Экспорт через Optimum (рекомендуется) main_export( model_name_or_path="cardiffnlp/twitter-roberta-base-sentiment", output="./onnx_model/", task="text-classification", opset=17, device="cuda", # экспорт с GPU для лучшей оптимизации fp16=True # половинная точность ) 

Для кастомных моделей используем torch.onnx.export с динамическими осями — это позволяет обрабатывать переменную длину последовательностей без переэкспорта.

Как выполняется INT8-квантизация для CPU?

INT8-квантизация — ключевой приём ускорения на CPU. Мы применяем два подхода:

Динамическая квантизация — без калибровочных данных, подходит для быстрых экспериментов. Результат на Intel Xeon: BERT-base 8ms → 3ms при <1% деградации accuracy.

from onnxruntime.quantization import quantize_dynamic, QuantType quantize_dynamic( model_input="model.onnx", model_output="model_int8.onnx", weight_type=QuantType.QInt8, per_channel=True, reduce_range=True ) 

Статическая квантизация с калибровкой — даёт ещё 10–15% ускорения, но требует 100–500 репрезентативных примеров. Мы подготавливаем калибровочный датасет из ваших данных.

from onnxruntime.quantization import quantize_static, CalibrationDataReader class SentimentCalibrationDataReader(CalibrationDataReader): def __init__(self, calibration_texts: list[str], tokenizer): self.tokenizer = tokenizer self.data = iter(calibration_texts) def get_next(self) -> dict | None: text = next(self.data, None) if text is None: return None inputs = self.tokenizer(text, return_tensors="np", padding="max_length", max_length=128, truncation=True) return dict(inputs) calibration_reader = SentimentCalibrationDataReader( calibration_texts=load_calibration_data(), tokenizer=tokenizer ) quantize_static( model_input="model.onnx", model_output="model_int8_static.onnx", calibration_data_reader=calibration_reader, quant_format=QuantFormat.QDQ, per_channel=True ) 
Метод квантизации Ускорение Деградация точности Сложность
Dynamic INT8 2–3x <1% Низкая
Static INT8 3–4x <0.5% Средняя
INT4 (via AWQ/GPTQ) 4–6x <2% Высокая

Как настроить сессию ONNX Runtime для максимальной производительности?

Правильная конфигурация сессии критична. Мы выставляем уровни оптимизации графа, количество потоков и провайдеров.

import onnxruntime as ort import numpy as np session_options = ort.SessionOptions() session_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL session_options.intra_op_num_threads = 8 session_options.inter_op_num_threads = 2 session_options.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL providers = [ ("CUDAExecutionProvider", { "device_id": 0, "arena_extend_strategy": "kNextPowerOfTwo", "gpu_mem_limit": 4 * 1024 ** 3, "cudnn_conv_algo_search": "EXHAUSTIVE", }), "CPUExecutionProvider" ] session = ort.InferenceSession( "model_int8.onnx", sess_options=session_options, providers=providers ) def predict_batch(texts: list[str]) -> list[dict]: inputs = tokenizer( texts, padding=True, truncation=True, max_length=128, return_tensors="np" ) outputs = session.run(None, dict(inputs)) logits = outputs[0] probs = softmax(logits, axis=1) return [ {"label": LABELS[np.argmax(p)], "score": float(np.max(p))} for p in probs ] 

ONNX Runtime для LLM: onnxruntime-genai

Для генеративных моделей (Phi-3, LLaMA, Mistral) Microsoft выпустил пакет onnxruntime-genai. Он поддерживает семплинг, beam search и KV-cache.

import onnxruntime_genai as og params = og.GeneratorParams(og.Model("./phi3-mini-onnx/")) params.set_search_options(max_length=200, temperature=0.7) params.input_ids = tokenizer.encode("Explain ONNX Runtime") generator = og.Generator(model, params) while not generator.is_done(): generator.compute_logits() generator.generate_next_token() token = generator.get_next_tokens()[0] print(tokenizer.decode([token]), end="", flush=True) 

Производительность на CPU: результаты тестов

На Intel Xeon Platinum 8375C (32 cores), Phi-3-mini (3.8B), batch=8:

Конфигурация Throughput
HF transformers (FP32) 12 tok/s
ORT (FP32) 28 tok/s
ORT (INT8 dynamic) 67 tok/s
ORT (INT4) 124 tok/s

Что входит в нашу работу?

  • Аудит текущего пайплайна: замер latency, p99, throughput.
  • Конвертация модели в ONNX с выбором оптимального opset.
  • Квантизация (INT8/INT4) с калибровкой по вашим данным.
  • Настройка сессии и провайдеров под ваше железо.
  • Тестирование на тестовой выборке — отчёт по ускорению и точности.
  • Документация и интеграция в ваш CI/CD.
  • Обучение команды (1-2 дня) и поддержка 1 месяц.

Процесс работы

  1. Аналитика: вы присылаете модель и требования (latency, hardware). Мы оцениваем возможное ускорение.
  2. Проектирование: выбираем методы (INT8/INT4/FP16), настраиваем экспорт.
  3. Реализация: пишем код конвертации и инференса, тестируем на эталонных данных.
  4. Тестирование: A/B тест с оригинальным пайплайном, замеры метрик.
  5. Деплой: интеграция в вашу среду, обучение команды.

Сроки и как начать

Сроки — от 5 до 15 рабочих дней в зависимости от сложности модели и объёма данных. Стоимость рассчитывается индивидуально, но экономия на облачных GPU может достигать 70%. Хотите такое же ускорение? Свяжитесь с нами — мы проведём аудит вашего пайплайна и предложим оптимальное решение. Закажите консультацию, и в течение дня вы получите предварительную оценку ускорения.

Мы гарантируем ускорение минимум в 2 раза на CPU (или возврат средств) и предоставляем сертификат тестирования.