Skip to main content

onnx_runtime_memory/
oracle.rs

1//! The **size oracle**: byte size of an activation value.
2//!
3//! Sizes may be unknown at build time when a shape has symbolic (dynamic)
4//! dimensions. The planner is generic over any `Fn(ValueId) -> Option<usize>`
5//! so the *same* algorithm serves two callers:
6//!
7//! * **build-time** planning from fully-static shapes ([`static_size_oracle`]),
8//!   which returns `None` for any symbolic-shaped value and drives the planner
9//!   to a [`crate::PlanStatus::Deferred`] result; and
10//! * **run-time** planning, where the executor supplies a closure backed by the
11//!   resolved concrete shapes for the current run.
12
13use onnx_runtime_ir::{as_static_shape, Graph, ValueId};
14
15/// Byte size of a value from its *static* shape, or `None` if any dimension is
16/// symbolic (unknown until run time) or the element count overflows `usize`.
17///
18/// Uses [`onnx_runtime_ir::DataType::checked_storage_bytes`] so sub-byte packed
19/// types (`int4`/`uint4`/`float4`) are sized correctly and an overflowing
20/// element count becomes `None` rather than a wrapped under-count.
21pub fn static_size(graph: &Graph, value: ValueId) -> Option<usize> {
22    let val = graph.try_value(value)?;
23    let dims = as_static_shape(&val.shape)?;
24    let mut numel: usize = 1;
25    for d in dims {
26        numel = numel.checked_mul(d)?;
27    }
28    val.dtype.checked_storage_bytes(numel)
29}
30
31/// A size oracle closure that sizes values from their fully-static shapes.
32///
33/// Returns `None` for any symbolic-shaped value, which the planner reports as
34/// [`crate::PlanStatus::Deferred`] so the executor can re-plan once shapes
35/// resolve.
36pub fn static_size_oracle(graph: &Graph) -> impl Fn(ValueId) -> Option<usize> + '_ {
37    move |value| static_size(graph, value)
38}