Skip to content

Commit b37b649

Browse files
committed
fix
1 parent b5fbdef commit b37b649

4 files changed

Lines changed: 37 additions & 47 deletions

File tree

crypto/math-cuda/src/merkle.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -455,15 +455,8 @@ fn build_comp_poly_tree_nodes_dev(
455455
Ok((nodes_dev, num_leaves, stream))
456456
}
457457

458-
pub fn build_comp_poly_tree_from_evals_ext3(parts_interleaved: &[&[u64]]) -> Result<Vec<u8>> {
459-
let (nodes_dev, _num_leaves, stream) = build_comp_poly_tree_nodes_dev(parts_interleaved)?;
460-
let out = stream.clone_dtoh(&nodes_dev)?;
461-
stream.synchronize()?;
462-
Ok(out)
463-
}
464-
465-
/// Like [`build_comp_poly_tree_from_evals_ext3`] but keeps the tree nodes on
466-
/// device (returned as a [`crate::lde::GpuMerkleTree`] with its root), so R4
458+
/// Build the comp poly Merkle tree on device and keep the nodes resident
459+
/// (returned as a [`crate::lde::GpuMerkleTree`] with its root), so R4
467460
/// composition openings gather paths on device instead of copying the whole
468461
/// tree to host. `leaves_len = lde_size / 2` (row pair leaves).
469462
pub fn build_comp_poly_tree_from_evals_ext3_keep(
@@ -480,11 +473,12 @@ pub fn build_comp_poly_tree_from_evals_ext3_keep(
480473
})
481474
}
482475

