Skip to content

Commit db2d04c

Browse files
committed
Merge m4b/b1 @ 11d3e43 (b1 rebased on #1014 59e9890, the rest sink on) into m4b/b2
2 parents 13702eb + 11d3e43 commit db2d04c

4 files changed

Lines changed: 102 additions & 17 deletions

File tree

‎crypto/stark/src/multilinear_block.rs‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -741,15 +741,20 @@ where
741741
.unwrap_or_else(|panic| std::panic::resume_unwind(panic));
742742
let next = next.map(|(group, store, wide, upload, uploaded)| {
743743
// What the committer waited for once its commit ended:
744-
// the group's arrival, then the rest of its upload.
744+
// the group's arrival, then the rest of its upload —
745+
// never more than the upload (a commit that ended before
746+
// the upload began paid all of it, and no more).
745747
let ready = arrived.max(commit_end);
746748
Ahead {
747749
group,
748750
store,
749751
wide,
750752
upload,
751753
wait_paid: arrived.saturating_duration_since(commit_end).as_secs_f64(),
752-
upload_paid: uploaded.saturating_duration_since(ready).as_secs_f64(),
754+
upload_paid: uploaded
755+
.saturating_duration_since(ready)
756+
.as_secs_f64()
757+
.min(upload),
753758
}
754759
});
755760
(committed, next)

‎prover/src/block_whir.rs‎

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,13 @@ pub struct BlockOptions {
235235
pub drop_streamed_ops: bool,
236236
/// With windows: `0` lays each streamed chunk out on the layout thread as
237237
/// it arrives; `n > 0` lays them out on `n` threads, packed in arrival
238-
/// order all the same, while the layout thread lays out the rest of the
239-
/// run as soon as it is built. Production: 0. Three read −0.54 / −0.22 s of
240-
/// base (FAST 421 / 422), but their extra host memory grows with the block
241-
/// (BIG 390: +2.2 / +4.2 / +8.7 GiB at 1.0 / 1.3 / 1.8×).
238+
/// order all the same (the same groups and proof bytes), while the layout
239+
/// thread lays out the rest of the run as soon as it is built. Production:
240+
/// 3. Once phase A uploads ahead, the inline layout closes the middle groups
241+
/// after the card is free; three workers close them in time (FAST 835:
242+
/// phase A −0.93 s, whole block −1.00 s, peak −0.68 GiB at 1×). Unbounded
243+
/// they held more host memory as the block grew (BIG 390); `layout_ahead`
244+
/// bounds them (BIG 392: flat).
242245
pub layout_workers: usize,
243246
/// With `layout_workers > 0`: `Some(k)` lets at most `k + 1` streamed
244247
/// chunks be laid out (or in the making) and not yet packed, where the
@@ -247,7 +250,12 @@ pub struct BlockOptions {
247250
pub layout_ahead: Option<usize>,
248251
/// With `layout_workers > 0`: pack the rest of the run as it is laid out,
249252
/// in AIR order, so a group closes once its own tables are ready instead
250-
/// of after all of them; the packing order is the same.
253+
/// of after all of them; the packing order is the same. Production: on,
254+
/// with [`Self::rest_layout_bytes`]'s waves — laid out all at once, the
255+
/// first table in AIR order was ready only with the last, and packing as
256+
/// laid out read +0.21 s (FAST 422); in waves the AIR order's prefix is
257+
/// laid out first, and since three layout workers (04984808d) phase A
258+
/// waits on the groups the rest closes.
251259
pub pack_rest_as_laid_out: bool,
252260
/// How phase A holds each group's columns once committed
253261
/// ([`multilinear_block::Narrowing`]): production packs them narrow on the
@@ -302,9 +310,9 @@ impl BlockOptions {
302310
stream_keccak_rnd: false,
303311
stream_memw_lt: false,
304312
drop_streamed_ops: true,
305-
layout_workers: 0,
313+
layout_workers: 3,
306314
layout_ahead: Some(2),
307-
pack_rest_as_laid_out: false,
315+
pack_rest_as_laid_out: true,
308316
narrow: multilinear_block::Narrowing::CARD,
309317
upload_ahead: true,
310318
memlog: memlog::from_env(),
@@ -518,6 +526,9 @@ pub struct LayoutStamps {
518526
/// The rest's tables laid out narrow from the finish's packed columns
519527
/// ([`BlockOptions::pack_finished`]): how many, and their packed bytes.
520528
pub packed_rest: (usize, usize),
529+
/// Each table of the rest in AIR order: its name, when its layout ended
530+
/// (seconds since the prove started) and its group.
531+
pub rest_tables: Vec<(String, f64, usize)>,
521532
}
522533

523534
impl BlockStamps {
@@ -536,7 +547,7 @@ impl BlockStamps {
536547
);
537548
for (g, s) in self.groups.iter().enumerate() {
538549
out.push_str(&format!(
539-
"BLOCK GROUP {g}: tables {} · polys {} · cells {:.1} M || A wait {:.3} upload {:.3} paid {:.3} commit {:.3} retire {:.3} done@{:.2} || B upload {:.3} argue {:.3} encode {:.3} open {:.3}\n",
550+
"BLOCK GROUP {g}: tables {} · polys {} · cells {:.1} M || A wait {:.3} upload {:.3} paid {:.3} commit {:.3} retire {:.3} from@{:.2} done@{:.2} || B upload {:.3} argue {:.3} encode {:.3} open {:.3}\n",
540551
s.tables,
541552
s.polys,
542553
s.cells as f64 / 1e6,
@@ -545,6 +556,7 @@ impl BlockStamps {
545556
s.upload_paid,
546557
s.commit,
547558
s.retire,
559+
s.committed_at - s.commit - s.retire,
548560
s.committed_at,
549561
s.upload_b,
550562
s.argue,
@@ -607,6 +619,15 @@ impl BlockStamps {
607619
l.packed_rest.0,
608620
l.packed_rest.1 as f64 / (1u64 << 30) as f64,
609621
));
622+
let tables: Vec<String> = l
623+
.rest_tables
624+
.iter()
625+
.map(|(name, at, group)| format!("{name}@{at:.2}·g{group}"))
626+
.collect();
627+
out.push_str(&format!(
628+
"BLOCK REST TABLES (laid out at · group): {}\n",
629+
tables.join(" ")
630+
));
610631
}
611632
out.push_str(&format!(
612633
"BLOCK RECOMMIT: 0 (a revived commitment builds no tree) · first-round paths from kept tops: {} calls · {} leaves re-hashed on the host · phase B on one thread + one upload helper\n",
@@ -2283,6 +2304,9 @@ struct RestLaid<'a> {
22832304
busy: f64,
22842305
/// [`LayoutStamps::packed_rest`].
22852306
packed_rest: (usize, usize),
2307+
/// Each table's AIR index and when its layout ended (seconds since the
2308+
/// prove started), in AIR order.
2309+
laid_at: Vec<(usize, f64)>,
22862310
}
22872311

22882312
/// `prepared_now`: derive the prepared columns here, before the tables are
@@ -2351,8 +2375,9 @@ fn lay_out_rest<'a>(
23512375
.enumerate()
23522376
.filter(|(_, ((_, trace, _), _))| trace.main_table.width != 0)
23532377
.collect();
2354-
// Each table's seconds, for the readout, and the tables laid out narrow.
2378+
// Each table's seconds and when its layout ended, for the readout.
23552379
let timed = std::sync::Mutex::new(Vec::with_capacity(built.len()));
2380+
let laid_at = std::sync::Mutex::new(Vec::with_capacity(built.len()));
23562381
let narrow_tables = std::sync::atomic::AtomicUsize::new(0);
23572382
let narrow_bytes = std::sync::atomic::AtomicUsize::new(0);
23582383
let lay_out = |(i, ((_, trace, _), air)): (usize, ((_, &mut TraceTable<F, E>, _), _))| {
@@ -2371,6 +2396,9 @@ fn lay_out_rest<'a>(
23712396
table_of(air, trace, shape, true)
23722397
}
23732398
.map(|table| (i, shape, table));
2399+
if let Ok(mut laid_at) = laid_at.lock() {
2400+
laid_at.push((i, start.elapsed().as_secs_f64()));
2401+
}
23742402
if let (Some(ledger), Ok((_, _, table))) = (ledger, &laid) {
23752403
use std::sync::atomic::Ordering::Relaxed;
23762404
ledger.rest.fetch_sub(rows, Relaxed);
@@ -2472,6 +2500,11 @@ fn lay_out_rest<'a>(
24722500
slowest,
24732501
busy: t.elapsed().as_secs_f64(),
24742502
packed_rest: (narrow_tables.into_inner(), narrow_bytes.into_inner()),
2503+
laid_at: {
2504+
let mut laid_at = laid_at.into_inner().unwrap_or_default();
2505+
laid_at.sort_unstable_by_key(|&(i, _)| i);
2506+
laid_at
2507+
},
24752508
})
24762509
}
24772510

@@ -2801,6 +2834,7 @@ fn prove_streamed(
28012834
slowest,
28022835
busy: rest_busy,
28032836
packed_rest,
2837+
laid_at,
28042838
} = rest;
28052839
let names: std::collections::HashMap<String, usize> = refs
28062840
.iter()
@@ -2877,6 +2911,16 @@ fn prove_streamed(
28772911
})
28782912
.collect::<Result<Vec<_>, Error>>()?;
28792913
let busy = chunks + rest_busy + t.elapsed().as_secs_f64();
2914+
let group_of = |table: usize| {
2915+
groups
2916+
.iter()
2917+
.position(|g| g.contains(&(table as u32)))
2918+
.unwrap_or(usize::MAX)
2919+
};
2920+
let rest_tables = laid_at
2921+
.iter()
2922+
.map(|&(i, at)| (refs[i].name().to_string(), at, group_of(i)))
2923+
.collect();
28802924
Ok(Laid {
28812925
table_counts,
28822926
runtime_page_ranges,
@@ -2895,6 +2939,7 @@ fn prove_streamed(
28952939
slowest,
28962940
ahead_most,
28972941
packed_rest,
2942+
rest_tables,
28982943
},
28992944
})
29002945
});

‎prover/src/lfm/whir_block_tests.rs‎

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,6 @@ fn the_whir_block_tree_on_a_real_block() {
13561356
if let Some(n) = knob("BLOCK_WHIR_LAYOUT_WORKERS") {
13571357
options.layout_workers = n;
13581358
}
1359-
// `BLOCK_WHIR_PACK_REST=1`: the rest of the run packed as it is laid out.
13601359
// `BLOCK_WHIR_LAYOUT_AHEAD=k` bounds the chunks unpacked at k + 1;
13611360
// `none` lifts the bound (the reverted version, BIG 390).
13621361
match std::env::var("BLOCK_WHIR_LAYOUT_AHEAD")
@@ -1371,8 +1370,17 @@ fn the_whir_block_tree_on_a_real_block() {
13711370
}
13721371
Err(_) => {}
13731372
}
1374-
options.pack_rest_as_laid_out =
1375-
std::env::var("BLOCK_WHIR_PACK_REST").is_ok_and(|v| v.trim() == "1");
1373+
// `BLOCK_WHIR_PACK_REST=0|1` (production 1): the rest packed as it is laid
1374+
// out.
1375+
match std::env::var("BLOCK_WHIR_PACK_REST")
1376+
.as_deref()
1377+
.map(str::trim)
1378+
{
1379+
Ok("0") => options.pack_rest_as_laid_out = false,
1380+
Ok("1") => options.pack_rest_as_laid_out = true,
1381+
Ok(other) => panic!("BLOCK_WHIR_PACK_REST={other}: 0 or 1"),
1382+
Err(_) => {}
1383+
}
13761384
// `BLOCK_WHIR_DROP_OPS=0`: the builder keeps the streamed chunks' ops
13771385
// (production drops them).
13781386
match std::env::var("BLOCK_WHIR_DROP_OPS")
@@ -1510,6 +1518,24 @@ fn the_whir_block_tree_on_a_real_block() {
15101518
options.keccak_rows_log2,
15111519
options.ecsm_rows_log2,
15121520
);
1521+
// Each group's tables by AIR, in the group's order: which tables the
1522+
// card waited for, and where the layout's chunks went.
1523+
for (g, group) in proof.groups.iter().enumerate() {
1524+
let mut kinds: Vec<(String, usize)> = Vec::new();
1525+
for &index in group {
1526+
let name = refs[index as usize].name();
1527+
let kind = name.split('[').next().unwrap_or(name).to_string();
1528+
match kinds.last_mut() {
1529+
Some((last, n)) if *last == kind => *n += 1,
1530+
_ => kinds.push((kind, 1)),
1531+
}
1532+
}
1533+
let kinds: Vec<String> = kinds
1534+
.into_iter()
1535+
.map(|(kind, n)| if n == 1 { kind } else { format!("{kind}×{n}") })
1536+
.collect();
1537+
println!("W3 GROUP TABLES {g}: {}", kinds.join(" "));
1538+
}
15131539
}
15141540
println!(
15151541
"W3 BASE: {base:.2}s · statement at {stated_at:.2}s · plan + {} leaves emitted by {ready_at:.2}s ({})",

‎prover/src/tests/block_whir_tests.rs‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,7 +2102,7 @@ fn block_whir_on_a_real_block() {
21022102
};
21032103
let mut options = BlockOptions::production();
21042104
// `BLOCK_WHIR_LAYOUT_WORKERS=n` (production 0, the inline layout) and
2105-
// `BLOCK_WHIR_PACK_REST=1`, as the tree's harness takes them;
2105+
// `BLOCK_WHIR_PACK_REST=0|1`, as the tree's harness takes them;
21062106
// `BLOCK_WHIR_DROP_OPS=0`: the builder keeps the streamed chunks' ops
21072107
// (production drops them).
21082108
if let Some(n) = std::env::var("BLOCK_WHIR_LAYOUT_WORKERS")
@@ -2125,8 +2125,17 @@ fn block_whir_on_a_real_block() {
21252125
}
21262126
Err(_) => {}
21272127
}
2128-
options.pack_rest_as_laid_out =
2129-
std::env::var("BLOCK_WHIR_PACK_REST").is_ok_and(|v| v.trim() == "1");
2128+
// `BLOCK_WHIR_PACK_REST=0|1` (production 1): the rest packed as it is laid
2129+
// out.
2130+
match std::env::var("BLOCK_WHIR_PACK_REST")
2131+
.as_deref()
2132+
.map(str::trim)
2133+
{
2134+
Ok("0") => options.pack_rest_as_laid_out = false,
2135+
Ok("1") => options.pack_rest_as_laid_out = true,
2136+
Ok(other) => panic!("BLOCK_WHIR_PACK_REST={other}: 0 or 1"),
2137+
Err(_) => {}
2138+
}
21302139
match std::env::var("BLOCK_WHIR_DROP_OPS")
21312140
.as_deref()
21322141
.map(str::trim)

0 commit comments

Comments
 (0)