+28
-8
src/main.rs
+28
-8
src/main.rs
···
109
109
handle.join().unwrap();
110
110
}
111
111
if let Some(handle) = gpu_handle {
112
-
handle.join().unwrap();
112
+
if let Err(e) = handle.join() {
113
+
println!("GPU thread exited with error: {:?}", e);
114
+
}
113
115
}
114
116
115
117
println!("Finished heating for {:?}", start_time.elapsed());
···
240
242
});
241
243
compute_pass.set_pipeline(&compute_pipeline);
242
244
compute_pass.set_bind_group(0, &bind_group, &[]);
243
-
// Dispatch enough work to keep GPU busy
244
-
compute_pass.dispatch_workgroups(256, 256, 1);
245
+
// Dispatch enough work to keep GPU busy. Use a smaller grid to
246
+
// avoid very long-running single submissions which can trigger
247
+
// backend timeouts during shutdown.
248
+
compute_pass.dispatch_workgroups(128, 128, 1);
245
249
}
246
250
251
+
// Gracefully handle errors on shutdown
252
+
// Submit work
247
253
queue.submit(Some(encoder.finish()));
248
-
// Queue submission handles synchronization
249
-
250
254
iteration += 1;
251
-
//if iteration % 100 == 0 {
252
-
// println!("GPU iterations: {}", iteration);
253
-
//}
255
+
}
256
+
257
+
// Wait for all submitted work to complete before returning to avoid
258
+
// backend timeouts during shutdown. `on_submitted_work_done` takes a
259
+
// callback, so use a channel and wait with a timeout to avoid hanging
260
+
// indefinitely.
261
+
let (tx, rx) = std::sync::mpsc::sync_channel(1);
262
+
queue.on_submitted_work_done(move || {
263
+
// best-effort send; ignore error if receiver was dropped
264
+
let _ = tx.send(());
265
+
});
266
+
match rx.recv_timeout(Duration::from_secs(30)) {
267
+
Ok(()) => (),
268
+
Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
269
+
eprintln!("Warning: timed out waiting for GPU work to complete during shutdown");
270
+
}
271
+
Err(e) => {
272
+
eprintln!("Warning: error while waiting for GPU shutdown: {:?}", e);
273
+
}
254
274
}
255
275
256
276
println!("GPU heater stopped after {} iterations", iteration);