Прискорення 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 для реального часу. Стек: 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 (або повернення коштів) і надаємо сертифікат тестування.