§ 03

§ 03 · Matrix math

GPUs and tiles

Thousands of cores, each one holding a lottery ticket

A GPU is a chip with thousands of small cores. It was built to colour millions of pixels at once, and it turned out to be just as good at matrix multiplication, because every cell of the answer can be computed independently.

Pearl mining runs on GPUs, on the same circuits that serve AI models. This page explains how a GPU actually does the multiplication, and how Pearl turns that process into lottery tickets without slowing it down.

Try it

Run Pearl’s real mining steps on tiny matrices. Watch the output split into tiles, each tile keep its diary, and each diary become a ticket.

Toy miner

Pearl’s real mining steps, one at a time, on tiny matrices

Toy sizes Real jobs are thousands of rows wide, with rank-128 noise and odds near 1 in 10¹⁶ per ticket. The steps, hash functions and byte layouts here are mainnet’s.

time1,760,000,000 job key55e6f354 hash_A94afc3a4 hash_Bf146e798 seed_B05899146 seed_Ac40e9a24 tickets 94f9a7 cc31a8 325a4b d5cd77

Step 1 of 11

Start from a block template

A miner starts from a block template: the first 76 bytes of the header. Version, the previous block’s hash, the Merkle root of the transactions, the time and the difficulty bits. There’s no nonce. The last 32 bytes, the proof commitment, can only be filled in once a ticket wins.

Change the time and watch every fingerprint above change.

Real Pearl The template comes from pearld (getblocktemplate) with real hashes; the toy uses aa…aa and bb…bb. Same 76-byte layout, with both hashes byte-reversed.

Runs in your browser · toy parameters m × k × n = 4 × 16 × 4, r = 4 src/lib/miner.ts · runToyJob

How does a GPU multiply matrices?

The slow part of a GPU isn’t arithmetic. It’s fetching numbers from memory. So a fast multiplication is organised around reuse: load each number once, use it as often as possible.

The output is cut into blocks, and each block goes to a group of threads. In Pearl’s reference miner, a group computes a 128 × 256 block of the output. It walks along the shared dimension k in steps of 128: load a 128 × 128 piece of A′ and a 128 × 256 piece of B′ into fast on-chip memory, multiply them, add to the running sums, and move on.

128×256×128 MACs(128+256)×128 numbers loaded=4,194,30449,152≈85\frac{128 \times 256 \times 128 \ \text{MACs}}{(128 + 256) \times 128 \ \text{numbers loaded}} \;=\; \frac{4{,}194{,}304}{49{,}152} \;\approx\; 85
Each number fetched from memory feeds about 85 multiply-accumulates. That ratio is what keeps the arithmetic units busy.

Inside each group, tensor cores do the multiplying. A tensor core multiplies a small block of matrix in a single instruction. In integer mode it takes 8-bit inputs and adds the products into 32-bit sums, which is exactly the format of Pearl’s noisy matrices (see integers).

What is a hash tile?

A hash tile is a small patch of output cells whose running sums together make one lottery ticket. Every 128 steps along k, the tile’s running sums are XOR-ed into one 32-bit word and folded into a 64-byte diary; at the end, a keyed BLAKE3 hash of the diary is the ticket.

Pearl’s reference GPU miner uses tiles of 2 × 64 = 128 cells, with an odd-looking pattern: rows 0 and 8, and column pairs 0–1, 8–9, 16–17 and so on up to 248–249, all inside the 128 × 256 output block.

0808162432404856■ one thread’s accumulators: one 2 × 64 hash tile (32 of its 64 columns shown)Rows 0–15, columns 0–63 of a 128 × 256 output block; the pattern repeats to column 249.
The reference miner's hash tile, in the top-left corner of a GPU output block. The highlighted cells are rows 0 and 8 at columns 0, 1, 8, 9, 16, 17…

Why that pattern? It’s exactly the set of accumulator registers that one GPU thread holds in an NVIDIA Hopper tensor-core tile of width 256. (That’s the research’s reading of the kernel code, not a design rule Pearl states.) So each thread’s own registers are one ticket. It can XOR them together without exchanging any data with other threads, and the multiplication runs at full speed.

Doesn’t the hashing slow the GPU down?

Barely. The extra work per tile is one XOR per cell per checkpoint:

  • A checkpoint comes every 128 steps along k. For a 128-cell tile that’s 128 × 128 = 16,384 multiply-accumulates.
  • Folding them costs 128 XORs plus one rotate. That’s one cheap integer operation per 128 multiply-accumulates.
  • Those run on the GPU’s ordinary cores while the tensor cores keep multiplying.
  • At the very end, each tile needs one BLAKE3 hash of 64 bytes.

The cost that remains is the noise and its removal, a few percent (see rank and noise). Pearl Research Labs report about 5% total overhead serving Llama-3.3-70B on H200 GPUs, against an unspecified baseline.

How many tickets is a multiplication?

Every output cell belongs to exactly one tile, so:

tickets=m⋅ncells per tile,work per ticket=cells per tile×k\text{tickets} = \frac{m \cdot n}{\text{cells per tile}}, \qquad \text{work per ticket} = \text{cells per tile} \times k

For the shape declared in block 130,825’s certificate, m = 131,072 and n = 262,144 with 128-cell tiles and k = 8,192:

Value
Tickets in one multiplication 131,072 × 262,144 ÷ 128 = 268,435,456
Multiply-accumulates per ticket 128 × 8,192 = 1,048,576
Chance one ticket wins, at the snapshot difficulty about 9.3 × 10⁻¹⁷

The winning bar is scaled by each ticket’s work, so every multiply-accumulate has the same tiny chance, whatever the tile shape or matrix size. That’s why Pearl’s hashrate counts multiply-accumulates. See tickets and target.

Make a guess

A miner switches from 2 × 64 tiles to 8 × 16 tiles, same k. Does it win more often?

Think of your answer first, then check it.

Answer No.

Both shapes have 128 cells, so each ticket costs the same work and faces the same bar. And even with a bigger tile, the bar grows in proportion to the tile’s work. The chance per multiply-accumulate stays the same, which is the point.

How fast are real GPUs?

A 2026 study of pool data lists NVIDIA H100 workers at about 500 to 700 trillion multiply-accumulates per second, and RTX 3090s at 75 to 120 trillion. Explorers write these as “TH/s”, but on Pearl each “hash” is one multiply-accumulate. For what that means for your odds, try the mining odds tool.

Code: the reference miner's settings

From settings.py (miner/miner-base/src/miner_base/settings.py:9-26 at v1.5.2, on GitHub):

miner/miner-base/src/miner_base/settings.py Python
noise_rank: int = 128

# GEMM tile sizes
tile_size_m: int = 128
tile_size_n: int = 256
tile_size_k: int = 128

# Hash tile pattern for the 128x256 tile
rows_pattern: list[int] = [0, 8]
cols_pattern: list[int] = [
0, 1, 8, 9, 16, 17, 24, 25, 32, 33, 40, 41, 48, 49, 56, 57,
# … every 8 columns …
192, 193, 200, 201, 208, 209, 216, 217, 224, 225, 232, 233, 240, 241, 248, 249,
]

The XOR of a thread’s registers happens in the CUDA kernel, in pow_utils.hpp (miner/pearl-gemm/csrc/gemm/pow_utils.hpp:165-181 at v1.5.2, on GitHub).

The codex

Suggested

Up and down arrows move through the results, Enter opens one, Escape closes. Anywhere on the site, slash or Command K opens this search, and the square brackets [ and ] go to the previous and next page.