483-
/// Build a FRI-layer Merkle tree on device from an interleaved ext3 eval
484-
/// vector. Each leaf hashes two consecutive ext3 values. `num_leaves =
485-
/// evals.len() / 6` (since each ext3 is 3 u64s).
486-
///
487-
/// Returns the `(2*num_leaves - 1) * 32`-byte node buffer in standard layout.
476+
/// Test-only parity harness: build a FRI layer Merkle tree on device from an
477+
/// interleaved ext3 eval vector and return the full host node buffer so tests
478+
/// can compare it byte for byte against the CPU. Production folds and commits
479+
/// via [`crate::fri::FriLayer::fold_and_commit_layer`]. Each leaf hashes two
480+
/// consecutive ext3 values; `num_leaves = evals.len() / 6`. Returns the
481+
/// `(2*num_leaves - 1) * 32`-byte node buffer in standard layout.
488482
pub fn build_fri_layer_tree_from_evals_ext3(evals: &[u64]) -> Result<Vec<u8>> {
489483
assert!(
490484
evals.len().is_multiple_of(6),

crypto/math-cuda/tests/keccak_leaves.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,14 @@ fn keccak_comp_poly_leaves_matches_cpu() {
217217
let parts_slices: Vec<&[u64]> =
218218
parts_interleaved.iter().map(|v| v.as_slice()).collect();
219219

220-
let nodes =
221-
math_cuda::merkle::build_comp_poly_tree_from_evals_ext3(&parts_slices).unwrap();
220+
// Exercise the production keep path, then read the resident nodes
221+
// back to host to check the leaf bytes.
222+
let tree =
223+
math_cuda::merkle::build_comp_poly_tree_from_evals_ext3_keep(&parts_slices)
224+
.unwrap();
225+
let be = math_cuda::device::backend().unwrap();
226+
let stream = be.next_stream();
227+
let nodes: Vec<u8> = stream.clone_dtoh(&*tree.nodes).unwrap();
222228
let num_leaves = lde_size / 2;
223229
let leaves_offset = (num_leaves - 1) * 32;
224230
for i in 0..num_leaves {

crypto/stark/src/instruments.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,18 @@ use std::sync::OnceLock;
44
use std::sync::atomic::{AtomicU64, Ordering};
55
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
66

7-
// =========================================================================
8-
// Wall-clock span timeline (the trustworthy per-step measurement)
9-
// =========================================================================
7+
// Wall clock span timeline: the trustworthy per step latency breakdown.
108
//
11-
// Nested wall clock spans opened and closed on the driving (main) thread at
12-
// phase boundaries. Unlike the `accum_*` thread local sub timers below (which
13-
// sum per worker CPU time across rayon threads and over count, so percentages
14-
// exceed 100%), these spans do not overlap and sum to their parent, so the tree
15-
// is a true latency breakdown. Parallel regions are measured as a single span
16-
// around the blocking call (that is their latency); their internal split is
17-
// reported separately as CPU time, never mixed into the wall tree.
9+
// Spans open and close on the main thread at phase boundaries. They do not
10+
// overlap and sum to their parent, so the tree is a true latency breakdown
11+
// (unlike the accum_* thread local sub timers below, which sum per worker CPU
12+
// time across rayon threads and can exceed 100%). A parallel region is one span
13+
// around the blocking call; its internal split is reported separately as CPU
14+
// time, never mixed into the wall tree.
1815
//
1916
// let _s = instruments::span("trace_build"); // RAII, stops on drop
2017
//
21-
// `Instant::now()` is about 20 ns, fine at phase granularity; never put it
22-
// inside per op loops.
18+
// Instant::now() is about 20 ns, fine at phase granularity, not in per op loops.
2319

2420
#[derive(Clone, Debug)]
2521
pub struct SpanRecord {
@@ -138,9 +134,11 @@ pub fn timeline_json(spans: &[SpanRecord]) -> String {
138134
if i > 0 {
139135
out.push(',');
140136
}
137+
// Escape the label so a quote or backslash cannot break the JSON.
138+
let label = s.label.replace('\\', "\\\\").replace('"', "\\\"");
141139
out.push_str(&format!(
142140
"{{\"label\":\"{}\",\"depth\":{},\"wall_ns\":{},\"order\":{},\"start_ns\":{}}}",
143-
s.label,
141+
label,
144142
s.depth,
145143
s.wall.as_nanos(),
146144
s.order,

crypto/stark/src/prover.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -424,14 +424,10 @@ pub fn table_parallelism() -> usize {
424424
}
425425
}
426426

427-
/// Heuristic peak device working set for one table, in bytes. Two parts: the
428-
/// LDE columns co-resident on the GPU (main base field at 8 B, aux ext3 at
429-
/// 24 B) times a scratch factor for the NTT and leaf hash transients, plus the
430-
/// resident Merkle trees (main, aux, composition, FRI layers) kept on device R1
431-
/// to R4. Each full tree is about `2*lde_size` nodes of 32 B (`64*lde_size`);
432-
/// together at the R4 peak about 256 B per `lde_size` covers them. A deliberate
433-
/// over estimate that gates a safety ceiling, not a precise allocator. Pass
434-
/// `aux_cols == 0` where the aux LDE is not yet resident (R1 main commit).
427+
/// Heuristic peak device bytes for one table: co-resident LDE columns plus the
428+
/// resident Merkle trees, with a scratch factor for NTT and leaf transients. A
429+
/// deliberate over estimate for a safety ceiling, not a precise allocator. Pass
430+
/// aux_cols == 0 when the aux LDE is not yet resident (R1 main commit).
435431
fn estimate_table_vram_bytes(main_cols: usize, aux_cols: usize, lde_size: usize) -> u64 {
436432
const BYTES_PER_BASE: u64 = 8;
437433
const EXT3_BYTES: u64 = 24;
@@ -445,16 +441,12 @@ fn estimate_table_vram_bytes(main_cols: usize, aux_cols: usize, lde_size: usize)
445441
lde_term.saturating_add(tree_term)
446442
}
447443

448-
/// Plan contiguous table chunks for parallel proving.
449-
///
450-
/// A chunk grows until it reaches `k` tables (the core and RAM bound limit) or
451-
/// its summed VRAM estimate would exceed `budget`, whichever comes first. A
452-
/// single table larger than `budget` forms its own chunk (it runs solo rather
453-
/// than being excluded). With `budget == u64::MAX` the VRAM constraint is never
454-
/// binding for any realistic estimate, so chunks fall back to fixed size `k`,
455-
/// the same as the previous `step_by(k)` scheme. So on non-cuda builds and when
456-
/// VRAM is not binding, scheduling (and therefore the proof) is unchanged.
457-
/// Returns `(start, end)` half open ranges covering `0..estimates.len()` in order.
444+
/// Plan contiguous table chunks for parallel proving. A chunk grows until it
445+
/// hits `k` tables or its summed VRAM estimate would exceed `budget`; a single
446+
/// table larger than `budget` runs solo. With `budget == u64::MAX` (non-cuda,
447+
/// or VRAM not binding) chunks fall back to fixed size `k`, identical to the
448+
/// old `step_by(k)`, so scheduling and the proof are unchanged. Returns
449+
/// `(start, end)` half open ranges covering `0..estimates.len()` in order.
458450
fn plan_table_chunks(estimates: &[u64], k: usize, budget: u64) -> Vec<(usize, usize)> {
459451
let n = estimates.len();
460452
let k = k.max(1);

0 commit comments

Comments
 (0)