← На главную

5 троичных весов в байт: BitNet b1.58 распаковывают умножением на 3

14.07.2026 20:53 · hackernews

Для BitNet b1.58 с троичными весами нужно как-то плотно упаковывать триты (троичные цифры) в байты. Идеал — log(3)/log(2) бита на трит, но на практике требуется быстрая параллельная распаковка, поэтому берут небольшие блоки. Оказалось, что 5 тритов отлично влезают в 8 бит — получается 1.6 бита на трит с эффективностью 99.06% от теоретического предела.

Упаковка простая: составляем из тритов число, как из цифр, и записываем его в байт. А вот распаковка — интереснее. Обычно цифры извлекают делением и остатком, но в SIMD (AVX2, ARM NEON) деление целых чисел не поддерживается. Выход — посмотреть на число как на фиксированную точку. Умножая 8-битный байт на 3, получаем 10-битное число, и два старших бита дают нужный трит. Никаких делений, только умножение.

Деление нужно только при упаковке, но в контексте LLM-весов пакуют редко, а распаковывают часто — так что такой перекос оправдан. Алгоритм использует потолочное деление (ceiling division), чтобы компенсировать ошибку округления при последующем извлечении тритов.

Проверка на C показала, что все 243 возможные комбинации (3^5) упаковываются и распаковываются без потерь. Этот метод уже применяется в llama.cpp для типов TriLMs и BitNet b1.58 — соответствующий pull request (#8151) включает SIMD-реализации для AVX2 и ARM NEON.

Читать оригинал →