ngpt · experiments 1 and 2

Dory1.0-4B, re-measured: NVIDIA's looped nGPT against its own model card

With enough repeats and the card's own metric, Dory reproduces its model card at every loop count on GPQA Diamond, IFBench and AA-LCR, the three of its benchmarks this project can run. None of the four disagreements from the first round was about the model. The 4-loop shortfall was too few repeats plus a different IFBench metric than the card's. The AA-LCR gap was a single draw of 100 questions. The card's low score for its Qwen3.5-4B baseline comes in good part from a blank line Qwen writes before its answers: graded unstripped, Qwen loses 6 of the 6.6 points, though a faithful replay of NVIDIA's harness leaves 2–4 unexplained. And the card's 20–60% token savings were measured on multi-turn agent tasks, a different kind of task from the single-question reasoning tested here.

What the loop buys is concentrated in the second pass through the core: about 5 points on GPQA, 9 on AA-LCR and 4 on IFBench, and 0.009 bits per byte on held-out text, 95% of what eight passes achieve. It costs 1.4× the compute of one pass. Passes 3 and 4 add nothing these sets can resolve: the 2→4 step is −1.0 ± 1.0 on GPQA, +0.2 ± 0.8 on IFBench and +0.7 ± 2.7 on AA-LCR. On GPQA, one 2-loop pass matches a majority vote over five or six 1-loop samples at about a quarter of the compute.

Dory's lead over other small models is not produced by the loop. It is already there at 1 loop, and it grows on 22 instruction types this project wrote and nobody has published. NVIDIA's own non-looped 4B, run through the same harness, is 15–37 points behind. Post-training is the likeliest source, though nothing here isolates it: the only available control differs in model generation, architecture and reasoning length at once. On plain text Dory is a worse language model than Qwen3.5-4B at every loop count. The loop's largest single step is on long-document questions, which is also the noisiest set here.

Experiment 1: Mon 19 Oct 2026 (week 43), Modal workspace yaroslavvb, $41.64 of a $50 cap. Experiment 2 (the ablations): Mon 19 – Tue 20 Oct 2026, Misha Makarov's Modal workspace michael-76064, $301.94 of a $500 cap, about 63 GPU-hours. Claims: Boris Ginsburg's LinkedIn post of Sat 17 Oct 2026 and the model card it links (revision b366b87f). Code, every number's script, and this page: the private repo yaroslavvb/ngpt.

The four disagreements, settled

What experiment 1 found What experiment 2 measures Card Why
1 4 loops below the card: GPQA 70.7, IFBench 75.3 (prompt-loose) GPQA 73.1 ± 0.7; IFBench 78.8 ± 0.6 72.16 / 79.0 Two repeats of one resumed run, and a different IFBench metric
2 The card's Qwen3.5-4B IFBench 53.83 against our ~60 60.4; graded as the server returns it, 54.4 53.83 Qwen writes a blank line after its reasoning; graded unstripped it loses 6 points and Dory loses none. 2–4 points stay unexplained
3 AA-LCR at 1 loop 68 against 63 62.7 63 One draw of 100 questions; three fresh draws read 57, 68 and 63
4 Answers 6–15% shorter, the card says 20–60% 9–18% shorter 20–60% The card's chart is multi-turn agent tasks; nothing here is
NVIDIA's model cardThis run, with 95% intervalQwen3.5-4B reference
GPQA Diamond 70 75 80 1 2 3 4 Qwen run: 78.8 Qwen run 78.8 Qwen card: 77.7 Qwen card 77.7 NVIDIA card, 1 loop: 69.19 NVIDIA card, 2 loops: 72.41 NVIDIA card, 4 loops: 72.16 This run, 1 loop: 69.2 (95% interval 67.3 to 71.1) 69.2 This run, 2 loops: 74.1 (95% interval 72.3 to 75.9) 74.1 This run, 3 loops: 73.4 (95% interval 71.8 to 74.9) 73.4 This run, 4 loops: 73.1 (95% interval 71.7 to 74.6) 73.1 loops % correct
IFBench 60 70 80 1 2 3 4 Qwen run: 60.4 Qwen run 60.4 Qwen card: 53.8 Qwen card 53.8 NVIDIA card, 1 loop: 74.29 NVIDIA card, 2 loops: 77.94 NVIDIA card, 4 loops: 79.00 This run, 1 loop: 74.2 (95% interval 73.0 to 75.5) 74.2 This run, 2 loops: 78.6 (95% interval 77.4 to 79.7) 78.6 This run, 3 loops: 78.2 (95% interval 76.1 to 80.4) 78.2 This run, 4 loops: 78.8 (95% interval 77.7 to 79.8) 78.8 loops NVIDIA's metric
AA-LCR 60 70 1 2 4 Qwen card: 64.7 Qwen card 64.7 Qwen run: 64.0 Qwen run 64.0 NVIDIA card, 1 loop: 63.00 NVIDIA card, 2 loops: 71.00 NVIDIA card, 4 loops: 73.00 This run, 1 loop: 62.7 (95% interval 59.0 to 66.4) 62.7 This run, 2 loops: 71.3 (95% interval 68.6 to 74.1) 71.3 This run, 4 loops: 72.0 (95% interval 68.1 to 75.9) 72.0 loops % correct, judged
Benchmark 1 loop 2 loops 3 loops 4 loops Qwen3.5-4B
GPQA Diamond 69.2 ± 1.0 (4 repeats) / 69.19 74.1 ± 0.9 (4 repeats) / 72.41 73.4 ± 0.8 (4 repeats) 73.1 ± 0.7 (6 repeats) / 72.16 78.8 ± 1.1 / 77.71
IFBench, NVIDIA's metric 74.2 ± 0.7 (6 repeats) / 74.29 78.6 ± 0.6 (6 repeats) / 77.94 78.2 ± 1.1 (2 repeats) 78.8 ± 0.6 (7 repeats) / 79 60.4 ± 1.3 / 53.83
AA-LCR 62.7 ± 1.9 (3 draws) / 63 71.3 ± 1.4 (3 draws) / 71 – 72.0 ± 2.0 (2 draws) / 73 64.0 ± 4.8 / 64.7

