feat(byr-fogtix): optimize merge/ff case

This commit is contained in:
Alain Zscheile 2022-10-15 22:56:33 +02:00
parent c2a0aba3a5
commit 4dedcbe057

View file

@ -102,6 +102,7 @@ fn data_ser(din: Vec<u64>, dout: &mut Vec<u8>) {
dout.extend(din.into_iter().flat_map(|i| i.to_be_bytes()));
}
#[allow(non_snake_case)]
fn main() {
let args = <Args as clap::Parser>::parse();
@ -252,11 +253,7 @@ fn main() {
let mut bit = b.changelist.0.iter().peekable();
mprgs.add(pbarA.clone());
mprgs.add(pbarB.clone());
loop {
let (ap, bp) = match (ait.peek(), bit.peek()) {
(Some(ap), Some(bp)) => (ap, bp),
(_, _) => break,
};
while let (Some(ap), Some(bp)) = (ait.peek(), bit.peek()) {
if ap == bp {
let bytecode = changes.get(ap)?;
BytecodeWrapper(&bytecode[..]).run(&mut data).map_err(|e| {
@ -287,17 +284,7 @@ fn main() {
.enumerate()
.map(|(n, &i)| (X::B(n), i))
.collect::<Vec<_>>();
// this just relies on the fact that any remaining duplicates between A and B are idempotent
// TODO: compute common elements between restA & restB, and handle them specifically (dedup)
let appAB = restA
.iter()
.chain(restB.iter())
.copied()
.collect::<Vec<_>>();
let appBA = restB
.into_iter()
.chain(restA.into_iter())
.collect::<Vec<_>>();
let appMX = {
let mut mx = Vec::new();
// time for cursed merge-sort
@ -327,41 +314,57 @@ fn main() {
pbarB.finish_and_clear();
mx
};
// run them...
let (data1, data2) = (data.clone(), data.clone());
let (changes1, changes2) = (changes.try_clone()?, changes.try_clone()?);
fn run_chain(
mut data: Vec<u64>,
chain: Vec<(X, [u8; 32])>,
changes: byr_core::MassChangesGet,
pbar: ProgressBar,
) -> IoResult<Vec<u64>> {
for (idx, i) in pbar.wrap_iter(chain.into_iter()) {
let mut p = fogtix_vm::Process {
stack: core::mem::take(&mut data),
callstack: Vec::new(),
m: &changes.get(&i)?,
instrp: 0,
};
p.run(None).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("{:?}:{:?}", idx, e),
)
})?;
data = p.stack;
let tA_B = if (!restA.is_empty()) && (!restB.is_empty()) {
// this just relies on the fact that any remaining duplicates between A and B are idempotent
// TODO: compute common elements between restA & restB, and handle them specifically (dedup)
let appAB = restA
.iter()
.chain(restB.iter())
.copied()
.collect::<Vec<_>>();
let appBA = restB
.into_iter()
.chain(restA.into_iter())
.collect::<Vec<_>>();
// run them...
let (data1, data2) = (data.clone(), data.clone());
let (changes1, changes2) = (changes.try_clone()?, changes.try_clone()?);
fn run_chain(
mut data: Vec<u64>,
chain: Vec<(X, [u8; 32])>,
changes: byr_core::MassChangesGet,
pbar: ProgressBar,
) -> IoResult<Vec<u64>> {
for (idx, i) in pbar.wrap_iter(chain.into_iter()) {
let mut p = fogtix_vm::Process {
stack: core::mem::take(&mut data),
callstack: Vec::new(),
m: &changes.get(&i)?,
instrp: 0,
};
p.run(None).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("{:?}:{:?}", idx, e),
)
})?;
data = p.stack;
}
Ok(data)
}
Ok(data)
}
let (pA, pB) = (
ProgressBar::new(appAB.len().try_into().unwrap()).with_prefix("s|aug"),
ProgressBar::new(appBA.len().try_into().unwrap()).with_prefix("aug|s"),
);
mprgs.add(pA.clone());
mprgs.add(pB.clone());
let tA = std::thread::spawn(move || run_chain(data1, appAB, changes1, pA));
let tB = std::thread::spawn(move || run_chain(data2, appBA, changes2, pB));
let (pA, pB) = (
ProgressBar::new(appAB.len().try_into().unwrap()).with_prefix("s|aug"),
ProgressBar::new(appBA.len().try_into().unwrap()).with_prefix("aug|s"),
);
mprgs.add(pA.clone());
mprgs.add(pB.clone());
let tA = std::thread::spawn(move || run_chain(data1, appAB, changes1, pA));
let tB = std::thread::spawn(move || run_chain(data2, appBA, changes2, pB));
Some((tA, tB))
} else {
None
};
let pMX =
ProgressBar::new(appMX.len().try_into().unwrap()).with_prefix("s<m>aug");
@ -390,32 +393,37 @@ fn main() {
data = p.stack;
}
let rA = tA.join().expect("s|aug thread failed")?;
let rB = tB.join().expect("aug|s thread failed")?;
let mut succ = true;
if let Some((tA, tB)) = tA_B {
let rA = tA.join().expect("s|aug thread failed")?;
let rB = tB.join().expect("aug|s thread failed")?;
let mut succ = true;
if rA != rB {
let _ = mprgs
.println("ERROR: the diverging parts don't commute with each other!");
succ = false;
}
if rA != data {
let _ = mprgs.println(
"ERROR: the merged version and s|aug have mismatching results!",
);
succ = false;
}
if rB != data {
let _ = mprgs.println(
"ERROR: the merged version and aug|s have mismatching results!",
);
succ = false;
}
if !succ {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"merging failed".to_string(),
));
if rA != rB {
let _ = mprgs.println(
"ERROR: the diverging parts don't commute with each other!",
);
succ = false;
}
if rA != data {
let _ = mprgs.println(
"ERROR: the merged version and s|aug have mismatching results!",
);
succ = false;
}
if rB != data {
let _ = mprgs.println(
"ERROR: the merged version and aug|s have mismatching results!",
);
succ = false;
}
if !succ {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"merging failed".to_string(),
));
}
} else {
let _ = mprgs.println("NOTE: applied fast-forward");
}
data_ser(data, &mut snap.data);