unparallelled commited on
Commit
beec723
·
verified ·
1 Parent(s): d5bf030

Upload docs/ClaudeReport_session_2026-09-15_680m_tied_head_fix_and_phase1_extension.md with huggingface_hub

Browse files
docs/ClaudeReport_session_2026-09-15_680m_tied_head_fix_and_phase1_extension.md CHANGED
@@ -1,82 +1,169 @@
1
- # 2026-09-15 - 680M tied-head bf16 fix, then phase-1 context extension (4k -> 16k)
2
 
3
- Workspace: dist/Context_Parallelism
4
- Files: Scripts/Blutrain/bluscriptCP.cpp, p1_680m.sh, p1_shipper.sh, dl_p23.sh, mix_buckets.py
 
 
5
 
6
- ## Why this session exists
7
 
8
- Two long-context extension runs on the 1.06B model collapsed. Both broke at roughly
9
- 80 percent of a cumulative b5 (64k-131k) epoch, and the collapse tracked cumulative
10
- long-document exposure rather than data composition -- mixing shorter buckets in
11
- delayed it but did not prevent it. The degraded model showed 62x more NLL<0.5
12
- positions, the fingerprint of copying rather than retrieval. Long-position
13
- processing itself stayed intact.
14
-
15
- Working hypothesis: the 1.06B is undertrained at 0.99 tok/param (Chinchilla is 20),
16
- so copying is the cheaper solution than retrieval and the model falls into it. That
17
- predicts a better-trained base has a higher ceiling. varybatch is a 680M at
18
- 10.5 tok/param -- the test.
19
 
20
  ## The bug that had to be fixed first
21
 
22
- varybatch scored NLL 12.13, worse than uniform. Bisected with CP_DUMP_ACTS against
23
- a PyTorch reference implementation. Cause: in GPT::forward, the weight_tying path
24
- cast the TRANSPOSED embedding matrix to bf16. The cast ignores strides, so the tied
25
- head multiplied a garbled weight.
26
-
27
- before: transpose -> to_compute(bf16) [strided cast, silently wrong]
28
- after: to_compute(bf16) -> transpose -> contiguous()
29
-
30
- Never surfaced before because every model trained in this repo uses weight_tying=0,
31
- which takes the separate contiguous lm_head path. bluscript_zero_ckpt.cpp -- the
32
- trainer that actually produced varybatch -- documents the same hazard in a comment
33
- about contiguous() and trans_b.
34
-
35
- Confirmed by bf16 mask bisection: mask=15 gave 12.1295, mask=7 (head in fp32) gave
36
- 3.0496. After the fix the 680M scores 3.0497 (PyTorch reference: 3.0793) and the
37
- 1.06B is unchanged at 3.1719 (was 3.1717), so no regression.
38
-
39
- Result: the 680M beats the 1.06B on identical data, 3.05 vs 3.17.
40
-
41
- ## Phase-1 run (launched, in progress)
42
-
43
- 2x H100 80GB, cp=2. Parent varybatch step 3400.
44
-
45
- window 16,384 via YaRN SCALE=4 x ORIG_MAXPOS=4096 (must equal CP_T exactly)
46
- data Data_Loader/Data/p1mix, 640,009,970 tokens, b3 50 / b2 30 / b1 20
47
- steps 1,200 of 1,220 usable at global_batch 524,288 (grad_accum 32)
48
- WSD warmup 100 / stable 1,098 / tail 2
49
- measured 50,117 MB of 81,559 MB per card, 7.83 s/step, ETA 2h34m
50
-
51
- Both YaRN inputs were verified against the trainer that produced the checkpoint
52
- rather than assumed: rope_theta 500000 (bluscript_zero_ckpt.cpp:121 and config.md)
53
- and context_length 4096. The trainer prints a "provenance UNVERIFIED" warning only
54
- because no sidecar file exists to compare against; the values are correct.
55
 
56
- Ladder (b5 deliberately ends at 36 percent of its epoch -- both prior collapses
57
- were at ~80 percent):
58
 
59
- phase 1 4k -> 16k b3 50, b2 30, b1 20
60
- phase 2 16k -> 32k b4 50, b3 30, b1 20 fits 2x H100, tight
61
- phase 3 32k -> 64k b5 50, b4 25, b3 15, b1 10 needs >= 4 GPUs (117 GB at cp=2)
 
 
62
 
63
- ## Process notes worth keeping
 
 
64
 
65
- - The shipper reads $LOG/runnum, but the training script only writes it after
66
- training COMPLETES. That left the mixcont shipper idle for 50 minutes. Wrote it
67
- manually at launch this time.
68
- - The shipper's `STEP % FREQ` gate assumes checkpoints are named 200/400/...
69
- If the trainer names them 199/399/... it silently ships nothing. The phase-1 copy
70
- ships every checkpoint the glob actually finds instead of predicting the numbering.
71
- - Every hf download used an explicit --include. An unfiltered one earlier in this
72
- project pulled 167 GB and broke the build.
73
- - Every upload is verified by byte size against what HF reports back, never by the
74
- exit code of `hf upload` -- that returned success for a missing file on 2026-09-10
75
- and 17 GB of checkpoints were lost.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
  ## Open
78
 
79
- - CP_EVAL_PPL is broken and deferred by decision. Not required: training, the NIAH
80
- evals in run_longeval.sh, and the trainer's own "validation loss:" line are all
81
- separate code paths.
82
- - Phase 3 cannot run on this 2-GPU box.
 
 
 
1
+ # 2026-09-15 / 2026-09-16 - 680M tied-head bf16 fix, phase-1 context extension (4k -> 16k), and the baseline correction
2
 
3
+ Workspace: Context_Parallelism (GPU box, now torn down) / CP (laptop)
4
+ Files: Scripts/Blutrain/bluscriptCP.cpp, p1_680m.sh, p2_680m.sh, p1_shipper.sh,
5
+ p1_finish.sh, p1_eval2.sh, p1_plots.sh, mk_p1_plots.py, dl_p23.sh, mix_buckets.py,
6
+ run_longeval.sh, HANDOFF_H200_32K.md
7
 
8
+ ## Why this session existed
9
 
10
+ Two long-context extension runs on the 1.06B collapsed, both at roughly 80 percent
11
+ of a cumulative b5 epoch, tracking cumulative long-document exposure rather than
12
+ data composition. Working hypothesis: the 1.06B is undertrained at 0.99 tok/param,
13
+ so copying is a cheaper solution than retrieval. That predicts a better-pretrained
14
+ base has a higher ceiling. varybatch is a 680M at 10.5 tok/param - the test.
 
 
 
 
 
 
15
 
16
  ## The bug that had to be fixed first
17
 
18
+ varybatch scored NLL 12.1295, worse than uniform. Bisected with CP_DUMP_ACTS
19
+ against a PyTorch reference. GPT::forward's weight_tying path cast the TRANSPOSED
20
+ embedding matrix to bf16; the cast ignores strides, so the tied head multiplied a
21
+ garbled weight.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ before: transpose -> to_compute(bf16) [strided cast, silently wrong]
24
+ after: to_compute(bf16) -> transpose -> contiguous()
25
 
26
+ Confirmed by mask bisection: mask=15 gave 12.1295, mask=7 (head in fp32) gave
27
+ 3.0496. After the fix the 680M scores 3.0497 (PyTorch reference 3.0793) and the
28
+ 1.06B is unchanged at 3.1719 (was 3.1717). Never surfaced before because every
29
+ model trained in this repo uses weight_tying=0 and takes the separate contiguous
30
+ lm_head path. bluscript_zero_ckpt.cpp documents the same hazard in a comment.
31
 
32
+ ## Phase 1: 4k -> 16k
33
+
34
+ 2x H100, cp=2, parent varybatch step 3400.
35
 
36
+ window 16,384 via YaRN SCALE=4 x ORIG_MAXPOS=4096
37
+ data p1mix, 640,009,970 tokens, b3 50 / b2 30 / b1 20
38
+ steps 1,200 of 1,220 usable at global_batch 524,288 (grad_accum 32)
39
+ measured 50,117 MB of 81,559 per card, 7.83 s/step, clean finish
40
+ loss 2.5969 @step 99 -> 2.6006 @step 1199 (i.e. flat)
41
+ val 2.8726 -> 2.8560 over the whole run
42
+
43
+ rope_theta 500000 and context_length 4096 were verified against
44
+ bluscript_zero_ckpt.cpp:121 and .mdfiles/config.md - the trainer's
45
+ "provenance UNVERIFIED" warning only means no sidecar exists to compare against.
46
+
47
+ ## Result: a null
48
+
49
+ niah_single, N=100, greedy, haystack b2_8192_16384/val_shard_00000.bin.
50
+
51
+ prompt len base680 (untrained, zero-shot YaRN) p1final (1200 steps)
52
+ 8,192 84 77
53
+ 16,360 40 42
54
+
55
+ Both deltas sit inside the +-9-13pp Wilson band at N=100. 1,200 steps and 2.6 GPU
56
+ hours changed nothing measurable. The flat loss predicted this.
57
+
58
+ Depth breakdown at 16,360 (both models): 0 percent when the needle is at the start,
59
+ 100 percent when it is at the end, monotonic in between. That is recency, not
60
+ retrieval, and training did not move it.
61
+
62
+ ## Four explanations I gave, three of them wrong
63
+
64
+ 1. LEARNING RATE - WRONG. I claimed phase 1 ran at 1.8e-4 against the 1.06B's
65
+ 3e-4. CP_MAX_LR and CP_MIN_LR appear ZERO times in bluscriptCP.cpp; max_lr is
66
+ hardcoded 6e-4 at line 151. Every run in this project, both models, every
67
+ context stage, trained at 6e-4 x REWARMUP_PEAK 0.3 = 1.8e-4. The scripts that
68
+ set CP_MAX_LR=1e-3 were setting a variable the trainer never reads, and
69
+ ext64k_b5.sh:23 already said so. THIS IS THE SAME ERROR I MADE AND LOGGED ON
70
+ 2026-09-09 ("my 3.0e-4 came from assuming max_lr=1e-3").
71
+
72
+ 2. TOO FEW LONG TOKENS - WRONG. At the same 524,288 global batch, phase 1 saw
73
+ 314,572,800 b3 tokens; mix64k saw 188,743,680. Phase 1 had 1.67x MORE.
74
+
75
+ 3. TRUNCATION - BACKWARDS. b3 documents are 16,384-32,768 tokens, at or above the
76
+ 16,384 window, so every phase-1 window is contiguous single-document text. That
77
+ is the good case and the reason b3 was chosen. The 65,536-window runs are the
78
+ ones that packed several b3 docs plus boundaries per window.
79
+
80
+ 4. BASELINE - WRONG, AND MY CORRECTION WAS ALSO PARTLY WRONG. I reported 42 as
81
+ "far below the 1.06B's 65-70", but ext64k had been through three extension
82
+ stages. The stage analogue is the 1.06B's own 16k ladder: l1/l2/l3 tied at 35.0
83
+ at 16,360, best l3long2k (run17 step 2000) 43.0. So 42 is at the 16k-stage best.
84
+ But then the comparison table I built to show that was itself invalid, because
85
+ eval directories used DIFFERENT haystacks.
86
+
87
+ ## Haystack tiering (the reason cross-run eval comparison is unsafe here)
88
+
89
+ val_shard_00000.bin mix64k_1200, mixcont/cliff1400 <- same as phase 1
90
+ b2val_haystack.bin decide, ext32k, ext64k <- probably same, UNVERIFIED
91
+ b3val_haystack.bin lenb
92
+ flux_val_000000.bin newck, longeval_yarnfix (N=50)
93
+
94
+ Proof this matters: checkpoint blumodelcp_run2_step_400 scores 78 under lenb and
95
+ 62 under decide - same weights, 16pp apart, different haystack. The haystack files
96
+ are not on HF, so b2val_haystack.bin cannot be byte-checked against
97
+ val_shard_00000.bin despite the suggestive name.
98
+
99
+ Only mix64k (83 @8192 / 70 @16360) and mixcont (80 / 54) are certainly comparable
100
+ to phase 1.
101
+
102
+ ## What actually stands
103
+
104
+ - The 680M base reaches 84 @8192 zero-shot, equal to the fully-laddered mix64k's
105
+ 83 on the SAME haystack. That is the one real signal for the higher-ceiling
106
+ hypothesis.
107
+ - At 16,360 the 680M sits at 40-42, at the level of the 1.06B's 16k-stage ladder
108
+ and well below its fully-laddered 65-70.
109
+ - 1,200 steps of training added nothing at either length.
110
+ - Therefore: the hypothesis is neither confirmed nor refuted. Phase 1 did not fail
111
+ to reach a ceiling; it failed to move at all.
112
+
113
+ ## YaRN rule correction (HANDOFF_H200_32K.md)
114
+
115
+ The doc said ORIG_MAXPOS must be "the length the weights were ACTUALLY trained at".
116
+ Right for a single extension, wrong for a ladder. build_rope_cache takes rope_theta
117
+ and is rebuilt from base theta every run, so SCALE never composes with the previous
118
+ stage. Re-basing freezes interpolation at theta/2 while the window doubles:
119
+
120
+ stage as-run (re-based) interp last tok -> virtual ramp
121
+ 16k 4 x 4096 theta/4 4,096 [14,32]
122
+ 32k 2 x 16384 theta/2 16,384 [21,39]
123
+ 64k 2 x 32768 theta/2 32,768 [24,42]
124
+
125
+ stage corrected interp last tok -> virtual ramp
126
+ 16k 4 x 4096 theta/4 4,096 [14,32]
127
+ 32k 8 x 4096 theta/8 4,096 [14,32]
128
+ 64k 16 x 4096 theta/16 4,096 [14,32]
129
+
130
+ find_dim(num_rot, L, head_dim, base) does not take scale, so the ramp moves only
131
+ when ORIG_MAXPOS moves. The 1.06B ladder followed the old rule from its 32k stage
132
+ on. This is NOT thought to be the collapse cause - a wrong cache is a static defect
133
+ while the collapse was progressive - but it plausibly lowered the ceiling.
134
+
135
+ ## Operational errors this session
136
+
137
+ - The eval aborted in 49 s: run_longeval.sh defaults CP_DATA_ROOT to
138
+ Data_Loader/Data, which on that box held only subdirectories, and the trainer
139
+ builds a data loader even for pure generation ("no .bin shards found for split
140
+ train"). Fixed with GEN_DATA_ROOT.
141
+ - up() verified logs/upload.log against a file it was itself appending to, so it
142
+ always reported a mismatch. Now uploads a snapshot copy.
143
+ - A sed heredoc produced an EMPTY p2_680m.sh that still passed bash -n. test -s is
144
+ now checked alongside it.
145
+ - run_longeval.sh prefixes OUT with $PWD, so an absolute OUT becomes
146
+ ".../Context_Parallelism//tmp/...". Caught by an N=2 smoke test before it cost a
147
+ second full cycle.
148
+ - I called the NLL position analysis a "copying fingerprint that explained why"
149
+ retrieval dropped. It does not explain it: NLL shape and retrieval ANTI-correlate
150
+ in that very data (the degraded model has the steeper context gain). The evidence
151
+ for degradation is NIAH alone; the NLL work ruled out broken long-range
152
+ processing and showed where the loss gain sat, nothing more.
153
+
154
+ ## State
155
+
156
+ Everything byte-verified on HF unparallelled/BluScriptCP: full resumable phase-1
157
+ checkpoint both ranks (11.2 GB), both plots, all eval CSVs and generations, every
158
+ script, corrected handoff doc. p2mix and p3mix built and verified to read shards
159
+ disjoint from phase 1 and from each other. p2_680m.sh written and refuses to run
160
+ without a completed phase 1. Phase 3 needs >= 4 GPUs (~115 GB at cp=2).
161
 
162
  ## Open
163
 
164
+ - Why training moved nothing. Remaining candidate: next-token loss on natural text
165
+ may not reward reaching backwards, so there is no gradient toward retrieval.
166
+ Untested.
167
+ - Whether b2val_haystack.bin == val_shard_00000.bin, which would widen the
168
+ comparable set to ext64k/ext32k/decide.
169
+ - CP_EVAL_PPL broken for weight_tying=1, deferred by decision.