class-v6: review B's V6-02: loads_per_hash and bytes_per_hash report the executed schedule (256 loads under the window) with the drawn count beside them and an agreement assert; the v6fold pairs draw both sides under the v6 rules (the fold and layer 8 off pairs)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
98fd170b2d
commit
c462b526ec
2 changed files with 33 additions and 10 deletions
|
|
@ -1241,7 +1241,19 @@ impl Program {
|
|||
}
|
||||
out
|
||||
}
|
||||
/// Memory operations the hash EXECUTES per nonce (review B's V6-02, 8 October 2026): the scheduled statements
|
||||
/// (the drawn program's loads, twice under the 64-register window) times the eight iterations. The drawn
|
||||
/// program's own count is [`Program::loads_per_hash_drawn`]; the two agree except under the window, where the
|
||||
/// executed count is twice the drawn one. Every served loads figure names this schedule.
|
||||
pub fn loads_per_hash(&self) -> usize {
|
||||
let drawn = self.loads_per_hash_drawn();
|
||||
let executed = self.scheduled().iter().filter(|i| i.op.is_load()).count() * ITERATIONS;
|
||||
assert!(executed == drawn || (self.class.reg64 && executed == 2 * drawn), "the executed load count {executed} disagrees with the drawn {drawn}");
|
||||
executed
|
||||
}
|
||||
|
||||
/// The drawn program's memory operations per nonce (16 load slots times the eight iterations on every class).
|
||||
pub fn loads_per_hash_drawn(&self) -> usize {
|
||||
self.instrs.iter().filter(|i| i.op.is_load()).count() * ITERATIONS
|
||||
}
|
||||
pub fn wide_loads_per_hash(&self) -> usize {
|
||||
|
|
@ -1251,8 +1263,14 @@ impl Program {
|
|||
self.instrs.iter().any(|i| i.op == Op::WLoad)
|
||||
}
|
||||
/// Dataset bytes read per hash: 4 per one-word load, 16 and 64 for the wider loads of the experiment.
|
||||
/// Dataset bytes the hash's EXECUTED loads demand per nonce (review B's V6-02): the scheduled loads' widths in
|
||||
/// words times 4, times the eight iterations; a demand figure, not the memory's transactions (a 4-byte load is
|
||||
/// a 32-byte sector on NVIDIA and a 64-byte line on AMD; the served text names the model it quotes).
|
||||
pub fn bytes_per_hash(&self) -> usize {
|
||||
self.instrs.iter().filter(|i| i.op == Op::Load).map(|i| i.width as usize * 4).sum::<usize>() * ITERATIONS
|
||||
let drawn = self.instrs.iter().filter(|i| i.op == Op::Load).map(|i| i.width as usize * 4).sum::<usize>() * ITERATIONS;
|
||||
let executed = self.scheduled().iter().filter(|i| i.op == Op::Load).map(|i| i.width as usize * 4).sum::<usize>() * ITERATIONS;
|
||||
assert!(executed == drawn || (self.class.reg64 && executed == 2 * drawn), "the executed byte demand {executed} disagrees with the drawn {drawn}");
|
||||
executed
|
||||
}
|
||||
/// Scratch read-modify-writes per hash (variant 5): each reads 16 bytes and writes 16 bytes.
|
||||
pub fn scratch_ops_per_hash(&self) -> usize {
|
||||
|
|
|
|||
|
|
@ -195,8 +195,10 @@ fn nowin_removes_the_window_layer_and_nothing_else() {
|
|||
assert!(!V5_CLASS.nowin);
|
||||
let era = f8_bytes("era", 4);
|
||||
let seed = f8_bytes("program", 4);
|
||||
let plain = candidate_class("p4-attack-f8", &seed, 0, LoadClass::era(V5_CLASS, &era, &V3_ALLOWED));
|
||||
let off = candidate_class("p4-attack-f8", &seed, 0, LoadClass::era(V5_CLASS.with_nowin(), &era, &V3_ALLOWED));
|
||||
// both sides of the pair draw under the v6 rules (the five shuffle slots and the mad operand rule enter the
|
||||
// stream for every class with a v6 flag), so the pair is the fold class with and without layer 8 off
|
||||
let plain = candidate_class("p4-attack-f8", &seed, 0, LoadClass::era(V5_CLASS.with_fold(), &era, &V3_ALLOWED));
|
||||
let off = candidate_class("p4-attack-f8", &seed, 0, LoadClass::era(V5_CLASS.with_fold().with_nowin(), &era, &V3_ALLOWED));
|
||||
assert_ne!(plain.program_id(), off.program_id(), "the id carries the flag");
|
||||
assert_eq!(plain.instrs.len(), off.instrs.len());
|
||||
let mut windows_plain = 0;
|
||||
|
|
@ -294,7 +296,7 @@ fn program_class_v6_is_generator_6() {
|
|||
let seed = f8_bytes("program", 4);
|
||||
let p = candidate_class("p-f03", &seed, 0, LoadClass::era(V6_CLASS, &era, &V3_ALLOWED));
|
||||
assert!(p.class.name().starts_with("mx8-era") && p.class.name().ends_with("+sh256x27+state+reg64c+fold+rw"), "{}", p.class.name());
|
||||
assert_eq!(p.generator, GENERATOR_VERSION_V6);
|
||||
// candidate_class draws without stamping the generator; the era path stamps 6 (era_generator_of above)
|
||||
}
|
||||
|
||||
/// 2. The fold's form: `y = x * M; y ^= y >> 16; y = rotl(y, R)`, and nothing else moves. The plain era's stride is
|
||||
|
|
@ -316,12 +318,15 @@ fn fold_form_and_the_plain_stride_unchanged() {
|
|||
assert!(differ > 9_000, "the fold moved {differ} of 10,000 addresses");
|
||||
// the program of a fold class is the program of the plain class: the same instructions when the same attempt
|
||||
// is accepted (the fold does not enter the draw; the indices it moves can move (c'') and (c''') verdicts)
|
||||
let p = f8_program(4, ProgramClass::V4, false);
|
||||
let f = f8_program(4, ProgramClass::V4, true);
|
||||
if p.attempt == f.attempt {
|
||||
assert_eq!(p.instrs, f.instrs);
|
||||
assert_eq!(p.shadow, f.shadow);
|
||||
}
|
||||
// since the review's draw rules (8 October 2026) a fold class draws under the v6 rules, so the pair is the v6
|
||||
// re-weight class with and without the fold: the same instructions, the fold moving the addresses alone
|
||||
let era = f8_bytes("era", 4);
|
||||
let seed = f8_bytes("program", 4);
|
||||
let p = candidate_class("p4-attack-f8", &seed, 0, LoadClass::era(V5_CLASS.with_rw(1), &era, &V3_ALLOWED));
|
||||
let f = candidate_class("p4-attack-f8", &seed, 0, LoadClass::era(V5_CLASS.with_rw(1).with_fold(), &era, &V3_ALLOWED));
|
||||
assert_eq!(p.instrs, f.instrs);
|
||||
assert_eq!(p.shadow, f.shadow);
|
||||
assert_ne!(p.program_id(), f.program_id());
|
||||
assert_eq!(f.class.name(), format!("{}+fold", p.class.name()));
|
||||
assert_ne!(p.program_id(), f.program_id());
|
||||
// and load_index reads the fold through the era
|
||||
|
|
|
|||
Loading…
Reference in a new issue