Skip to main content

Module ternary

Module ternary 

Source
Expand description

BitNet b1.58 ternary quantization codec — STELLAR §A compression (task #12).

Ternary packing of weights ∈ {-1, 0, +1} with a per-tensor absmean scale (BitNet 1.58b): it replaces fused multiply-adds with hardware adds/subtracts in the GEMM kernels and shrinks the weights to ≈ 1.6 bits each. This module is the reusable codec; it is applied during transcode by crate::p64_weight::transcode_safetensor_to_p64_ternary so a P64 image ships compressed, not as a verbatim blob.

§Encoding

  • Quantize (per tensor): scale = mean(|w|); t_i = clamp(round(w_i / scale), -1, +1).
  • Dequantize: w_i ≈ scale · t_i.
  • Packing: five trits per byte in base-3 (3⁵ = 243 ≤ 256) → 8 bits / 5 trits = 1.6 bits/weight. A trit {-1,0,+1} is offset to a digit {0,1,2}; a byte is d₀ + 3·d₁ + 9·d₂ + 27·d₃ + 81·d₄.

The hot-path dequant (dequantize_ternary) is zero-heap (it streams base-3 digits straight into the caller’s f32 buffer — no intermediate trit Vec). The encode path runs at ingest (cold), where a working Vec is acceptable.

Constants§

GGML_TYPE_TERNARY_158
Engine element-type code for a BitNet-1.58b ternary tensor (well outside the GGML code range, so it never collides with F32=0 / F16=1 / Q8_0=8 / Q4_K=12 / BF16=30). Mnemonic: “1.58b”.
TERNARY_GEMM_2BIT_WGSL
The branchless 2-bit WGSL ternary-GEMM kernel; CPU oracle is ternary_gemm_cpu_2bit.
TERNARY_GEMM_WGSL
The WGSL ternary-GEMM compute kernel (STELLAR §A). Its CPU parity reference is ternary_gemm_cpu, which mirrors it byte-for-byte (same trit extraction, add/subtract, end-scale). The GPU pipeline binds: 0 activations (f32), 1 packed trits (u32 words), 2 TernaryParams uniform, 3 output (f32).
TRITS_PER_BYTE
Trits packed per byte (3⁵ = 243 ≤ 256).
TRITS_PER_BYTE_2BIT
Trits packed 4-per-byte, 2 bits each: 0b00 = 0, 0b01 = +1, 0b10 = -1 (0b11 unused).

Functions§

dequantize_blob
Decode a ternary_blob of count weights into out (zero-heap dequant).
dequantize_ternary
Dequantize packed ternary → f32 weights (scale · trit) into out. Zero-heap: digits are streamed straight from the bytes (no intermediate trit allocation). Writes out.len() values.
pack_trits
Pack ternary values (i8 ∈ {-1,0,+1}) into bytes (5 trits/byte, base-3). The final partial group is zero-padded (decodes back to the requested count via unpack_trits_into).
pack_trits_2bit
Pack ternary values into 2-bit codes, 4 per byte.
packed_trit_len
Bytes needed to pack count trits (5 per byte).
packed_trit_len_2bit
Bytes to pack count trits at 2 bits each (4/byte).
quantize_ternary
BitNet 1.58b quantize: per-tensor absmean scale + ternary values ∈ {-1,0,+1}. A zero (or empty) tensor yields scale = 0.0 and all-zero trits.
rebake_ternary_blob_to_2bit
Rebake an on-disk base-3 ternary_blob ([scale f32 LE][5-trits/byte]) into the runtime 2-bit branchless VRAM layout consumed by [ternary_gemm_2bit.wgsl] / ternary_gemm_cpu_2bit.
ternary_blob
Encode a weight tensor to a self-describing ternary blob: [scale: f32 LE][packed trits]. (The element count is recovered from the tensor’s shape in the container manifest.)
ternary_blob_len
Total ternary-blob length for count weights: a 4-byte f32 scale + the packed trits.
ternary_gemm_cpu
CPU oracle for ternary_gemm.wgsl. Computes out[m][i] = scale · Σ_j trit(W[i][j])·act[m][j] where packed holds the row-major trits of an (n_out × n_in) weight matrix. The weight contributes by add/subtract only (the BitNet win); the per-tensor scale is applied once per output element. Zero-heap. Strides default to dense (n_in / n_out) when 0.
ternary_gemm_cpu_2bit
CPU oracle for ternary_gemm_2bit.wgsl — same math as ternary_gemm_cpu, 2-bit packing + branchless accumulation.
trit_at
Extract the ternary value {-1,0,+1} at linear weight index k from packed trits — the exact operation ternary_gemm.wgsl::trit_at performs (5 trits/byte, base-3).
trit_at_2bit
Trit value {-1,0,+1} at linear index k from 2-bit packing — the branchless mirror of ternary_gemm_2bit.wgsl::pair_at ((code==1) - (code==2)).
unpack_trits_into
Unpack out.len() trits from packed bytes into the caller’s buffer (zero-heap). Returns the number written (min(out.len(), packed capacity)).