Optimal patch size for dynamic-patching byte LMs — what the record actually measures
Date: 2026-10-18. Read-only: one file created, no code touched, nothing committed, no GPU.
Ask: what patch size should our byteflow patcher target — is 4-8 bytes right, does it
scale with d_global, and what do byteflow_eps2 / byteflow_k_tokens control?
Builds on, does not repeat: docs/reviews/patching-research-2026-10-02.md (architecture
choice; BLT’s scheme ablation; SpaceByte Table 1) · docs/research/2026-10-16-jepa-dspark-alternatives.md
(2610.11790) · docs/reviews/byteflow-rate-2026-10-02.md (our 4× vs the paper’s 2.56×) ·
docs/research/2026-10-18-data-capacity.md. This pass is about size, not whether to patch.
Method: arXiv MCP only, ~25 calls, no 429s, every ID resolved individually; repo numbers
name their file. The brief’s 2026-09-26-byte-lm-recipes.md does not exist on disk.
[A] = authors’ abstract · [F] = paper full text, read this session · [ours] = our
measurement · [S] = my inference.
Verdict table (claim → source → what it measured)
Section titled “Verdict table (claim → source → what it measured)”| # | claim | source | what it measured |
|---|---|---|---|
| 1 | Dynamic byte LMs run ~4-6 bytes/patch; the flagship 8B BLT-Entropy is 4.5 | 2412.09871 [F] | 8B, 4.5T bytes: avg 4.5 B/patch, avg task 61.1 vs Llama-3 8B (4.4 B/token) 60.0; BLT-Space 6.1 → 58.0 (Table 1) |
| 2 | BLT swept ps = 6 and 8 only; no patch-size ablation; ps=8 loses at 1B, wins at 7B | 2412.09871 [F] | FLOP-equivalent pairs at fixed inference FLOPs: 470m → ps6 610m / ps8 760m; 3.6B → 5.2B / 6.6B (Table 2); “ps 8 starts … worse … at 1B but ends up better than bpe at 7B” (§5.1); search_paper_text “patch size ablation” → 0 passages |
| 3 | Quality falls monotonically as patches grow at fixed model | 2605.09630 [F] | NLU avg p=4 52.9, p=8 52.2, p=16 48.0 (byte baseline 54.1); code pass@1 28.1 / 24.1 / 18.2 (Tables 1-2) |
| 4 | ByteFlow’s own sweep: best at the lowest compression, graceful to 5.12× | 2603.03583 [F] | 600M/50B: 2.0× 51.74, 2.56× (default) 50.89, 3.41× 50.13, 5.12× 48.48; 1.3B/500B: 64.44 → 60.91 |
| 5 | MegaByte (fixed stride): P=8 for text; at matched compute, shift capacity local → global wins | 2305.07185 [F] | PG19: patch 8, ctx 8192, global 758M / local 262M; audio P=32, Image64 P=12; 350M/290M → 1.014, 760M/262M → 1.002, 1.3B/218M → 0.991 (Table 10) |
| 6 | H-Net: 1-stage realizes BPIC ≈ 4.7-4.8, 2-stage (3,3) ≈ 7, and multi-stage beats one stage at the same FLOPs | 2507.07955 [F] | Large: 2-stage bpb 0.743 / acc 55.5 vs 1-stage 0.755 / 53.6; XL: 0.715 / 58.2 vs 0.728 / 56.2 (Tables 1-2) |
| 7 | Larger patches are bought back by intra-patch compute (SP), never for free | 2605.09630 [F] | p=16+SP ≈ byte baseline (54.2 vs 54.1) with 3-4× less inference compute and 16× smaller patch KV; p=8+SP 53.8 < p=4+SP 56.2 |
| 8 | Entropy patching at a 10-byte budget collapses on computed values | 2610.11790 [A] | BLT-1B: 10% patch starts (≈10 B/patch, [S]) → 19.0% exact on GSM8K computed results; 26% (≈3.85 B/patch) → 76.8%; survives LoRA (32.9 vs 72.7) |
| 9 | A compression-ratio curriculum (low → high) helps — slightly | 2605.30080 [A] | H-Net 350M, FineWeb-Edu 100B: adaptive N 8.0→9.5, avg 47.3 vs fixed 46.2-47.0; robustness 29.0 vs 28.8-28.9; val BPB ≈0.828 all |
| 10 | The byte-level encoder+decoder doesn’t shrink with patch size, so the measured saving is well under the nominal p× | 2412.09871 + 2605.09630 [F] | “larger patch sizes only affect flops from the patch Latent Transformer”; 20× params (400M→8B) ⇒ local params ~2×; seq reduction vs measured FLOPs/byte: p=4 4.0×/3.1×, p=8 8.0×/4.5×, p=16 16×/5.7× |
| 11 | The light-encoder/heavy-decoder split is the published choice | 2412.09871 [F] | Table 9: 1 encoder + 9 decoder layers 0.822 bpb vs 5+5 0.844 (with n-gram hashes) / 0.843 (without) |
| 12 | We already ran 4 B/patch (K=128 over 512 B) and won the 200-step smoke | [ours] | configs/byteflow.toml (byteflow_9m); 3.466 vs plain 3.947 equal-params, full-arm small loses 6.498 (benches/history.tsv:157-159 via docs/decisions/2026-10-15-1b-readiness-plan.md:21); 4.82/4.90 vs 6.71/6.60 at eval@100, ~65 vs ~450 ms/step (byteflow-ab-2026-10-02.md) |
Q1 — what sizes do published patchers use and measure?
Section titled “Q1 — what sizes do published patchers use and measure?”The live band is 4-6 bytes/patch: BLT-Entropy 4.5 and BLT-Space 6.1 (2412.09871
Table 1); SpaceByte’s spacelike rule ≈ 6 on PG-19, ≈ 8 on Github (2404.14408, read in
patching-research-2026-10-02.md §1.3; Scratchpad measures it at 6.3); H-Net 1-stage
realizes 4.8 (2507.07955 Table 1); Scratchpad’s best-with-SP is p=4 (2605.09630).
Our own byteflow_9m A/B ran 4 B/patch [ours]. BLT’s “patch-size ablation” as such does
not exist: search_paper_text for “patch size ablation” returns 0 passages, and §7 ablates
cross-attention, n-gram hashes and encoder/decoder depth. What they picked: 4.5 bytes for
the 8B flagship, 6/8 for the study — the flagship is finer than the study’s optimum
[S: the flagship is FLOP-matched and 4.5 buys more patch steps; the paper does not explain
it].
Q2 — do LARGE patches (32-64 B) pay for text, and does the optimum scale with capacity?
Section titled “Q2 — do LARGE patches (32-64 B) pay for text, and does the optimum scale with capacity?”No source found for 32-64 B on text. The largest measured text setting anywhere in this
pass is Scratchpad’s p=16: the worst vanilla point (NLU 48.0, code 18.2), recovered only
to baseline by SP (54.2), and still below p=4+SP (56.2). MegaByte’s P=32 is audio, P=192
images (2305.07185 §7/§6.3) — no text setting above 16 B/patch exists in this pass. The
2610.11790 “10% of bytes” budget (≈10 B/patch, [S]) is the closest text datapoint and it
collapses (19.0% vs 76.8%).
Capacity scaling is real but is a claim about the global model, not text granularity: BLT
ps=8 overtakes ps=6 by 7B (2412.09871 §5.1), and at fixed inference FLOPs ps=8 buys a
1.7× latent model vs ps=6’s 1.3× (Table 2) — the bigger global model is where the
freed FLOPs go (MegaByte Table 10, row 5). Neither paper sweeps patch size against d_global
jointly, so “optimal patch size scales with d_global” is [S] — two scaling studies
support it, ByteFlow’s flat penalty is the counterweight: the compression cost did not
shrink 600M → 1.3B (3.26 vs 3.53 pts, 2603.03583 Table 6).
Q3 — the information-bottleneck argument, and a measured quality curve
Section titled “Q3 — the information-bottleneck argument, and a measured quality curve”The argument in print is cost, not bits-per-dimension: patch size is “the main factor for
determining the cost” because the global model runs once per patch (2412.09871 §3), and
MegaByte’s >98% of FLOPs sit in per-position FFNs, so P× fewer global positions funds a P×
larger global model (2305.07185 §2.1, via patching-research-2026-10-02.md). No paper
normalizes by d_global; no bytes-per-latent-dimension curve exists. The nearest formal
statement is ByteFlow’s rate-distortion derivation R_ε(h) = ½ logdet(I + (d/ε²)·HHᵀ)
(2603.03583 App. A, eq. 11) — ε² is the reconstruction noise variance, the scale below which
a new direction is not worth a boundary. Measured quality-vs-size curves exist, all
sloping down at fixed model: 2605.09630 (p=4/8/16), 2603.03583 Table 6/E.2 (2.0×-5.12×),
2412.09871 Table 1 (4.5 vs 6.1), 2610.11790 (3.85 vs 10 B/patch). The only upward moves change
something else too: a bigger global model (BLT), scratchpads (SP), or hierarchy (H-Net).
Q4 — does hierarchical patching dominate single-level large patches?
Section titled “Q4 — does hierarchical patching dominate single-level large patches?”At matched FLOPs and data, yes for H-Net: 2-stage (3,3) beats 1-stage at both scales (bpb 0.743/0.715 vs 0.755/0.728; acc 55.5/58.2 vs 53.6/56.2, 2507.07955 Table 2), and the abstract claims parity with a token transformer twice its size. AU-Net extends the idea to 3+ stages with schedules like (16, 8) at 1M context and (1000, 200, 25) at 5M (2502.14553 Table A2). H-Net’s own negative: fixed-width pooling is “much worse than all other H-Net variants” — the win is learned boundaries, not depth. Counter-evidence: SP degrades H-Net under strict FLOPs matching (2605.09630 §5.1), so “hierarchy dominates” holds for H-Net’s downsampling-with-DC, not universally.
Q5 — how much of the nominal p× saving survives?
Section titled “Q5 — how much of the nominal p× saving survives?”Structurally, only the latent transformer’s share scales as 1/p (row 10). Measured, in the
one paper that reports both columns side by side (2605.09630): sequence reduction
4.0×/8.0×/16.0× against measured FLOPs/byte reduction 3.1×/4.5×/5.7× at p=4/8/16 — i.e.
~78%/56%/36% of the nominal saving survives [S: the division is mine; the two columns are
theirs]. BLT’s layer ablation agrees prescriptively (row 11): make the encoder cheap, because
it is paid per byte. On our box the wall-clock share is smaller again: the 200-step smoke ran
~65 vs ~450 ms/step at equal bytes (byteflow-ab-2026-10-02.md), but the step is launch-bound
(AGENTS.md §3.1: 13.3% util, GEMMs ≈16% of a warm step), so a FLOP saving buys less wall clock
than its FLOP fraction — the arithmetic 2026-10-16-token-skipping.md already did for depth.
Q6 — patch-size curricula / tunable threshold schedules (2026)
Section titled “Q6 — patch-size curricula / tunable threshold schedules (2026)”Yes, one, and it is a compression-ratio curriculum, not a size curriculum: ATDC
(2605.30080) ramps the target N from 8.0 to 9.5 over training on H-Net 350M / FineWeb-Edu
100B, beating fixed N=7/8/9 by +0.3-1.1 points avg accuracy (47.3 vs 46.2-47.0) and +0.1-0.2
robustness, at essentially identical BPB (≈0.828); the authors call it “more stable training
dynamics”, not a quality jump. Adjacent, not curricula: BLT retunes the entropy threshold
at inference (0.6 → 0.1) to trade steps for task accuracy (2412.09871 §5.2), and 2610.22100
reports that switching boundary rules after training did not work. Nothing found
schedules patch size itself or ε².
What this means for our knobs (byteflow_eps2, byteflow_k_tokens)
Section titled “What this means for our knobs (byteflow_eps2, byteflow_k_tokens)”Read from the port, not assumed: byteflow.py:519 selects positions with
marginal_gains_exact(h, eps2) only under byteflow_logdet; the default L2 path calls
marginal_gains_l2(h) and never reads eps2 — so on every preset we ship, eps2 is inert
and compression is set entirely by K (select_positions is plain top-(K−1) over ΔR,
byteflow.py:408-424). ByteFlow itself rejected a threshold in favour of fixed top-K, for
the reason our eps2 is a trap: a global threshold is a “magic number” whose realized sequence
length varies per input and breaks the static graph (2603.03583 §4.2). So: eps2 deserves
no seed set; K is the knob. Our operating points: byteflow_9m ran K=128 / 512 B = 4
B/patch [ours]; the port default is K=3200 / 8192 B = 2.56 B/patch (config.py:268-290)
— finer than anything published (BLT 4.5, H-Net 4.8, SpaceByte 6.0-6.3). A patch-size sweep
should move K down (bigger patches), never up. The polygon and instruments exist:
port/scripts/ab_byteflow.py (unrun 3-seed driver at K=128/512; emits event=patch
mean/median/p90/histogram per run) and port/scripts/patch_rate.py (CPU probe, --k flag;
mean = T/K by construction; random-init caveat in its docstring — note ab_byteflow.py cites
it as scripts/patch_rate.py, the repo’s one dead path reference, though the file exists).
Pre-registered predictions for a patch-size sweep (K ∈ {200, 128, 96, 64, 32} over the 512-byte window = 2.56 / 4 / 5.33 / 8 / 16 B/patch; fixed bytes/step, fixed window, 3 seeds, and BLT’s own fairness rule — “we ensure that the number of bytes in each batch remains constant … to avoid giving larger patch sizes unfair advantage”, 2412.09871 §4.3):
- 4 vs 2.56 B/patch: BPB within the 3-seed spread, either direction. The curve is flat at the fine end in every source (ByteFlow 2.0× vs 2.56× = 0.85 pts at 600M), and at 9.2M the spread eats effects this size. If 2.56 wins by more than the spread, suspect loop positions per byte (more K = more compute), not patch quality.
- 8 B/patch: predicted loss, ΔBPB ≥ +0.05 vs 4 B/patch. Basis: Scratchpad p=4→8 costs 0.7 NLU points and 4.0 MBPP points; BLT’s ps=8 is worse at 1B.
- 16 B/patch: predicted loss, ΔBPB ≥ +0.15, and no win. The only published way to hold quality at p=16 is SP’s extra intra-patch compute — a new mechanism, not a K change.
- If any large-K arm wins BPB, check the confound first: BLT’s large-patch wins all spend the freed FLOPs on a bigger global model (Table 2: 1.7×), which the 9.2M polygon cannot express as a K sweep; SP’s wins are extra compute inside the patch.
- Hierarchy is the supported alternative if large patches are wanted for context length: H-Net’s 2-stage result (bpb 0.715 vs 0.728 at XL) is the evidence to buy.
VERIFIED vs SPECULATION
Section titled “VERIFIED vs SPECULATION”VERIFIED. All IDs and dates resolved through the arXiv MCP this session; all quoted
numbers are [A] or [F] as marked. Own-repo: configs/byteflow.toml (K=128,
max_bytes=512, eps2=0.5), port/src/dormouse/config.py:268-290 (K=3200, max_bytes=8192,
eps2=0.5), port/src/dormouse/model/byteflow.py:519 and :408-424,
port/scripts/ab_byteflow.py + port/scripts/patch_rate.py,
docs/reviews/byteflow-ab-2026-10-02.md, docs/decisions/2026-10-15-1b-readiness-plan.md:21
(3.466/3.947/6.498 via benches/history.tsv:157-159), AGENTS.md §3.1.
SPECULATION (mine). S1 “optimal patch size scales with d_global” — from BLT’s
1B-vs-7B crossover and its FLOP-matched pairs; no paper sweeps the two jointly. S2 the
~78/56/36% arithmetic in Q5 — my division of the paper’s two columns. S3 every prediction
at 9.2M. S4 that 2.56 B/patch is “finer than needed” — the band is 4-6 B/patch but BLT’s
flagship is 4.5 while its study favours 8, so the band’s width is not tight.
Confidence. HIGH on: the 4-6 B/patch band; the monotone decline at fixed model; eps2
inert on our default path; the encoder/decoder not scaling with patch size. MED on:
capacity-scaling (two studies, neither at our scale; ByteFlow’s counter-trend). LOW on:
any number at 9.2M, the 32-64 B question (no source), and the curve between 4 and 16 B/patch.
IDs resolved this session (all individually, no 429s)
Section titled “IDs resolved this session (all individually, no 429s)”Resolved: 2412.09871 (BLT, 2024-12-13) · 2404.14408 (SpaceByte, 2024-04-22) ·
2305.07185 (MegaByte, 2023-05-12) · 2507.07955 (H-Net, 2025-07-10) · 2603.03583
(ByteFlow, 2026-03-03) · 2605.09630 (Scratchpad Patching, 2026-05-10) · 2610.11790
(boundary dependence, 2026-10-08) · 2610.22100 (novelty patching, 2026-10-15) ·
2502.14553 (AU-Net / MBLM, 2025-02-20) · 2605.30080 (ATDC, 2026-05-28) · 2605.08044
(Fast BLT, 2026-05-08) · 2608.03599 (boundaries, 2026-08-04).
Failed to resolve: 2404.07974 — my first guess for SpaceByte; it resolves to a quant-ph
matchgate paper. 2305.07185 returned “not found in storage” on the first search_paper_text
call (needed download_paper first) — a tool-state error, not a bad ID.
Not found at all (named, not guessed): a BLT patch-size ablation; any 32-64 B/patch text
result; any bytes-per-latent-dimension curve; any patch-size curriculum.
Owed: a line in docs-site/tools/manifest.mjs — this task forbade touching other files.