Skip to content

Commit 6e3a723

Browse files
authored
misc: more comments and slightly adjust flow (#1256)
hide `launch_idx` and simplify some conditioning logic
1 parent 1e7fffb commit 6e3a723

1 file changed

Lines changed: 39 additions & 36 deletions

File tree

ceno_zkvm/src/scheme/scheduler.rs

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -372,60 +372,63 @@ impl ChipScheduler {
372372
let mut pending: Vec<ChipTask<'a, PB>> = tasks;
373373

374374
while !pending.is_empty() || tasks_inflight > 0 {
375-
// A: Non-blocking drain completions
376-
for msg in done_rx.try_iter() {
375+
// First drain any completions already available to free memory immediately.
376+
// This non-blocking path keeps utilization high (and covers the initial loop
377+
// iteration when nothing is running yet), so we handle completions here.
378+
while let Ok(msg) = done_rx.try_recv() {
377379
if let Err(e) = handle_completion(msg, pool, &mut tasks_inflight, "") {
378380
drop(task_tx);
379381
return Err(e);
380382
}
381383
}
382384

383-
// B: Find first task that fits
384-
let mut launched_idx = None;
385+
// Launch the first pending task whose memory fits; otherwise fall through to wait.
385386
if tasks_inflight < CONCURRENT_PROVING_WORKERS {
386-
for (vec_idx, task) in pending.iter().enumerate() {
387-
if pool
388-
.try_book_capacity(task.estimated_memory_bytes)
387+
if let Some(vec_idx) = pending.iter().position(|task| {
388+
pool.try_book_capacity(task.estimated_memory_bytes)
389389
.is_some()
390-
{
391-
tracing::info!(
392-
"[scheduler] Launching circuit={}, estimated_mem={:.2}MB, pool_booked={:.2}MB",
393-
task.circuit_name,
394-
task.estimated_memory_bytes as f64 / (1024.0 * 1024.0),
395-
pool.get_booked_total() as f64 / (1024.0 * 1024.0)
396-
);
397-
launched_idx = Some(vec_idx);
398-
break;
399-
}
390+
}) {
391+
let task = pending.remove(vec_idx);
392+
tracing::info!(
393+
"[scheduler] Launching circuit={}, estimated_mem={:.2}MB, pool_booked={:.2}MB",
394+
task.circuit_name,
395+
task.estimated_memory_bytes as f64 / (1024.0 * 1024.0),
396+
pool.get_booked_total() as f64 / (1024.0 * 1024.0)
397+
);
398+
tasks_inflight += 1;
399+
task_tx.send(task).unwrap();
400+
continue;
400401
}
401402
}
402403

403-
if let Some(vec_idx) = launched_idx {
404-
let task = pending.remove(vec_idx);
405-
tasks_inflight += 1;
406-
task_tx.send(task).unwrap();
407-
} else if tasks_inflight > 0 {
408-
// C: Block wait for completion when nothing fits
409-
tracing::info!(
410-
"[scheduler] Pool full, waiting for task completion... pool_booked={:.2}MB, inflight={}",
411-
pool.get_booked_total() as f64 / (1024.0 * 1024.0),
412-
tasks_inflight
413-
);
414-
if let Ok(msg) = done_rx.recv() {
404+
// No task launched: either nothing fits (so wait) or we are deadlocked.
405+
if tasks_inflight == 0 {
406+
tracing::error!("Deadlock: Remaining tasks are too big for the memory pool!");
407+
return Err(ZKVMError::BackendError(BackendError::CircuitError(
408+
"Deadlock: Remaining tasks are too big for the memory pool!"
409+
.to_string()
410+
.into_boxed_str(),
411+
)));
412+
}
413+
414+
tracing::info!(
415+
"[scheduler] Pool full, waiting for task completion... pool_booked={:.2}MB, inflight={}",
416+
pool.get_booked_total() as f64 / (1024.0 * 1024.0),
417+
tasks_inflight
418+
);
419+
420+
// Second call site blocks instead of busy-waiting when the pool is full; this
421+
// waits for the next completion to free memory before trying to launch again.
422+
match done_rx.recv() {
423+
Ok(msg) => {
415424
if let Err(e) =
416425
handle_completion(msg, pool, &mut tasks_inflight, " (blocked)")
417426
{
418427
drop(task_tx);
419428
return Err(e);
420429
}
421430
}
422-
} else {
423-
tracing::error!("Deadlock: Remaining tasks are too big for the memory pool!");
424-
return Err(ZKVMError::BackendError(BackendError::CircuitError(
425-
"Deadlock: Remaining tasks are too big for the memory pool!"
426-
.to_string()
427-
.into_boxed_str(),
428-
)));
431+
Err(_) => break,
429432
}
430433
}
431434

0 commit comments

Comments
 (0)