Single pass with a 65,536-token output budget, complete repeats only. ± is the sampling error on these same questions (the right error for comparing with another measurement of the same set); a single draw gets the binomial bound. Repeat means also cluster by job (the two low 4-loop GPQA repeats in experiment 1 came from one resumed job), so some between-run variance sits outside these bars. IFBench is NVIDIA's metric: the mean over prompts of the fraction of instructions followed, strictly. Qwen3.5-4B's GPQA comes from a 32K-budget run whose budget did not bind (0.0–0.3% of traces reached it).

1. Four loops reproduce; the old shortfall was two repeats and a metric

At 4 loops, GPQA Diamond reads 73.1 ± 0.7 over 6 repeats against the card's 72.16. Experiment 1's 70.7 was two repeats from one run that had been stopped and resumed on a smaller batch. Its two repeats scored 69.7 and 71.7, against 72.2–75.8 in the six fresh ones. Every loop count is now at or above the card: 69.2 at 1 loop (the card's digits exactly), 74.1 at 2 against 72.41, 73.4 at 3 (the card has no 3-loop column).

IFBench at 4 loops reads 78.8 ± 0.6 over 7 repeats against the card's 79.0. Experiment 1 quoted prompt-level loose accuracy, the IFBench paper's headline, which reads 77.9 ± 0.6 here. The card's number is NVIDIA's own metric, the mean fraction of instructions followed, scored strictly. NeMo Gym's IFBench verifier defines it as mean/reward × 100 with grading_mode: fraction. The all-or-nothing strict rate reads 75.9 ± 0.6 and cannot be the card's metric: it is about 5 standard errors below. On NVIDIA's metric every loop count lands on the card: 74.2 against 74.29, 78.6 against 77.94, 78.8 against 79.

"4 loops is no better than 2" holds, as a statement about power. Paired on the same questions, GPQA's 2→4 step is −1.0 ± 1.0, and the card's own GPQA columns also step down (−0.25). IFBench gains at the second loop and then flattens, 74.2 → 78.6 → 78.2 → 78.8: the 1→2 step is +4.3 ± 1.1 (card +3.65) and 2→4 is +0.2 ± 0.8 (card +1.06). AA-LCR's 2→4 step is +0.7 ± 2.7. Our 2→4 steps sit within about 1 SE of the card's own 2→4 steps on all three benchmarks, so this is not a disagreement with the card either: a 4-loop gain under about 2 points cannot be resolved on these sets.

The card's cheaper last-loop KV cache keeps one cache per recurrent layer instead of one per loop. Each loop then attends to earlier tokens' final-loop states. It is not what separates us from the card. At 2 loops it matches per-loop caching (GPQA −1.0 ± 1.2, IFBench −0.5 ± 1.2). At 4 loops it reads +0.3 ± 0.9 on GPQA and +0.8 ± 0.9 on IFBench, both null. Its value is cost: at 4 loops it serves 1.34× the tokens per second on an H200, because the smaller cache fits twice the batch.

On NVIDIA's own GPQA prompt (the Artificial Analysis multiple-choice template with one fixed answer order per question), 2 and 4 loops match the card (73.2, 72.5) and 1 loop reads 66.4, 2.8 below it. This rests on 2 repeats with the answer position held fixed, so it bundles the prompt wording with position bias. The two answer extractors, simple-evals' regex and NVIDIA's lenient one, score all 8,514 Dory GPQA records identically; they pick a different letter on one, which both mark wrong.

2. The Qwen3.5-4B baseline: a blank line costs it six points

How Qwen3.5-4B's IFBench answers are read NVIDIA's metric (64K Qwen sampling / 64K NeMo Gym sampling / 32K)
Our run, answer stripped (our convention) 60.4 / 60.5 / 58.9
Qwen's own model card 59.2
Same answers, graded exactly as returned (leading blank line kept) 53.6 / 54.4 / 53.1
Replay of NVIDIA's harness (also grades unfinished traces' reasoning) 56.2 / 58.1 / 55.8
NVIDIA's card 53.83
Thinking switched off (whole reply graded) 32.8
Reasoning graded together with the answer 29.3 / 28.7 / 30.0

Qwen3.5-4B closes its reasoning with </think> followed by a blank line before the answer. It does this on 99.4–99.8% of the replies where it finishes; Dory starts its answer immediately on 99.3–99.5% of them. Graded on the text after </think> with the whitespace stripped, which is this project's convention, Qwen reads 60.4 on NVIDIA's metric. That sits on Qwen's own card (59.2). IFBench's strict scorer grades the response as given, and NeMo Gym passes it the reply as the server returns it. Graded that way, Qwen reads 54.4 under NeMo Gym's sampling, against the card's 53.83. The difference is all leading whitespace: stripping only the left side reproduces the stripped score, and stripping only the right side reproduces the raw one. The loss falls on whitespace- and layout-sensitive checkers (format:no_bullets_bullets, line_indent, options, no_whitespace, custom:csv_*). 37–42 instructions flip from pass to fail and none flip back. Dory's 3,731 rollouts flip none. NVIDIA's numbers show the same pattern across the whole Qwen family: the card reads Qwen3.5-4B 5.4 points below Qwen's own report on IFBench and Qwen3.5-9B 5.5 below. The same card reads the same model 1.5 points above Qwen's GPQA and 7.7 above its AA-LCR.

It is not a complete reconciliation. NeMo Gym grades the last output item. When a reply never closes its reasoning, which happens on 21% of Qwen's IFBench replies under NVIDIA's sampling, that item is the reasoning itself rather than an empty answer. A replay of that rule reads 55.8–58.1, which leaves 2–4 points unexplained. NVIDIA also sets no output cap, and more budget would raise Qwen further. The reading also assumes a reasoning parser that splits on </think> alone; vLLM's qwen3 parser would have graded whole replies, giving about 29. The unstripped reading is the closest of 52 hypotheses checked, so its near-exact match is partly selection. What does not depend on selection is the mechanism and its size: about 6 points for Qwen and none for Dory. The other hypotheses ruled out include NVIDIA's sampling, output caps, metric definitions, reasoning switched off, reasoning graded with the answer, and IFBench and checkpoint revisions.

Qwen3.5-4B (NeMo Gym sampling)Dory, 1 loopDory, 2 loopscard, Qwencard, 1 loopcard, 2 loops
IFBench under an output cap4060808K12.5K16K24K32K64Koutput tokens allowed (64K = the full run)NVIDIA's metriccard, Qwen: 53.83card, 1 loop: 74.29card, 2 loops: 77.94Qwen3.5-4B (NeMo Gym sampling), output tokens allowed (64K = the full run) 8K: 34.8Qwen3.5-4B (NeMo Gym sampling), output tokens allowed (64K = the full run) 12.5K: 54.2Qwen3.5-4B (NeMo Gym sampling), output tokens allowed (64K = the full run) 16K: 58.2Qwen3.5-4B (NeMo Gym sampling), output tokens allowed (64K = the full run) 24K: 59.8Qwen3.5-4B (NeMo Gym sampling), output tokens allowed (64K = the full run) 32K: 60.2Qwen3.5-4B (NeMo Gym sampling), output tokens allowed (64K = the full run) 64K: 60.5Dory, 1 loop, output tokens allowed (64K = the full run) 8K: 40.2Dory, 1 loop, output tokens allowed (64K = the full run) 12.5K: 60.5Dory, 1 loop, output tokens allowed (64K = the full run) 16K: 69.3Dory, 1 loop, output tokens allowed (64K = the full run) 24K: 75.3Dory, 1 loop, output tokens allowed (64K = the full run) 32K: 76.0Dory, 1 loop, output tokens allowed (64K = the full run) 64K: 76.0Dory, 2 loops, output tokens allowed (64K = the full run) 8K: 43.6Dory, 2 loops, output tokens allowed (64K = the full run) 12.5K: 64.9Dory, 2 loops, output tokens allowed (64K = the full run) 16K: 73.8Dory, 2 loops, output tokens allowed (64K = the full run) 24K: 77.2Dory, 2 loops, output tokens allowed (64K = the full run) 32K: 77.6Dory, 2 loops, output tokens allowed (64K = the full run) 64K: 77.9■ card, 2 loops 77.94■ Dory k=2 77.9■ Dory k=1 76.0■ card, 1 loop 74.29■ Qwen 60.5■ card, Qwen 53.83

An output cap of about 12.5K tokens is the other way to put Qwen on 53.83, which is why we tested it. The same cap puts Dory at 60–65 against its own card's 74–78, so NVIDIA's harness did not cut answers short.

So the card overstates Dory's IFBench lead over Qwen3.5-4B. Under our convention the gap is 13.8 ± 2.3 at 1 loop and 18.2 ± 2.3 at 2 loops, paired over the same 300 prompts. The card implies 20.5 and 24.1.

