Как стать автором
Обновить

Комментарии 10

По описанию похоже на GGML или GGUF Q4_0. Чем отличается, в чем преимущества?

Тем что not invented here.

В случае больших языковых моделей основным ограничивающим фактором является пропускная способность памяти. GGUF является форматом хранения, при котором коэффициенты квантуются, и модель начинает занимать меньше места, а уже в оперативной памяти по частям преобразуется в fp16 или bf16 для вычислений.

Мы же работаем с моделями существенно меньшего размера и квантуем не для эффективного сжатия в памяти в первую очередь, а для вычислений. В результате, у нас отличается и сама схема квантования, и подход к ее вычислению: мы квантуем веса, входные сигналы и вычисляем свертки полностью в целых числах, оптимизируя все методы для центральных процессоров.

GGUF является форматом хранения, при котором коэффициенты квантуются, и модель начинает занимать меньше места, а уже в оперативной памяти по частям преобразуется в fp16 или bf16 для вычислений.

Я конечно могу предположить, что кто-то использует GGUF именно так как вы описали, но насколько я помню llama.cpp использует процессорные AVX SIMD инструкци для паралельной обработки "low precise" данных. Поэтому разница в скорости между Q8 и Q4 примерно в полтора раза, как и между Q4 и Q2.

Для llama моделей схемы квантования qn_* устроены следующим образом: веса делятся на блоки и в каждом блоке квантуются независимо до n разрядов. То есть на каждый блок еще приходится несколько параметров схемы квантования (например, scale и bias, которые также могут иметь разную разрядность). В результате усреднения по сети получаются дробные значения bits per weight, которые можно, например, видеть в таблице. При этом на один вес приходится 2^n возможных значений.

Вычисление квантованных llama моделей, разумеется, использует AVX на CPU. Сначала квантованные веса загружаются в векторные регистры, чем сильнее квантована сеть, тем больше весов можно загрузить за один load. Далее эти веса распаковываются непосредственно на регистрах и вычисляется скалярное произведение с помощью AVX-инструкций. Проверили сейчас, непосредственно в llama.cpp для типов q4_0 и q8_0 выполняется распаковка в int8 для весов и fp16 для скейлов (сравните функции ggml_vec_dot_q4_0_q8_0 для типа q4_0 и ggml_vec_dot_q8_0_q8_0 для типа q8_0 тут) и скалярное произведение вычисляется умножением значений int8 c аккумулированием во float. То есть, разница в скорости для двух этих типов возникает за счет загрузки и распаковки весов, не самого вычисления скалярного прозведения.

В нашем случае диапазон значений веса не является степенью двойки и позволяет представить больше, чем 16 значений, однако позволяет нам имплементировать матричное умножение более эффективно, чем для 8-битных сетей.

В результате мы достигаем скорости практически как у 4-битных моделей, но 4.6-битные сети работают точнее.

Спасибо, теперь понятней. Почитал статью, интересно.
Не увидел в ней сравнения с существующими алгоритмами квантизации, только с 8 бит. Не проводили?

Также сравнились с 4 битами, для которых есть быстрая ЦПУ имплементация (дальше только тернарные, тернарно-бинарные и бинарные сети, которые заметно хуже по качеству), и 4.6-битное квантование лучше по качеству и всего на 4% медленнее.

Какое емкое описание. На 8 бит приходится аж 23 значения...

Они что, "изобрели" очередной FP-8/BF-8 (Которые анонсированы в видеокартах)?

Не запоздали ли? )

fp8/bf8 принципиально отличаются от нашей схемы квантования, так как это типы данных с плавающей точкой и для работы с ними нужны отдельные арифметико-логические устройства, которые есть не на всех центральных процессорах. Наш же тип использует линейную схему квантования и работает полностью в целых числах, скоро напишем подробную статью.

Изобретен квантоний.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий