1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//! The speculative transaction against the walk, on the q4 toy stand.
//!
//! Every round runs a 5-token verify whose proposals are all junk, rolls
//! back to the one known token, then compares against a pristine walk of
//! the same sequence. Two things must hold BIT FOR BIT, round after round:
//! the verify's answer for the committed token equals the walk's logits,
//! and a final probe token confirms no residual state damage.
//!
//! CMF_GPU=wgpu CMF_TOY_DIR=... cargo test -p cortiq-engine \
//! --features gpu --release --test gpu_spec_txn -- --nocapture
#![cfg(feature = "gpu")]
use std::sync::Arc;
fn toy_dir() -> Option<String> {
let d = std::env::var("CMF_TOY_DIR").unwrap_or_else(|_| {
"/private/tmp/claude-501/-Users-oleg-Documents-cortiq-bot-cmfpublic/674db62a-643b-4641-b330-5feed6d40b67/scratchpad"
.to_string()
});
std::path::Path::new(&d).join("q4.cmf").exists().then_some(d)
}
#[test]
fn rejected_verify_leaves_the_walk_intact() {
for (k, v) in [
("CMF_SDOT", "0"),
("CMF_GPU_VRAM_MB", "2000"),
("CMF_DSV4_GPU_LAYER", "1"),
("CMF_DSV4_GPU_ATTN", "1"),
("CMF_DSV4_GPU_MOE2", "1"),
("CMF_DSV4_CHAIN", "1"),
] {
// Test-start, single-threaded: the latch-before-read contract holds.
unsafe { std::env::set_var(k, v) };
}
match cortiq_engine::gpu_wgpu::selected_and_up() {
None => {
eprintln!("wgpu не запрошен (CMF_GPU=wgpu) — пропуск");
return;
}
Some(false) => panic!("wgpu запрошен, но контекст не поднялся"),
Some(true) => {}
}
let Some(dir) = toy_dir() else {
eprintln!("стендов нет (CMF_TOY_DIR) — пропуск");
return;
};
let path = std::path::Path::new(&dir).join("q4.cmf");
let model = Arc::new(cortiq_core::CmfModel::open_sharded(path.to_str().unwrap()).unwrap());
let mk = || {
cortiq_engine::pipeline::Pipeline::from_model(
&model,
cortiq_engine::sampler::SamplerConfig::default(),
)
.unwrap()
};
let mut walk = mk();
let mut spec = mk();
let vocab = 128usize;
let ids: Vec<u32> = (0..96u32)
.map(|i| ((i * 37 + 11) % (vocab as u32 - 2)) + 1)
.collect();
let warm = 24usize;
// Six rounds: enough to cross a compressor boundary twice. The toy's
// random weights amplify the contract's one-ulp round-off through
// near-tied expert selections, so long runs drift by construction —
// the real-model drift rate is measured on the stand instead.
let rounds = 6usize;
let step = |p: &mut cortiq_engine::pipeline::Pipeline, id: u32| -> Vec<f32> {
let b = p.dsv4.as_mut().unwrap();
let (g, layers, cfg) = (&b.0, &b.1, b.2);
let st = &mut b.3;
let mut lg = Vec::new();
cortiq_engine::dsv4::forward_token(
g,
layers,
&cfg,
st,
id,
&g.inv_freq_window.clone(),
None,
&mut lg,
);
lg
};
for t in 0..warm {
let a = step(&mut walk, ids[t]);
let b = step(&mut spec, ids[t]);
assert_eq!(a, b, "прогрев разошёлся на токене {t}");
}
let mut flips = 0usize;
for r in 0..rounds {
let real = ids[warm + r];
// Spec side: a fully-rejected verify, then the rollback to 1.
let verify_row0 = {
let b = spec.dsv4.as_mut().unwrap();
let (g, layers, cfg) = (&b.0, &b.1, b.2);
let st = &mut b.3;
let pos0 = st.pos;
let fed: Vec<u32> = (0..5u32)
.map(|i| if i == 0 { real } else { (real + 7 + i * 13) % vocab as u32 })
.collect();
let mut argmax = Vec::new();
let mut lg_all = Vec::new();
let mut walked = Vec::new();
let txn = cortiq_engine::dsv4::dsv4_verify_chunk(
g,
layers,
&cfg,
st,
&fed,
pos0,
&g.inv_freq_window.clone(),
None,
&[],
&mut argmax,
&mut lg_all,
&mut walked,
)
.unwrap_or_else(|| panic!("verify отказал на раунде {r} (pos {pos0})"));
assert!(
cortiq_engine::dsv4::dsv4_spec_finish(
g,
layers,
&cfg,
st,
txn,
1,
&fed,
&g.inv_freq_window.clone(),
None,
),
"rollback отказал на раунде {r}"
);
assert_eq!(st.pos, pos0 + 1, "позиция после отката");
lg_all[..cfg.vocab].to_vec()
};
// Walk side: the same token, plainly. The verify's answer must match
// the walk to ARGMAX and to round-off: the batch reuses the walk's
// kernels, but one irreducible ulp of reassociation survives (traced
// to the attention half; the MoE's discrete expert selection then
// amplifies it on near-ties). The contract for the speculative mode
// is therefore greedy-equivalence up to round-off, not bit equality.
let a = step(&mut walk, real);
let mut mx = 0.0f32;
for (x, y) in a.iter().zip(&verify_row0) {
mx = mx.max((x - y).abs());
}
let am_a = a.iter().enumerate().max_by(|x, y| x.1.total_cmp(y.1)).unwrap().0;
let am_v = verify_row0.iter().enumerate().max_by(|x, y| x.1.total_cmp(y.1)).unwrap().0;
if am_a != am_v {
// Random toy weights sit on ties everywhere; a flip is the
// round-off contract showing, not a transaction fault. Count it.
flips += 1;
}
assert!(mx < 2e-2, "дрейф логитов вырос до {mx:e} на раунде {r}");
}
let probe = 3u32;
let a = step(&mut walk, probe);
let b = step(&mut spec, probe);
let mut mx = 0.0f32;
for (x, y) in a.iter().zip(&b) {
mx = mx.max((x - y).abs());
}
assert!(mx < 2e-2, "финальный зонд: дрейф {mx:e}");
println!(
"транзакция держит walk на {rounds} откатах: дрейф ≤ {mx:e}, argmax-флипов {flips}"
);
}