3. AA-LCR: one draw of 100 questions is not a measurement

Three independent single-pass 1-loop draws of the same 100 long-document questions read 57, 68 and 63, mean 62.7 against the card's 63 (the draw-to-draw error is ±3.2); they disagree on 32 of the 100 questions. Experiment 1's 68 was a fourth draw, cut at 32K and continued. The first analysis read the 11-point gap between it and the 57 draw as an effect of the budget convention (McNemar p = 0.04). Against the two later draws the same comparison gives p = 1.00 and 0.41: it was noise. At 2 loops: 69, 72 and 73, mean 71.3 against 71. At 4 loops: 72 and 72, mean 72.0 against 73. The second loop is worth +8.7 ± 3.1 points paired on the same questions, against the card's +8; the third and fourth add nothing measurable (+0.7 ± 2.7).

The judge is not the variable. Re-running gpt-oss-120b on the same answers changed 0–2 verdicts in 100, and so did running it at temperature 1 or with the AA-LCR card's older v1.0 prompt: every pass lands within 2 points. NVIDIA's own judge, Qwen3-235B-A22B-Instruct-2507-FP8 under NeMo Gym's strict one-word protocol, re-graded 12 complete answer sets: it reads −1 to +2 points against gpt-oss-120b (mean +0.4), and puts the single-pass draws at 63.7 at 1 loop, 70.3 at 2 loops, 72.0 at 4 loops (card 63, 71, 73). Qwen3.5-4B reads 64.0 under gpt-oss-120b and 65.0 under NVIDIA's judge (card 64.7); Nemotron-3-Nano-4B reads 18.0 and 19.0: it answers 100K-token documents in a median 770 output tokens.

A note on method, because it cost money. vLLM was seeded once per engine (seed 0) and requests carried no seed of their own. So a "repeat" launched as a separate job, with the same prompts in the same order at the same batch size, reproduced the first run token for token. Two AA-LCR "repeats" were byte-identical copies (100/100 answers), and three more were copies in progress. Every run is now seeded from its tag, every pool is checked for identical text before it is used, and the copies are excluded. GPQA repeats were never affected (each repeat reorders the answer choices, so the prompts differ), and neither were the IFBench repeats, which were checked.

4. Shorter answers, but not 20–60% shorter

2 loops4 loops
0×0.2×0.4×0.6×0.8×1×1.2×This run (single-turn reasoning)GPQA DiamondGPQA Diamond, 2 loops: 0.91× the tokens of 1 loop0.91×GPQA Diamond, 4 loops: 0.89× the tokens of 1 loop0.89×IFBenchIFBench, 2 loops: 0.90× the tokens of 1 loop0.90×IFBench, 4 loops: 0.87× the tokens of 1 loop0.87×AA-LCRAA-LCR, 2 loops: 0.84× the tokens of 1 loop0.84×AA-LCR, 4 loops: 0.82× the tokens of 1 loop0.82×NVIDIA's card (multi-turn agentic)Terminal-Bench 2.1Terminal-Bench 2.1, 2 loops: 0.72× the tokens of 1 loop0.72×Terminal-Bench 2.1, 4 loops: 0.50× the tokens of 1 loop0.50×GDPval-AA-V2GDPval-AA-V2, 2 loops: 0.66× the tokens of 1 loop0.66×GDPval-AA-V2, 4 loops: 0.40× the tokens of 1 loop0.40×SWE-bench VerifiedSWE-bench Verified, 2 loops: 0.79× the tokens of 1 loop0.79×SWE-bench Verified, 4 loops: 0.74× the tokens of 1 loop0.74×τ³-Bankingτ³-Banking, 2 loops: 0.80× the tokens of 1 loop0.80×τ³-Banking, 4 loops: 0.77× the tokens of 1 loop0.77×1 loop = 1×
Benchmark 2 loops ÷ 1 3 loops ÷ 1 4 loops ÷ 1
GPQA Diamond 0.91× ± 0.01 0.89× ± 0.01 0.89× ± 0.01
IFBench 0.90× ± 0.03 0.90× ± 0.03 0.87× ± 0.02
AA-LCR 0.84× ± 0.02 – 0.82× ± 0.04

Total output tokens at k loops divided by total at 1 loop, paired over the same questions, single pass at 64K. The card's chart is four multi-turn agent benchmarks at 2 and 4 loops.

Looping shortens Dory's answers by 9–18%. The whole saving is in the reasoning; the final answer is the same length at every loop count. The saving keeps growing past 2 loops even though accuracy does not: on GPQA, 4 loops write 369 ± 158 fewer tokens than 2 for no change in score. On GPQA, looping also shortens what Dory gets right more than what it gets wrong: controlling for the length of the 1-loop answer, questions 1 loop never gets right shrink 10% less at 4 loops than questions it does (on IFBench and AA-LCR the same effect is within noise).

