Skip to main content

sim_lib_compute_wgpu/
counters.rs

1//! Physical queue-derived evidence for resident wgpu submissions.
2
3use std::sync::{Arc, Mutex};
4
5use crate::WgpuResidentSegment;
6
7/// Physical buffer range touched by a resident wgpu submission.
8#[derive(Clone, Debug, PartialEq, Eq)]
9pub struct BufferRange {
10    /// Byte offset inside the logical resident tensor buffer.
11    pub offset: u64,
12    /// Number of bytes touched.
13    pub bytes: u64,
14}
15
16impl From<&WgpuResidentSegment> for BufferRange {
17    fn from(segment: &WgpuResidentSegment) -> Self {
18        Self {
19            offset: segment.offset,
20            bytes: segment.bytes,
21        }
22    }
23}
24
25/// Queue-derived evidence for physical wgpu tensor work.
26#[derive(Clone, Debug, Default, PartialEq, Eq)]
27pub struct PhysicalSubmissionEvidence {
28    /// Queue submissions issued by the executor.
29    pub submissions: u64,
30    /// Host bytes uploaded through queue writes.
31    pub uploaded_bytes: u64,
32    /// Full tensor readbacks requested by terminal materialization.
33    pub full_readbacks: u64,
34    /// Scalar synchronizations performed for scalar reductions.
35    pub scalar_syncs: u64,
36    /// Resident ranges touched by submitted command buffers.
37    pub segments_touched: Vec<BufferRange>,
38}
39
40#[derive(Clone, Debug, Default)]
41pub(crate) struct WgpuPhysicalCounters {
42    inner: Arc<Mutex<PhysicalSubmissionEvidence>>,
43}
44
45impl WgpuPhysicalCounters {
46    pub(crate) fn snapshot(&self) -> PhysicalSubmissionEvidence {
47        self.inner
48            .lock()
49            .expect("wgpu physical counters poisoned")
50            .clone()
51    }
52
53    pub(crate) fn record_upload(&self, bytes: u64) {
54        let mut evidence = self.inner.lock().expect("wgpu physical counters poisoned");
55        evidence.uploaded_bytes = evidence.uploaded_bytes.saturating_add(bytes);
56    }
57
58    pub(crate) fn record_submit(&self, segments: &[WgpuResidentSegment]) {
59        let mut evidence = self.inner.lock().expect("wgpu physical counters poisoned");
60        evidence.submissions = evidence.submissions.saturating_add(1);
61        evidence
62            .segments_touched
63            .extend(segments.iter().map(BufferRange::from));
64    }
65
66    pub(crate) fn record_full_readback(&self) {
67        let mut evidence = self.inner.lock().expect("wgpu physical counters poisoned");
68        evidence.full_readbacks = evidence.full_readbacks.saturating_add(1);
69    }
70
71    pub(crate) fn record_scalar_sync(&self) {
72        let mut evidence = self.inner.lock().expect("wgpu physical counters poisoned");
73        evidence.scalar_syncs = evidence.scalar_syncs.saturating_add(1);
74    }
75}