tgoop.com/quant_prune_distill/174
Last Update:
PowerInfer: Fast Large Language Model Serving with a Consumer-grade GPU
[Статья] [Код]
Введение
За последние пару лет LLMки забавно прибавили в весе и многие модели не влезают в типичную пользовательскую GPU. А инферить умного ассистента локально ой как хочется.
Как выход, можно держать веса в ОЗУ или на диске и подгружать по мере необходимости - то есть заниматься offloading, Есть GPU-centic offloading, когда все вычисления происходят на GPU, и Hybrid Offloading (используемый в llama.cpp), где часть вычислений на GPU, а часть на CPU.
Основная проблема в том, что передача данных с GPU на CPU занимает уйму времени, и большая часть времени уходит на операции с памятью, пока ядра простаивают, и работает все дико медленно. Отсюда следует вывод, что ключом к ускорению является минимизация передачи данных между CPU и GPU.
Метод
В Deja Vu ранее было замечено, что в слоях трансформера активируется малая часть активаций для конкретного входа. Здесь же развили идею и заметили, что нейроны активируются неравномерно, и некоторые активируются часто - так называемые “горячие” 🔥, а другие же только время от времени (“холодные” ❄️). В частности, для OPT-30B 26% (для Llama-2-70B 43%) наиболее часто активируемых нейронов отвечают за 80% суммарной величины активаций. Статистики активаций считаются в offline режиме на подвыборке из c4 и wikipedia.
Отсюда возникает идея - держать горячие (коих не очень много) нейроны на GPU постоянно, а холодные - предсказывать с помощью специальных слоев, и подгружать по мере необходимости. Оказывается даже, что практичнее не выгружать холодные нейроны на GPU (для малых батчей), а считать на CPU.
Следующий нюанс в том, что делать со слоями, предсказывающими активные нейроны среди “холодных”. Держать их памяти - накладно для больших моделей, а наивное использование предикторов с меньшим числом параметров просаживает качество. И оказывается, что в слоях, где больше sparsity, можно использовать более слабый предиктор, и потому размер предиктора подбирается для каждого слоя отдельно.
На GPU мы работаем с матрицами фиксированного размера, и потому пользуемся эффективными ядрами для GEMM, а для CPU, обладающим куда меньше параллелизмом, отдельные вектор-векторные произведения считаются и так эффективно.
BY КПД
Share with your friend now:
tgoop.com/quant_prune_distill/174