The card's 0.40–0.80 ratios are Terminal-Bench, GDPval, SWE-bench and τ³-Banking. Those are multi-turn agent tasks, where a shorter or better first step can remove whole tool-call turns. None of that exists in a single-question benchmark, and this project did not run an agent harness. Single-question traces don't bridge the gap either. Across questions, the ratio falls only weakly with how long the 1-loop answer was. After correcting for the fact that the same noisy length appears in both the ratio and the predictor, the trend is about 4% per doubling, with a confidence interval that includes zero. So the card's agent numbers stay NVIDIA's measurement, unconfirmed here.

What a loop is worth

Dory has 36 blocks, each one attention layer plus one MLP (72 layers in the usual count): 8 input blocks, a 20-block core and 8 output blocks. The core runs k times per token, with the input blocks' output re-injected on every pass. 9 of the 36 attention layers use full attention (the rest a 1,024-token sliding window), and 5 of those 9 sit inside the core, so 2 loops apply 14/9 = 1.56× the full attention of one. The loop count is set at inference time; the checkpoint ships with 2.

Per thinking token

1 loop2 loops4 loops
GPQA Diamond: accuracy at a forced thinking budget405060701K2K4K8K16Kreasoning tokens allowed% correct1 loop, reasoning tokens allowed 1K: 38.4 (95% 34.1 to 42.6)1 loop, reasoning tokens allowed 2K: 42.2 (95% 38.0 to 46.3)1 loop, reasoning tokens allowed 4K: 53.8 (95% 50.1 to 57.5)1 loop, reasoning tokens allowed 8K: 60.4 (95% 57.0 to 63.7)1 loop, reasoning tokens allowed 16K: 67.7 (95% 65.1 to 70.3)2 loops, reasoning tokens allowed 1K: 43.2 (95% 39.3 to 47.0)2 loops, reasoning tokens allowed 2K: 47.0 (95% 43.3 to 50.6)2 loops, reasoning tokens allowed 4K: 57.6 (95% 54.2 to 60.9)2 loops, reasoning tokens allowed 8K: 65.9 (95% 63.1 to 68.8)2 loops, reasoning tokens allowed 16K: 71.0 (95% 68.5 to 73.4)4 loops, reasoning tokens allowed 1K: 42.2 (95% 37.9 to 46.4)4 loops, reasoning tokens allowed 2K: 48.2 (95% 44.2 to 52.2)4 loops, reasoning tokens allowed 4K: 57.8 (95% 54.5 to 61.1)4 loops, reasoning tokens allowed 8K: 65.2 (95% 62.1 to 68.2)4 loops, reasoning tokens allowed 16K: 69.4 (95% 66.7 to 72.2)■ 2 loops 71.0■ 4 loops 69.4■ 1 loop 67.7
1 loop2 loops4 loops
IFBench: accuracy at a forced thinking budget4060801K2K4K8K16Kreasoning tokens allowed% of prompts, loose1 loop, reasoning tokens allowed 1K: 37.3 (95% 35.1 to 39.6)1 loop, reasoning tokens allowed 2K: 43.5 (95% 41.1 to 45.9)1 loop, reasoning tokens allowed 4K: 53.7 (95% 51.2 to 56.2)1 loop, reasoning tokens allowed 8K: 63.3 (95% 60.7 to 65.9)1 loop, reasoning tokens allowed 16K: 71.8 (95% 69.3 to 74.3)2 loops, reasoning tokens allowed 1K: 43.7 (95% 41.4 to 45.9)2 loops, reasoning tokens allowed 2K: 49.8 (95% 47.6 to 52.1)2 loops, reasoning tokens allowed 4K: 55.8 (95% 53.4 to 58.3)2 loops, reasoning tokens allowed 8K: 65.0 (95% 62.4 to 67.6)2 loops, reasoning tokens allowed 16K: 74.5 (95% 72.1 to 76.9)4 loops, reasoning tokens allowed 1K: 44.7 (95% 39.0 to 50.3)4 loops, reasoning tokens allowed 2K: 49.3 (95% 43.7 to 55.0)4 loops, reasoning tokens allowed 4K: 56.7 (95% 51.1 to 62.3)4 loops, reasoning tokens allowed 8K: 68.0 (95% 62.7 to 73.3)4 loops, reasoning tokens allowed 16K: 74.0 (95% 69.0 to 79.0)■ 2 loops 74.5■ 4 loops 74.0■ 1 loop 71.8

Budget forcing cuts each reasoning trace at B tokens and asks for the answer. At every budget from 1K to 16K, 2 loops beat 1 by 3–6 points on GPQA and 2–6 on IFBench. On GPQA, 2 loops at 8K come within 2 points of 1 loop at 16K, and 2 loops reach 1 loop's full-budget accuracy with 0.74× its tokens. 4 loops track 2 loops within noise at every budget.

Against more samples

