GPU-ускорение
NextStat поддерживает GPU-ускоренную генерацию тоев и батч-вычисление NLL через CUDA (NVIDIA) и Metal (Apple Silicon). GPU-бэкенд выбирается во время выполнения через CLI или Rust API.
Бэкенды
| Backend | Точность | Платформа | Требование |
|---|---|---|---|
| CUDA | f64 (double) | NVIDIA GPUs | nvcc + CUDA toolkit |
| Metal | f32 (float) | Apple Silicon | macOS (встроенный) |
Сборка с поддержкой GPU
# CUDA (requires nvcc in PATH) cargo build --workspace --features cuda # Metal (Apple Silicon, macOS) cargo build --workspace --features metal
Использование CLI
# NVIDIA GPU (f64) nextstat hypotest-toys --input workspace.json \ --mu 1.0 --n-toys 10000 --gpu cuda # Apple Silicon GPU (f32) nextstat hypotest-toys --input workspace.json \ --mu 1.0 --n-toys 10000 --gpu metal
GPU-resident toy pipeline
Флаг --gpu-sample-toys хранит сгенерированные события прямо на GPU, исключая round-trip D2H+H2D для буфера obs_flat между сэмплером и батч-фиттером.
nextstat hypotest-toys --input workspace.json \ --mu 1.0 --n-toys 10000 --gpu cuda --gpu-sample-toys
Unbinned GPU WeightSys
Модификатор weightsys теперь lowered в CUDA/Metal ядра с поддержкой интерполяции code0 и code4p. В YAML-спецификации unbinned-модели:
modifiers:
- type: weightsys
param: alpha_jet_jes
lo: 0.95
hi: 1.05
interp_code: code4p # опционально, по умолчанию code0GPU Flow Evaluation
Flow PDF могут использовать GPU для NLL reduction. Два пути:
- Path 1: CPU flow + GPU NLL — Flow вычисляет
log p(x|θ)на CPU (ONNX Runtime), результат загружается на GPU, где CUDA-ядро выполняет extended unbinned likelihood reduction.GpuFlowSessionуправляет пайплайном автоматически. - Path 2: CUDA EP + I/O binding — С
--features neural-cudaONNX Runtime использует CUDA Execution Provider. Forward pass flow на GPU, log-prob остаётся device-resident. NLL reduction читает напрямую из GPU-памяти — zero host↔device копирование.
Градиент через центральные конечные разности (ε=1e-4): 2·n_params + 1 NLL вызовов на итерацию.
| Сценарий | Рекомендация |
|---|---|
| N < 10k событий, мало параметров | Только CPU (flow + NLL) |
| N > 50k событий, мультипроцессная модель | CPU flow + GPU NLL (Path 1) |
| N > 100k событий, NVIDIA GPU | CUDA EP + GPU NLL (Path 2) |
| Batch toys (1000+) | GPU NLL с batch-ядром |
Ускорение на CPU
Даже без GPU NextStat использует несколько стратегий ускорения на CPU:
- SIMD автовекторизация — Компиляторные векторные инструкции для батч-операций
- Параллелизм Rayon — Work-stealing пул потоков для генерации тоев и сканов параметров
- Apple Accelerate — vDSP и vForce для векторизованной математики на macOS (log, exp и т.д.)
Дифференцируемый слой
CUDA и Metal поддерживают дифференцируемый NLL-слой для интеграции с PyTorch:
| Функция | CUDA | Metal |
|---|---|---|
| Загрузка сигнала | Zero-copy через raw pointer | CPU → GPU (f64→f32) |
| Возврат градиента | Zero-copy или Vec<f64> | Vec<f64> (f32→f64) |
| Profiled q₀/qμ | GPU L-BFGS-B + теорема об огибающей | Тот же алгоритм, точность f32 |
| Многоканальный сигнал | Поддерживается | Поддерживается |
| Интеграция с PyTorch | Напрямую (тот же CUDA-контекст) | Через CPU tensor bridge |
Батч-фиттинг тоев
CUDA и Metal поддерживают GPU-ускоренный батч-фиттинг тоев для CLs-проверки гипотез:
| Точка входа | Описание |
|---|---|
fit_toys_batch_gpu / fit_toys_batch_metal | Высокоуровневый: генерация тоев из параметров модели |
fit_toys_from_data_gpu / fit_toys_from_data_metal | Низкоуровневый: пользовательские ожидаемые данные, init, bounds |
hypotest_qtilde_toys_gpu | Полный CLs-воркфлоу: фаза A (CPU-эталон) + фаза B (GPU-ансамбль) |
Архитектура: фаза A выполняет 3 базовых CPU-фита (свободный, условный при μ_test, условный при μ=0), затем фаза B отправляет на соответствующий GPU-бэкенд для батч-генерации ансамбля тоев.
# CUDA: CLs на тоях nextstat hypotest-toys --input workspace.json \ --mu 1.0 --n-toys 10000 --gpu cuda # Metal: CLs на тоях nextstat hypotest-toys --input workspace.json \ --mu 1.0 --n-toys 10000 --gpu metal
Бенчмарки производительности
CUDA: GEX44 · RTX 4000 SFF Ada (20 GB) · CUDA 12.0 · AMD EPYC 8 cores
Metal: Apple M5 · macOS · unified memory
Сборка: --release --features cuda|metal
Single-Операция Latency
| Операция | CPU | CUDA | Победитель |
|---|---|---|---|
| MLE-фит (8 params) | 2.3 ms | 136.3 ms | CPU 59× |
| MLE-фит (184 params) | 520.8 ms | 1,272.0 ms | CPU 2.4× |
| Профильный скан (184p, 21pt) | 8.4 s | 7.9 s | GPU 1.07× |
| Diff NLL + grad (8 params) | — | 0.12 ms | GPU-only |
| Diff NLL + grad (184 params) | — | 3.66 ms | GPU-only |
| Profiled q₀ (8 params) | — | 3.0 ms | GPU-only |
| Цикл обучения НС | — | 2.4 ms/step | GPU-only |
Батч-тои — большая модель (tHu, 184 params)
GPU lockstep amortizes накладные расходы ядра → sub-linear scaling
| Toys | CUDA f64 (RTX 4000) | Metal f32 (M5) | ||||
|---|---|---|---|---|---|---|
| GPU | CPU | × | GPU | CPU | × | |
| 100 | 20.2 s | 37.9 s | 1.8× | 10.7 s | 29.8 s | 2.8× |
| 500 | 63.4 s | 383.7 s | 6.0× | 29.1 s | 175.5 s | 6.0× |
| 1,000 | 119.9 s | 771.4 s | 6.4× | 56.8 s | 359.1 s | 6.3× |
Cross-Платформа Итоги (1,000 toys, 184 params)
| Backend | GPU | CPU | Ускорение |
|---|---|---|---|
| CUDA f64 (RTX 4000 SFF Ada) | 119.9 s | 771.4 s | 6.4× |
| Metal f32 (Apple M5) | 56.8 s | 359.1 s | 6.3× |
Батч-тои — малая модель (complex, 8 параметров)
Доминируют накладные расходы запуска ядра → CPU побеждает на обеих платформах
| Toys | GPU (CUDA) | CPU (8 cores) | Ускорение |
|---|---|---|---|
| 100 | 726 ms | 18 ms | CPU 40× |
| 500 | 1,169 ms | 23 ms | CPU 51× |
| 1,000 | 1,838 ms | 40 ms | CPU 46× |
| 5,000 | 7,412 ms | 146 ms | CPU 51× |
Ключевые наблюдения
- Сходящийся фактор ускорения ~6.3× — CUDA (f64) и Metal (f32) сходятся к одинаковому отношению GPU/CPU несмотря на разную точность, архитектуру и абсолютную производительность. Фундаментальное свойство lockstep-архитектуры батч L-BFGS-B.
- GPU-масштабирование батча сублинейно — 10× тоев → 5.9× времени. Lockstep-выполнение амортизирует накладные расходы запуска ядра по батчу.
- Масштабирование CPU суперлинейно на больших моделях — 10× тоев → 20.3× времени для 184 параметров из-за давления на L3-кеш.
- Кроссовер при ~100 параметрах — GPU побеждает для моделей со ~100+ параметрами. Ниже — доминирует параллелизм Rayon из-за пренебрежимо малых накладных расходов на тоя.
Рекомендация: используйте --gpu cuda или --gpu metal для батч-генерации тоев на моделях со 100+ параметрами. Для малых моделей и одиночных фитов используйте CPU (по умолчанию).
Ограничения Metal
Текущий статус Metal
- ›Батч-фиттинг тоев — полностью поддерживается (точность f32, ~1.27e-6 паритет NLL vs CPU f64).
- ›Дифференцируемый NLL + градиент — полностью поддерживается через CPU tensor bridge.
- ›Ранкинг — пока не поддерживается. Сервер и CLI возвращают чёткую ошибку. Используйте CPU для ранкинга на Apple Silicon.
Известные проблемы (исправлены)
- Паника memcpy_dtoh в батч-тоях — cudarc 0.19 требует
dst.len() >= src.len()для device-to-host копирования. Когда тои сходятся иn_active < max_batch, хост-буфер был слишком мал. Исправление: выделять хост-буферы размеромmax_batchи обрезать. - Сходимость ProfiledDifferentiableSession — допуск L-BFGS-B 1e-6 слишком жёсткий для проекционного градиента вблизи границ параметров. Исправление: допуск 1e-5 + критерий стабильности NLL.
Валидация
# Фит одной модели + паритет градиента (CUDA) cargo test -p ns-inference --features cuda -- --nocapture # Батч-тесты Metal cargo test -p ns-inference --features metal -- --nocapture # Паритет Python GPU pytest tests/python/test_gpu_parity.py -v
Интеграционные тесты Rust в crates/ns-inference/src/gpu_single.rs:
- test_gpu_nll_matches_cpu
- test_gpu_grad_matches_cpu
- test_gpu_fit_matches_cpu
- test_gpu_session_reuse
- test_gpu_complex_workspace
- test_gpu_nll_and_grad_at_multiple_points
Источники допусков: tests/python/_tolerances.py (Python) · crates/ns-inference/src/gpu_single.rs (Rust)
