Слияние ядер RMS_NORM и SCALE в llama.cpp ускоряет prefill на CUDA¶
4.0/10
В релизе llama.cpp b11177 представлено слияние CUDA-ядер RMS_NORM и SCALE, снижающее накладные расходы драйвера хоста на запуск операций в моделях с GDN-слоями. На стенде с 2x GTX 1080 Ti и моделью Qwen3.8-27B-UD-Q4_K_XL оптимизация обеспечила ускорение обработки промпта в llama-bench от +0,4% до +1,3%, а скорости генерации — до +0,6% (с 12,90 до 12,98 tok/s). В тестах llama-server с холодным prefill и спекулятивным декодированием draft-mtp прирост производительности составил +4,2% на контексте 8000 токенов (371,4 tok/s) и +4,8% на 20000 токенов (337,4 tok/s). Модификация полностью сохраняет побитную точность вычислений, оставляя перплексию неизменной (3,2030 при контексте 2048).
Метод оптимизации¶
Конструкция L2-нормализации в архитектурах с GDN вида ggml_scale(ggml_rms_norm(x, eps/n), 1/sqrt(n)) приводила к созданию двух дополнительных узлов SCALE на слой, генерируя 96 лишних запусков ядер на микробатч для модели с 48 слоями. В функцию rms_norm_f32 был внедрен флаг do_scale, благодаря которому операция вычисляет scale * (rsqrt(mean + eps) * x) в рамках того же ядра с общим этапом редукции и единым лаунчером. Фьюзинг активируется через ggml_can_fuse при отсутствии смещения у узла SCALE и наличии у выхода rms_norm ровно одного потребителя, повторяя логику, ранее примененную в бэкендах Metal и SYCL.
Показатели эффективности¶
Количество запусков ядер на микробатч на связке двух GPU снизилось с 1032,9 + 841,7 до 978,9 + 799,7 без изменения общего объема GPU-вычислений. Устранение накладных расходов вызова ядер драйвером ускорило предварительное заполнение контекста на длинных последовательностях в пайплайнах со спекулятивным декодированием draft-mtp почти на 5%.