Skip to content

Commit 5466709

Browse files
committed
fix: move divergence calculation to separate fn
1 parent 102fcdf commit 5466709

File tree

2 files changed

+75
-46
lines changed

2 files changed

+75
-46
lines changed

benchmarks/execute/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ enum BuildProfile {
2424
// const DEFAULT_APP_CONFIG_PATH: &str = "./openvm.toml";
2525

2626
static AVAILABLE_PROGRAMS: &[&str] = &[
27-
// "fibonacci_recursive",
28-
// "fibonacci_iterative",
27+
"fibonacci_recursive",
28+
"fibonacci_iterative",
2929
"quicksort",
30-
// "bubblesort",
30+
"bubblesort",
3131
// "pairing",
3232
// "keccak256",
3333
// "keccak256_iter",

crates/vm/src/arch/segment.rs

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,15 @@ pub type E1VmSegmentExecutor<F, VC> = VmSegmentExecutor<F, VC, E1ExecutionContro
269269
pub struct MeteredCtx {
270270
continuations_enabled: bool,
271271
memory_dimensions: MemoryDimensions,
272-
addr_space_alignment_bytes: Vec<usize>,
272+
// addr_space_alignment_bytes: Vec<usize>,
273273

274274
// Trace heights for each chip
275275
pub trace_heights: Vec<usize>,
276276
// Accesses of size [1, 2, 4, 8, 16, 32]
277277
// TODO(ayush): no magic number
278278
pub memory_ops: [usize; 6],
279-
// (addr_space, addr, size)
280-
pub memory_addresses: BTreeSet<(u8, u32, u8)>,
279+
// Indices of leaf nodes in the memory merkle tree
280+
pub leaf_indices: BTreeSet<u64>,
281281
}
282282

283283
impl MeteredCtx {
@@ -291,7 +291,7 @@ impl MeteredCtx {
291291
memory_dimensions,
292292
trace_heights: vec![0; num_traces],
293293
memory_ops: [0; 6],
294-
memory_addresses: BTreeSet::new(),
294+
leaf_indices: BTreeSet::new(),
295295
}
296296
}
297297
}
@@ -338,48 +338,77 @@ impl E1E2ExecutionCtx for MeteredCtx {
338338
self.memory_ops[log2_strict_usize(size)] += 1;
339339
// TODO(ayush): access adapter heights based on this
340340

341-
// TODO(ayush): see if this can be approximated by total number of reads/writes for AS != register
342-
self.memory_addresses
343-
.insert((address_space as u8, ptr, size as u8));
341+
// Calculate unique chunks and inner nodes in Merkle tree
342+
let mt_height = self.memory_dimensions.overall_height();
344343

345-
let log2_chunk = log2_strict_usize(CHUNK);
346-
self.trace_heights[offset + log2_chunk] = leaf_indices.len() * 2;
344+
// TODO(ayush): see if this can be approximated by total number of reads/writes for AS != register
345+
let num_chunks = size.div_ceil(CHUNK);
346+
for i in 0..num_chunks {
347+
let addr = ptr.wrapping_add((i * CHUNK) as u32);
348+
let block_id = addr / CHUNK as u32;
349+
let leaf_index = self
350+
.memory_dimensions
351+
.label_to_index((address_space, block_id));
352+
353+
// TODO(ayush): see if insertion and finding pred/succ can be done in single binary search pass
354+
if self.leaf_indices.insert(leaf_index) {
355+
// | Boundary | Merkle | Access Adapters |
356+
// TODO(ayush): no magic numbers
357+
let mut offset = 2;
358+
359+
// Boundary chip
360+
self.trace_heights[offset] += 1;
361+
362+
if self.continuations_enabled {
363+
// Merkle chip
364+
offset += 1;
365+
366+
let height_change =
367+
calculate_merkle_height_changes(leaf_index, &self.leaf_indices, mt_height);
368+
self.trace_heights[offset] += height_change * 2;
369+
}
347370

348-
// Calculate unique chunks and inner nodes in Merkle tree
349-
let height = self.memory_dimensions.overall_height();
350-
351-
// Map memory addresses to leaf indices in the Merkle tree
352-
let leaf_indices: BTreeSet<u64> = self
353-
.memory_addresses
354-
.iter()
355-
.map(|&(space, addr, _size)| {
356-
let block_id = addr / CHUNK as u32;
357-
(1 << height)
358-
+ (((space as u32 - self.memory_dimensions.as_offset) as u64)
359-
<< self.memory_dimensions.address_height)
360-
+ block_id as u64
361-
})
362-
.collect();
363-
364-
// Sum up the heights of the XORs between consecutive leaf indices
365-
let path_divergences = leaf_indices
366-
.iter()
367-
.zip(leaf_indices.iter().skip(1))
368-
.map(|(&lhs, &rhs)| (lhs ^ rhs).checked_ilog2().map_or(0, |bits| bits as usize))
369-
.sum::<usize>();
370-
371-
let modified_nodes_count = height + path_divergences;
372-
373-
// | Boundary | Merkle | Access Adapters |
374-
let mut offset = 2;
375-
self.trace_heights[offset] = leaf_indices.len();
376-
377-
if self.continuations_enabled {
378-
offset += 1;
379-
self.trace_heights[offset] = modified_nodes_count * 2;
371+
// 8-byte access adapter
372+
let log2_chunk = log2_strict_usize(CHUNK);
373+
self.trace_heights[offset + log2_chunk] += 2;
374+
}
380375
}
376+
}
377+
}
381378

382-
let log2_chunk = log2_strict_usize(CHUNK);
383-
self.trace_heights[offset + log2_chunk] = leaf_indices.len() * 2;
379+
/// Updates Merkle tree heights based on a new leaf index
380+
fn calculate_merkle_height_changes(
381+
leaf_index: u64,
382+
leaf_indices: &BTreeSet<u64>,
383+
height: usize,
384+
) -> usize {
385+
if leaf_indices.len() == 1 {
386+
return height;
384387
}
388+
389+
// Find predecessor and successor nodes
390+
let pred = leaf_indices.range(..leaf_index).next_back().copied();
391+
let succ = leaf_indices.range(leaf_index + 1..).next().copied();
392+
393+
let mut diff = 0;
394+
395+
// Add new divergences between pred and leaf_index
396+
if let Some(p) = pred {
397+
let new_divergence = (p ^ leaf_index).ilog2() as usize;
398+
diff += new_divergence;
399+
}
400+
401+
// Add new divergences between leaf_index and succ
402+
if let Some(s) = succ {
403+
let new_divergence = (leaf_index ^ s).ilog2() as usize;
404+
diff += new_divergence;
405+
}
406+
407+
// Remove old divergence between pred and succ if both existed
408+
if let (Some(p), Some(s)) = (pred, succ) {
409+
let old_divergence = (p ^ s).ilog2() as usize;
410+
diff -= old_divergence;
411+
}
412+
413+
diff
385414
}

0 commit comments

Comments
 (0)