- Key idea
- Bits, bytes, 2ⁿ patterns, unsigned and signed (two’s complement) integers, overflow
- Real world
- A car’s odometer with 6 digits counts from 000000 to 999999, then rolls back to 000000. Fixed digits mean a fixed range.
- In an LLM
- A 4-bit weight can only be one of 16 patterns. Everything a 4-bit model knows has to be written with those 16 symbols, plus a few scale numbers.
A bit is a switch
A bit is the smallest unit of storage: a single switch that is either 0 or 1. Group 8 of them and you have a byte, the unit file sizes and memory are measured in.
The key fact: n bits give 2ⁿ different patterns. One bit has 2 (0, 1). Two bits have 4 (00, 01, 10, 11). Every extra bit doubles the count:
| Bits | Patterns | Typical use |
|---|---|---|
| 1 | 2 | yes or no |
| 4 | 16 | a 4-bit quantized weight |
| 8 | 256 | one byte; an 8-bit weight or a text character |
| 16 | 65,536 | a bf16 or fp16 weight |
| 32 | about 4.3 billion | an fp32 number |
A pattern on its own means nothing. A format is the rule that says which number each pattern stands for. This whole course is about choosing that rule well.
Integers: binary counting
The simplest rule is binary counting. Each position is worth twice the one to its right: 1, 2, 4, 8, 16, … A pattern’s value is the sum of the positions holding a 1. With 8 bits, 00101010 is , and the range is 0 to 255. This is an unsigned 8-bit integer, uint8.
Try it
Negative numbers: two’s complement
To store negatives, computers use two’s complement: the leftmost bit is worth minus its usual value. In 8 bits it is worth −128 instead of +128, so 11111111 is and the range becomes −128 to 127. This is int8, the most common integer format in quantization. int4 runs from −8 to 7.
It looks odd, but it makes ordinary binary addition work for negative numbers with no special cases, which is why every processor uses it.
A 6-digit odometer has readings. Drive one more mile at 999,999 and it shows 000,000: the count overflows and wraps around. Nothing is wrong with the car; the display simply has no pattern for a million.
When a GPU multiplies int8 weights by int8 activations, each product can be as large as , far beyond int8’s range. Adding up thousands of such products in int8 would overflow immediately, so hardware accumulates them in int32, then scales the result back down. Quantized formats are for storing numbers; the arithmetic in between usually uses more bits.
Integers are evenly spaced
Integer patterns stand for evenly spaced numbers: every step is exactly 1. That is fine for counting, but a model’s weights are numbers like 0.0123 and −0.0471. To store those as integers you need an extra number, a scale, that says what one step is worth. That is the core trick of quantization, coming up in what quantization is. First, the format models are trained in: floating point.
Where this shows up
- Bits per weight decide a model’s size: how much memory a model needs.
- int8 and int4 are the targets of integer quantization: what quantization is.
- GGUF files pack several 4-bit codes into each byte: GGUF and llama.cpp.
Definitions
An -bit unsigned integer with bits :
In two’s complement the top bit has negative weight:
To negate a number, flip every bit and add 1. Overflow is arithmetic modulo .
Packing
Memory is addressed in bytes, so sub-byte formats pack several values per byte: two 4-bit values per byte (“nibbles”), four 2-bit values. A 4-bit tensor of values takes bytes plus its scales. Unpacking is a shift and a mask, e.g. lo = b & 0x0F, hi = b >> 4.