skypro1111 commited on
Commit
4c4804a
·
verified ·
1 Parent(s): ac2776e

заміряна швидкість декоду для трьох шляхів

Browse files
Files changed (1) hide show
  1. README.md +50 -14
README.md CHANGED
@@ -101,9 +101,7 @@ llama-server -m gguf/model-f16.gguf --host 127.0.0.1 --port 8901 \
101
  "logit_bias": [[<кожен токен із цифрою>, -100]]}
102
  ```
103
 
104
- llama.cpp дає ~864 токени/с проти 55 у ONNX на тій самій моделі й тій самій
105
- якості: на 270M крок декоду впирається в запуск CUDA-ядер, а не в обчислення,
106
- і виграють CUDA-графи.
107
 
108
  ### onnxruntime
109
 
@@ -122,8 +120,40 @@ out = model.generate(ids, max_new_tokens=192, do_sample=False)
122
  print(tok.decode(out[0, ids.shape[-1]:], skip_special_tokens=True))
123
  ```
124
 
125
- Це шлях для **CPU й edge**. На GPU він програє llama.cpp приблизно в 15 разів —
126
- чому саме, розписано нижче.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  ## Препроцесинг обов'язковий
129
 
@@ -261,9 +291,9 @@ python convert_hf_to_gguf.py <тека_моделі> --outfile model-f16.gguf --
261
  ідентичні ID один-в-один. Без збігу 52/52 результат вважати недійсним.
262
  Готовий `tokenizer.model` лежить у корені цього репозиторію.
263
 
264
- Навіщо взагалі GGUF: на 270M крок декоду впирається не в обчислення, а в запуск
265
- CUDA-ядер. llama.cpp тримає CUDA-графи — **864 токени/с проти 55 в ONNX**, при
266
- тій самій якості на якорі.
267
 
268
  ---
269
 
@@ -279,12 +309,18 @@ python scripts/export_onnx.py --model <тека_моделі> --out ./onnx
279
  Готовий граф лежить у `onnx/`. Він **fp32**, тому вдвічі більший за
280
  safetensors — це очікувано, а не помилка експорту.
281
 
282
- Чесна засторога: на GPU ONNX для цієї моделі **програє** llama.cpp приблизно в
283
- 15 разів (55 проти 864 ток/с), і причина не в якості реалізації, а в тому, що
284
- на такому розмірі все впирається в оверхед запуску ядер, а CUDA-графи
285
- onnxruntime для цього графа оголошує недоступними. ONNX тут має сенс для
286
- **CPU-інференсу й edge-сценаріїв**, де llama.cpp незручний, а не як швидший
287
- шлях на GPU.
 
 
 
 
 
 
288
 
289
  ## Тренування
290
 
 
101
  "logit_bias": [[<кожен токен із цифрою>, -100]]}
102
  ```
103
 
104
+ Це найшвидший шлях із трьох, і з великим відривом — див. таблицю нижче.
 
 
105
 
106
  ### onnxruntime
107
 
 
120
  print(tok.decode(out[0, ids.shape[-1]:], skip_special_tokens=True))
121
  ```
122
 
123
+ **На CUDA обов'язково вимикайте io-binding** — інакше граф падає з
124
+ `cudaErrorIllegalAddress` на `embed_tokens/Mul`:
125
+
126
+ ```python
127
+ model = ORTModelForCausalLM.from_pretrained(
128
+ "skypro1111/gemma-3-270m-uk-verbalizer", subfolder="onnx",
129
+ provider="CUDAExecutionProvider", use_io_binding=False)
130
+ ```
131
+
132
+ І майте на увазі: без явного `provider` optimum мовчки бере CPU, навіть коли
133
+ CUDA доступна.
134
+
135
+ ### Скільки це коштує за часом
136
+
137
+ Заміряно на RTX 3090 Ti: один рядок за раз (саме так модель і працює —
138
+ речення за реченням), greedy, до 192 нових токенів, медіана з п'яти прогонів.
139
+
140
+ | шлях | токенів/с |
141
+ |---|---|
142
+ | transformers, bf16, GPU | 27 |
143
+ | onnxruntime, fp32, CPU | 31 |
144
+ | onnxruntime, fp32, GPU | 69 |
145
+ | **llama.cpp, GGUF F16, GPU** | **532** |
146
+
147
+ llama.cpp швидший за transformers у **20 разів** — і це не про якість
148
+ реалізації матричних множень. На моделі такого розміру крок декоду впирається
149
+ не в обчислення, а в **накладні витрати на запуск CUDA-ядер**: сама робота
150
+ мізерна, а ядер на крок запускається стільки ж, скільки у великої моделі.
151
+ llama.cpp тримає CUDA-графи й тому цей оверхед майже прибирає.
152
+
153
+ Звідси практичний висновок: якщо потрібна пропускна здатність — беріть GGUF.
154
+ ONNX має сенс там, де llama.cpp незручний, і особливо на CPU: 31 проти 69
155
+ ток/с на GPU означає, що на процесорі модель втрачає лише вдвічі, а не в
156
+ десятки разів.
157
 
158
  ## Препроцесинг обов'язковий
159
 
 
291
  ідентичні ID один-в-один. Без збігу 52/52 результат вважати недійсним.
292
  Готовий `tokenizer.model` лежить у корені цього репозиторію.
293
 
294
+ Навіщо взагалі GGUF: це найшвидший шлях із трьох, **532 токени/с проти 27 у
295
+ transformers** — при побайтово тій самій якості (перевірено, відповіді
296
+ збігаються слово в слово).
297
 
298
  ---
299
 
 
309
  Готовий граф лежить у `onnx/`. Він **fp32**, тому вдвічі більший за
310
  safetensors — це очікувано, а не помилка експорту.
311
 
312
+ Дві речі, на які пішов час і які варто знати наперед:
313
+
314
+ * без явного `provider` optimum бере CPU, навіть коли CUDA доступна — мовчки;
315
+ * на CUDA треба `use_io_binding=False`, інакше граф падає з
316
+ `cudaErrorIllegalAddress` на `embed_tokens/Mul`.
317
+
318
+ Чесна засторога щодо швидкості: на GPU ONNX програє llama.cpp у **7-8 разів**
319
+ (69 проти 532 ток/с), і причина не в якості реалізації, а в тому, що на такому
320
+ розмірі все впирається в оверхед запуску ядер, який CUDA-графи llama.cpp
321
+ прибирають, а onnxruntime для цього графа — ні. Натомість ONNX добре тримається
322
+ **на CPU**: 31 ток/с проти 69 на GPU, тобто втрата лише вдвічі. Саме тут його
323
+ ніша, а не в перегонах на відеокарті.
324
 
325
  ## Тренування
326