1 loop, majority of 1, 3, 5… samples2 loops, majority of 1, 3, 5… samples3 loops, majority of 1, 3, 5… samples4 loops, majority of 1, 3, 5… samples
GPQA Diamond: more loops or more samples?707274123456810121416compute per question, × one 1-loop sample% correct1 loop, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 1: 69.41 loop, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 3: 71.91 loop, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 5: 73.11 loop, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 7: 73.82 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 1.36722: 73.22 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 4.10165: 74.62 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 6.83609: 75.32 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 9.57053: 75.43 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 1.68447: 73.43 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 5.05342: 74.34 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 2.14482: 72.54 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 6.43445: 74.04 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 10.7241: 74.14 loops, majority of 1, 3, 5… samples, compute per question, × one 1-loop sample 15.0137: 73.9■ 2 loops 75.4■ 3 loops 74.3■ 4 loops 73.9■ 1 loop 73.8

This panel pools experiment 1's 32K-continued repeats with the 64K ones, because a five- or six-sample vote needs more than four repeats: 8 repeats at 1 and 2 loops (four continued), 8 at 4 loops (two continued), 4 at 3 loops (64K only). That is why 2 loops reads 73.2 here against 74.1 in the score table, and 4 loops 72.5 against 73.1. Compute is matrix-multiply and attention FLOPs at each arm's measured prompt and output length, relative to one 1-loop sample. The pooled 1-loop arm's prompts include experiment 1's re-fed traces, which is why a 2-loop pass reads 1.37× here and 1.39× in "What a loop costs" (3 loops 1.68× against 1.79×).

Spending the compute on more samples instead of more loops, with majority vote: one 2-loop pass (73.2% at 1.37× the compute of a 1-loop sample) matches a five-sample 1-loop vote (73.1% at 5×) and a six-sample one (73.3% at 6×, 4.4× its cost). Above about twice the 1-loop cost, more samples at 2 loops own the frontier. The only deeper point on it is one 3-loop pass (73.4% at 1.68×); no 4-loop point is ever on it.

The gain also has a shape. Bin questions by how often 1 loop solves them, using held-out repeats. The second loop adds 4–9 points of solve rate to questions 1 loop sometimes gets and 0.7 to questions it never gets: it sharpens, it does not unlock. It also does not re-rank difficulty. Corrected for measurement noise, per-question solve rates correlate 0.99–1.01 across every pair of loop counts (values above 1 are an artifact of the correction and mean the orderings are indistinguishable). So there is nothing to route on: a per-question choice of loop count picked on held-out repeats scores below simply using the best single loop count.

Inside the model

Text written by scored at 1 scored at 2 scored at 3 scored at 4 scored at 6 scored at 8
Dory, 1 loop 0.7376 0.7801 0.7927 0.7971 0.7998 0.8005
Dory, 2 loops 0.7236 0.6776 0.6818 0.6850 0.6875 0.6883
Dory, 4 loops 0.7382 0.6832 0.6767 0.6756 0.6768 0.6778
Qwen3.5-4B 0.9838 0.9514 0.9551 0.9549 0.9553 0.9554

Next-token loss (nats per token) of reasoning traces from 60 GPQA questions, written by the model in the row and scored teacher-forced at each loop count; the minimum of each row is in bold.

Each loop count is a different distribution, not a sharper copy of one. Text written at 1 loop is predicted best at 1 loop, text written at 2 loops at 2, and so on. The step from 1 to 2 loops moves the distribution about 6× as far as the next two loops together (Jeffreys divergence 0.088 nats per token for 1→2 against 0.015 for 2→4). On reasoning traces nobody in the Dory family wrote (Qwen3.5-4B's), the loss is lowest at exactly 2 loops and every further loop gives a little back.

Next-token loss after each loop, all 24 documents0.650.6550.660.6651234681216loopsnats per tokenall 24 documents, loops 1: 0.7all 24 documents, loops 2: 0.6all 24 documents, loops 3: 0.7all 24 documents, loops 4: 0.7all 24 documents, loops 5: 0.7all 24 documents, loops 6: 0.7all 24 documents, loops 7: 0.7all 24 documents, loops 8: 0.7all 24 documents, loops 9: 0.7all 24 documents, loops 10: 0.7all 24 documents, loops 11: 0.7all 24 documents, loops 12: 0.7all 24 documents, loops 13: 0.7all 24 documents, loops 14: 0.7all 24 documents, loops 15: 0.7all 24 documents, loops 16: 0.7■ all text 0.6562
Next-token loss after each loop, Qwen-written text only (no loop count wrote it)0.930.9350.940.9451234681216loopsnats per tokenQwen-written text only (no loop count wrote it), loops 1: 0.9Qwen-written text only (no loop count wrote it), loops 2: 0.9Qwen-written text only (no loop count wrote it), loops 3: 0.9Qwen-written text only (no loop count wrote it), loops 4: 0.9Qwen-written text only (no loop count wrote it), loops 5: 0.9Qwen-written text only (no loop count wrote it), loops 6: 0.9Qwen-written text only (no loop count wrote it), loops 7: 0.9Qwen-written text only (no loop count wrote it), loops 8: 0.9Qwen-written text only (no loop count wrote it), loops 9: 0.9Qwen-written text only (no loop count wrote it), loops 10: 0.9Qwen-written text only (no loop count wrote it), loops 11: 0.9Qwen-written text only (no loop count wrote it), loops 12: 0.9Qwen-written text only (no loop count wrote it), loops 13: 0.9Qwen-written text only (no loop count wrote it), loops 14: 0.9Qwen-written text only (no loop count wrote it), loops 15: 0.9Qwen-written text only (no loop count wrote it), loops 16: 0.9■ Qwen text 0.9337

One 16-loop pass, read out after each loop, shows why. The first loop rewrites the state almost completely (its cosine with the input is −0.02). The second moves it by 2.6% of its length, 1.8% as far as the first. After that the steps keep shrinking, but ever more slowly, settling near 0.3% per pass by loop 10. The loss gains shrink faster, by about 0.27 per loop, toward a limit of 0.656, which is worse than the 0.647 at 2 loops.

Text 1 loop 2 loops 3 loops 4 loops 6 loops 8 loops Qwen3.5-4B
All 433 documents 0.6161 0.6068 0.6065 0.6063 0.6063 0.6064 0.5570
arXiv, 2026 0.7747 0.7630 0.7610 0.7605 0.7603 0.7603 0.7177
code 0.4115 0.4049 0.4043 0.4040 0.4042 0.4042 0.3511
human reasoning 0.5596 0.5511 0.5521 0.5520 0.5522 0.5524 0.5153
math 0.5072 0.4961 0.4960 0.4955 0.4954 0.4955 0.4347
wiki 0.7933 0.7848 0.7845 0.7846 0.7848 0.7848 0.7311

Bits per byte, teacher-forced, on 433 documents (1.5 MB) in five pools, including 2026 arXiv papers newer than either model; the best loop count per row is in bold. Tokenizer-free, so Qwen3.5-4B's column is directly comparable.

In aggregate, ordinary text shows a fixed point rather than an optimum. The second loop takes 0.0093 bits per byte off, which is 95% of the whole move from 1 to 8 loops. Loops 3–8 add up to another 0.0005, and the last two steps are inside their own error. The pools disagree past 2 loops: arXiv keeps improving to 8 loops, while human-written reasoning is best at 2 and slightly worse at every depth beyond. Qwen3.5-4B is the better language model on every pool. Dory needs 0.059 more bits per byte at 1 loop, and looping closes only a sixth of that gap.

What a loop costs

A 4-loop token does not cost 4× a 1-loop token: only the 20-block core repeats, and the 131,072-row output layer runs once. In matrix-multiply and attention FLOPs, an answer costs 1.00× / 1.39× / 1.79× / 2.24× at 1–4 loops, counting each loop count's shorter answers. Measured wall-clock time runs higher: at batch 256, a 4-loop token takes 2.4–3.1× the time of a 1-loop token depending on the GPU. Decoding at that batch is limited by memory traffic, and per-loop KV caching multiplies the cache that has to be read.

GPU (attention kernel) $ per GPU-hour Tokens/s, 1 loop Tokens/s, 4 loops 4 loops ÷ 1 $ per 1M tokens, 1 loop $ per 1M tokens, 4 loops
A100-80GB $2.50 2,441 877 2.78× $0.284 $0.791
H100 $3.95 9,633 3,086 3.12× $0.114 $0.355
H200 $4.54 10,938 4,078 2.68× $0.115 $0.309
B200, FlashInfer (CUDA devel image) $6.25 17,717 7,302 2.43× $0.098 $0.238
B200, Triton attention $6.25 13,158 5,451 2.41× $0.132 $0.318
B200, FlashAttention 2 $6.25 3,849 1,582 2.43× $0.451 $1.098

Same benchmark on each GPU: 198 GPQA prompts × 4,096 output tokens, 256 at a time, vLLM from the Dory PR. Dollars at Modal's list prices; a cold start (77–164 s on these runs) is extra.

On cost per token, the B200 is the best card for this model, but only if the image has a CUDA compiler. On Blackwell, this vLLM picks FlashInfer's TRT-LLM attention kernels, which compile on first use; on a slim image with no nvcc the engine dies. Forcing FlashAttention 2 instead runs at 3,849 tokens/s, which costs more per token than an A100, and Triton attention reaches 13,158. With the kernels compiled, a B200 does 17,717 tokens/s at 1 loop, 1.6× an H200, and is 15–23% cheaper per token. The A100 costs 2.5× the H200 per token: it has no FlashAttention 3.

Where Dory's advantage over other small models comes from

Model GPQA Diamond IFBench IFNovel (held-out) AA-LCR IFBench traces never finished
Dory, 1 loop 69.2 ± 1.0 74.2 ± 0.7 87.3 ± 1.0 62.7 ± 1.9 1.2%
Dory, 2 loops 74.1 ± 0.9 78.6 ± 0.6 89.1 ± 1.0 71.3 ± 1.4 0.5%
Dory, 4 loops 73.1 ± 0.7 78.8 ± 0.6 89.5 ± 1.0 72.0 ± 2.0 0.2%
Qwen3.5-4B 78.8 ± 1.1 60.4 ± 1.3 47.4 ± 1.5 64.0 ± 4.8 13.2%
gpt-oss-20b (high) 64.9 ± 1.3 68.6 ± 1.2 77.4 ± 1.3 – 0.2%
Nemotron-3-Nano-4B 53.5 ± 1.8 59.4 ± 1.5 49.9 ± 1.7 18.0 ± 2.2 1.0%

Same harness, prompts and grading for every model, at a 64K budget, with three exceptions. Qwen3.5-4B's GPQA is the 32K run, whose budget did not bind. gpt-oss-20b's GPQA uses NVIDIA's lenient extractor, because it bolds its answer label and simple-evals' regex misses it (54.3 with that regex); 15% of its GPQA traces also hit the budget at reasoning effort high, so treat that cell as a lower bound. IFBench and IFNovel use NVIDIA's metric, on the text after `` (after `assistantfinal` for gpt-oss-20b, whose output is Harmony). IFNovel is 300 prompts built for this project from 22 constraint types that exist in no public set, graded by this project's verifiers.

The verdict: Dory's edge over small models of its size is instruction following, and it is not produced by the loop. It is whole at 1 loop and holds up on constraint types nobody has published. NVIDIA's own non-looped 4B lacks it, and on ordinary text Dory is the weaker language model. That points at post-training, but nothing here isolates post-training: the only control differs in generation, architecture and reasoning length at once. Looping adds a consistent, modest second-pass gain on top, largest on long documents. Its practical value is "elastic compute": one checkpoint, with 2 loops buying everything looping offers that these sets can resolve.

A second implementation

Everything above runs through NVIDIA's own vLLM PR, so it measures the model and that code together. To separate them, Dory's forward pass was written a second time from scratch in pure PyTorch, from the vLLM PR and the llama.cpp fork brianchmielNV/llama.cpp at 98a74c97 read side by side (ref_dory.py). Scoring the same 70,192 teacher-forced tokens (24 documents written by Dory at 1, 2 and 4 loops and by Qwen3.5-4B), the two agree within 0.0002 nats of mean loss at every loop count (0.6649 / 0.6474 / 0.6531 against 0.6650 / 0.6474 / 0.6531). The signed per-token bias straddles zero, and the argmax matches 99.1–99.2% of the time. The remaining per-token difference, 0.015 nats, is the size of any bf16 reordering of the same mathematics; an fp32 RoPE cache alone moves it by 0.015. The smallest semantic error constructed was 35× larger: dropping the loop's re-injection moves per-token log-probabilities by 0.52 nats on average, and raises mean loss by 0.36 nats. Skipping the core entirely, which the independent implementation allows and vLLM does not, gives a loss of 12.57, worse than a uniform guess over the vocabulary (11.78): at 1 loop, the core is 40 of the 72 layers.

Method

What differs from NVIDIA's setup

Spend

Experiment 1 cost $41.64 of its $50 cap on the yaroslavvb workspace; nothing more was spent there. Experiment 2 ran on Misha Makarov's workspace michael-76064, 63 GPU-hours, almost all on H200s at about $4.8 an hour all-in:

What Cost
Dory's loop curve: GPQA and IFBench repeats at 1–4 loops, last-loop KV, NVIDIA's GPQA prompt $106.43
AA-LCR draws at 1, 2 and 4 loops $72.14
Baselines: Qwen3.5-4B, Nemotron-3-Nano-4B, gpt-oss-20b $21.07
IFNovel for every model $21.59
AA-LCR judging, including NVIDIA's 235B judge on 4 H200s $29.09
Teacher-forced scoring, budget forcing, the second implementation $12.77
GPU comparison: A100, H100, H200, B200 $6.68
Wasted: AA-LCR 'repeats' that were byte-identical copies of earlier draws $31.87
Setup: downloads and builds $0.30
Total, Misha's workspace $301.94 of $500

Per-app lines are in LEDGER.md; ledger.py --profile misha recomputes them from Modal's billing report.

What would settle the rest

  1. The agent-task token savings. Terminal-Bench 2.1 or SWE-bench Verified at 1, 2 and 4 loops would show whether a loop saves whole turns. That needs a new agent harness and sandboxes, well past this budget.
  2. The last 2–4 points of Qwen's IFBench. Serving Qwen3.5-4B through NeMo Gym's Responses API, uncapped, for 8 repeats would settle it (about 4 H200-hours at a 64K cap, more uncapped).
  3. An equal-effort recipe control. Nemotron-3-Nano-4B reasons 6–11× less than Dory on the instruction sets. The nearest public checkpoint from the right data generation, Nemotron-3.5-Lightning-30B-A3B, is non-looped but 30B (3B active) rather than 4B, and its trace lengths are unmeasured here.
  4. More AA-LCR draws. Draw-to-draw spread is about 5.5 points: 3–4 draws per loop count pin each level to about ±3, and about 7 each would pin the loop gain to ±3.