compute_context.h#
Graph-level annotation context that combines value-tag inference, in-place reuse analysis, and per-node memory profiling.
:cpp:class:ComputeContext stores the results of all three analyses and exposes them in a single object, mirroring the way :cpp:class:core::shapes::ShapesContext stores inferred descriptors.
-
namespace onnx_light
Alias that makes onnx-light headers compatible with code that references
ONNX_LIGHT_NAMESPACE(the macro used in the standard onnx package).Set to
ONNX_LIGHT_NAMESPACEso both names resolve to the same namespace.Symbol-visibility attribute for the public onnx-light C++ API.
Maps the upstream compatibility macro to onnx-light’s explicit proto ABI annotation. This keeps declarations from vendored ONNX headers visible when
lib_onnx_protouses hidden visibility by default.Namespace alias so that ONNX C++ code (and consumers such as onnxruntime) that refers to the literal
onnxnamespace — rather than theONNX_NAMESPACEmacro — resolves to the onnx-light namespace. The standard onnx package lives innamespace onnx; onnx-light usesonnx_light(via ONNX_LIGHT_NAMESPACE), so this alias keeps onnx-light a true drop-in. It is only introduced when the onnx-light namespace differs fromonnx.-
namespace core
-
namespace compute#
Typedefs
-
using ComputeEventLog = std::vector<ComputeEvent>#
-
using ShapeTag = std::string#
Represents a per-node memory snapshot computed by :cpp:class:
ComputeContext.The snapshot represents the memory footprint visible while one node runs:
already_allocated_bytesis the sum of the buffers already alive before the node starts (declared inputs, initializers and still-live intermediates), after shape inference and lifetime analysis;output_allocation_bytesis the additional memory that must be allocated for the node’s outputs because no eligible in-place reuse opportunity covers them;total_bytesis their sum.
The profile is stored as a
std::mapwith seven well-known keys:"total_bytes""already_allocated_bytes""output_allocation_bytes""inputs""initializers""intermediates""outputs"
The first three keys map to scalar :cpp:type:
core::expressions::DimTypevalues. The other four keys map tostd::map<ShapeTag, DimType>buckets split by value tag ("shape","axes","weight", or the empty string for untagged values)."already_allocated_bytes"is the sum of the"inputs","initializers"and"intermediates"maps;"output_allocation_bytes"is the sum of"outputs"; and"total_bytes"is the sum of those two scalar entries. Every amount is represented as a :cpp:type:core::expressions::DimType, so symbolic shapes retain their expression form instead of being dropped. The"outputs"map only counts the extra allocations performed at this node; outputs that reuse an existing input buffer in place contribute no additional bytes there.
-
using TaggedMemory = std::map<ShapeTag, expressions::DimType>#
-
using NodeMemoryProfileValue = std::variant<expressions::DimType, TaggedMemory>#
-
using NodeMemoryProfile = std::map<std::string, NodeMemoryProfileValue>#
Enums
-
enum class ComputeEventAction : int32_t#
Kind of decision recorded in the optional :cpp:class:
ComputeContextdecision log.kInPlace— one output was matched to one input for in-place reuse.kRelease— one value reached its last use at a node and can be released after that node.kReleaseShapeTag— one released value was also classified as"shape"by value tagging.
Values:
-
enumerator kInPlace#
-
enumerator kRelease#
-
enumerator kReleaseShapeTag#
Functions
-
inline constexpr const char *ComputeEventActionName(ComputeEventAction action)#
Returns the short lowercase label for
action.
Variables
-
constexpr const char *kNodeMemoryTotalBytesKey = "total_bytes"#
-
constexpr const char *kNodeMemoryAlreadyAllocatedBytesKey = "already_allocated_bytes"#
-
constexpr const char *kNodeMemoryOutputAllocationBytesKey = "output_allocation_bytes"#
-
constexpr const char *kNodeMemoryInputsKey = "inputs"#
-
constexpr const char *kNodeMemoryInitializersKey = "initializers"#
-
constexpr const char *kNodeMemoryIntermediatesKey = "intermediates"#
-
constexpr const char *kNodeMemoryOutputsKey = "outputs"#
-
class ComputeContext#
- #include <compute_context.h>
Holds the in-place reuse opportunities computed for a graph, mirroring the way :cpp:class:
core::shapes::ShapesContextholds the inferred descriptors.The reuse guess is purely structural: it reports the opportunities implied by shape inference and value lifetimes, not whether a particular kernel actually performs the reuse. Populate the context with :cpp:func:
ComputeInPlaceReuseGraph(consuming a :cpp:class:ShapesContextalready filled by :cpp:func:ShapesContext::ComputeShapeGraphor :cpp:func:ShapesContext::ComputeShapeModel), then read the result through :cpp:func:Reuse/ :cpp:func:NodeReuseor persist it into the graph with :cpp:func:WriteToMetadata.Public Types
-
using CustomValueTagFn = std::function<void(ComputeContext&, const NodeProto&, std::size_t node_index)>#
Callback signature for custom value-tag behavior. Receives
(ctx, node, node_index)wherectxcan be mutated through :cpp:func:TrySetValueTag/ :cpp:func:SetNodeTag.
-
using CustomValueTagMap = std::unordered_map<std::string, CustomValueTagFn>#
-
using InputShapes = std::unordered_map<std::string, SymTensor>#
Map from value name to the :cpp:class:
SymTensordescribing its shape and element type, used to seed shape inference for a :cpp:class:FunctionProtoor a bare node list (neither of which carries declared input types).
Public Functions
-
ComputeContext() = default#
-
std::pair<std::unordered_map<std::string, std::string>, std::vector<std::string>> ComputeValueAndNodeTags(const GraphProto &graph)#
Infers semantic
shape/axes/weighttags for the values and nodes ingraphand stores the result in*this(replacing any previously computed tags).- Returns:
A pair
(value_tags, node_tags)wherevalue_tagsmaps value names to their inferred tag andnode_tagsfollows the order ofgraph.node().
-
std::pair<std::unordered_map<std::string, std::string>, std::vector<std::string>> ComputeValueAndNodeTags(const FunctionProto &function)#
Same as :cpp:func:
ComputeValueAndNodeTags(const GraphProto&)but for a function body.
-
std::pair<std::unordered_map<std::string, std::string>, std::vector<std::string>> ComputeValueAndNodeTags(const utils::RepeatedProtoField<NodeProto> &nodes)#
Same as :cpp:func:
ComputeValueAndNodeTags(const GraphProto&)but for an arbitrary node list.
-
void SeedValueTag(const std::string &name, const std::string &tag)#
Seeds an initial value tag for a graph input, initializer, value_info or output so it participates in the incremental tag inference driven by :cpp:func:
AppendNodeTags. Mirrors the seeding performed whole-graph by :cpp:func:CollectGraphSeedTags.
-
void AppendNodeTags(const utils::RepeatedProtoField<NodeProto> &nodes, std::size_t node_index)#
Incrementally updates the value/node tags after the node at
node_index(the last node ofnodes) has been appended. Only that node and the nodes whose values it changes are (re)processed through a monotone worklist — no whole-graph loop — so appendingNnodes stays linear in the graph size instead of quadratic. The built-in inference rules converge to the same least fixed point as :cpp:func:ComputeValueAndNodeTags.
-
inline const std::unordered_map<std::string, std::string> &ValueTags() const noexcept#
Read-only access to the last value-tag map computed through :cpp:func:
ComputeValueAndNodeTags.
-
inline const std::vector<std::string> &NodeTags() const noexcept#
Read-only access to the last per-node tag list computed through :cpp:func:
ComputeValueAndNodeTags.
-
inline const std::string &NodeTag(std::size_t node_index) const#
Tag inferred for the node at
node_index.- Throws:
std::out_of_range – when
node_indexis out of bounds.
-
void SeedConstant(const std::string &name)#
Seeds
nameas a constant value (e.g. an initializer) so it participates in the incremental constant analysis driven by :cpp:func:AppendNodeConstant.
-
void AppendNodeConstant(const NodeProto &node, std::size_t node_index)#
Incrementally updates the constant analysis after the node at
node_indexhas been appended: records whether the node is constant and, when it is, marks its outputs as constant values. Appends exactly one entry to the per-node constant flag list.
-
inline bool IsConstantValue(const std::string &name) const noexcept#
Whether
nameis currently known to be a constant value.
-
inline const std::vector<ConstantInfo> &NodeConstant() const noexcept#
Read-only access to the incremental per-node constant classifications. One entry per appended node, in graph order.
-
inline bool NodeConstant(std::size_t node_index) const#
Whether the node at
node_indexproduces constant outputs.- Throws:
std::out_of_range – when
node_indexis out of bounds.
-
bool TrySetValueTag(const std::string &name, const std::string &tag)#
Sets or updates a value tag and returns
truewhen the internal map changed. Returnsfalsewhennameis empty, whentagis invalid/empty, or when setting it would not change the map.
-
bool SetNodeTag(std::size_t node_index, const std::string &tag)#
Sets or updates a per-node tag and returns
truewhen the internal list changed. Returnsfalsewhentagis invalid/empty or does not change the current value.- Throws:
std::out_of_range – when
node_indexis out of bounds.
-
inline void ClearCustomValueTagChangedFlag() noexcept#
Internal flag helpers used by value-tag inference around custom callbacks.
-
inline bool ConsumeCustomValueTagChangedFlag() noexcept#
-
inline void SetCustomValueTagFunction(const std::string &domain, const std::string &op_type, CustomValueTagFn fn)#
Registers or replaces a custom value-tag callback for
(domain, op_type).domain == ""is normalized toai.onnx.
-
inline const CustomValueTagFn *GetCustomValueTagFunction(const std::string &domain, const std::string &op_type) const#
Returns a pointer to the custom value-tag callback registered for
(domain, op_type), ornullptrif none is registered.
-
inline bool RemoveCustomValueTagFunction(const std::string &domain, const std::string &op_type)#
Removes the custom value-tag callback registered for
(domain, op_type).
-
inline void ClearCustomValueTagFunctions()#
Removes every custom value-tag callback.
-
inline const CustomValueTagMap &CustomValueTagFunctions() const noexcept#
Read-only access to all registered custom value-tag callbacks.
-
void ComputeInPlaceReuseGraph(const GraphProto &graph, const ShapesContext &ctx, bool allow_input_overwrite = false, const std::unordered_map<std::string, std::string> &value_tags = {})#
Guesses, for every node of
graph, which outputs may reuse which input buffers in place, using the shapes and element types already inferred intoctx, and stores the result in*this(replacing any previously computed result).- Parameters:
graph – Graph whose nodes are analysed, in topological order.
ctx – Shapes context already populated with the inferred descriptors for
graph(graph inputs, initializers, intermediates and outputs).allow_input_overwrite – When
false(the default), declared graph inputs are never offered as reusable buffers, so a caller’s input is never overwritten in place. Whentrue, a declared graph input may be reused like an intermediate (subject to the same lifetime and shape checks), allowing kernels to overwrite it.value_tags – Optional map from value name to tag string (
"shape","axes","weight"). When non-empty, values in the release list that carry the"shape"tag are also stored separately and exposed through :cpp:func:ReleaseAfterShapeTagged/ :cpp:func:NodeReleaseAfterShapeTagged, and written to :cpp:var:kReleaseAfterShapeTagMetadataKeyby :cpp:func:WriteToMetadata.
-
void SeedReuseInput(const std::string &name, bool is_graph_input, bool is_initializer, bool allow_input_overwrite)#
Seeds the incremental in-place-reuse lifetime state for a declared graph input (
is_graph_input) or initializer (is_initializer). Whenallow_input_overwriteisfalsethe value is protected (kept) from reuse; whentruea graph input is instead made available before the first node (producer index-1) so it can be reused at its last use. Mirrors the seeding performed whole-graph by :cpp:func:ComputeResultLifetimeInfo.
-
void SeedReuseOutput(const std::string &name)#
Seeds the incremental in-place-reuse lifetime state for a declared graph output: the value is kept alive and removed from the release / not-used lists of any earlier node that had treated it as releasable.
-
void AppendNodeReuse(const NodeProto &node, std::size_t node_index, const ShapesContext &ctx)#
Incrementally updates the in-place reuse and release-after annotations after the node
nodeatnode_indexhas been appended, using the shapes already inferred intoctx. Only this node and the previous last-users of its inputs are touched — no whole-graph loop — via :cpp:func:ComputeSingleNodeReuse. Appends exactly one entry to each of the per-node result vectors so they stay aligned with :cpp:func:Size.
-
inline std::size_t Size() const noexcept#
Number of nodes for which reuse has been computed (one entry per node of the analysed graph, in
graph.node()order). Zero before :cpp:func:ComputeInPlaceReuseGraphhas been called.
-
inline bool Empty() const noexcept#
truewhen no reuse has been computed yet.
-
inline const std::vector<std::vector<InPlaceReuse>> &Reuse() const noexcept#
Read-only access to the per-node reuse opportunities. Entry
ilists the opportunities discovered forgraph.node()[i]; nodes without any opportunity carry an empty list.
-
inline const std::vector<InPlaceReuse> &NodeReuse(std::size_t node_index) const#
Reuse opportunities discovered for the node at
node_index.- Throws:
std::out_of_range – when
node_indexis out of bounds.
-
inline const std::vector<std::vector<std::string>> &ReleaseAfterShapeTagged() const noexcept#
Read-only access to the per-node shape-tagged releasable values. When :cpp:func:
ComputeInPlaceReuseGraphwas called with a non-emptyvalue_tagsmap, this vector has one entry per node (same order asgraph.node()), and entryilists the names from therelease_afterlist that carry the"shape"value tag. WhenComputeInPlaceReuseGraphwas called withoutvalue_tags(or with an empty map), this vector is itself empty.
-
inline const std::vector<std::string> &NodeReleaseAfterShapeTagged(std::size_t node_index) const#
Shape-tagged releasable values for the node at
node_index.- Throws:
std::out_of_range – when
node_indexis out of bounds, or when :cpp:func:ComputeInPlaceReuseGraphwas called without value tags (in which case the vector is empty and every access is out of bounds).
-
inline const std::vector<NodeMemoryProfile> &Memory() const noexcept#
Read-only access to the per-node memory snapshots. Entry
idescribes the memory footprint observed while runninggraph.node()[i].
-
inline const NodeMemoryProfile &NodeMemory(std::size_t node_index) const#
Memory snapshot for the node at
node_index.- Throws:
std::out_of_range – when
node_indexis out of bounds.
-
const ShapesContext &ComputeShapes(const GraphProto &graph)#
Runs shape inference on
graphand stores the resulting descriptors in the :cpp:class:ShapesContextowned by*this.- Parameters:
graph – Graph whose nodes are analysed, in topological order.
- Returns:
A reference to the owned :cpp:class:
ShapesContext, now populated.
-
const ShapesContext &ComputeShapes(const ModelProto &model, bool prefill_with_value_info_output = false)#
Runs shape inference on
model.graph()(also recording opset versions and local functions frommodel) and stores the resulting descriptors in the :cpp:class:ShapesContextowned by*this.- Parameters:
model – Model whose main graph is analysed.
prefill_with_value_info_output – Forwarded to :cpp:func:
ShapesContext::ComputeShapeModel.
- Returns:
A reference to the owned :cpp:class:
ShapesContext, now populated.
-
const ShapesContext &ComputeShapes(const FunctionProto &function, const InputShapes &input_shapes = {})#
Runs shape inference on the body of
functionand stores the resulting descriptors in the :cpp:class:ShapesContextowned by*this.A :cpp:class:
FunctionProtoonly names its inputs, so their shapes and element types must be supplied throughinput_shapes. Any input consumed by a node but absent frominput_shapes(and not produced by an earlier node) makes shape inference throwstd::invalid_argument.- Parameters:
function – Function whose nodes are analysed, in topological order.
input_shapes – Shapes/types for the function inputs, seeded into the owned :cpp:class:
ShapesContextbefore inference.
- Returns:
A reference to the owned :cpp:class:
ShapesContext, now populated.
-
const ShapesContext &ComputeShapes(const utils::RepeatedProtoField<NodeProto> &nodes, const InputShapes &input_shapes = {})#
Runs shape inference on the node list
nodesand stores the resulting descriptors in the :cpp:class:ShapesContextowned by*this.A bare node list has no declared inputs, so the shapes and element types of every value not produced by the list itself must be supplied through
input_shapes. Any input consumed by a node but absent frominput_shapes(and not produced by an earlier node) makes shape inference throwstd::invalid_argument.- Parameters:
nodes – Nodes analysed in topological order.
input_shapes – Shapes/types for the values consumed by
nodesbut not produced by them, seeded into the owned :cpp:class:ShapesContextbefore inference.
- Returns:
A reference to the owned :cpp:class:
ShapesContext, now populated.
-
inline const ShapesContext &Shapes() const noexcept#
Read-only access to the :cpp:class:
ShapesContextowned by*this. Empty until :cpp:func:ComputeShapes(or :cpp:func:Compute) has run.
-
inline ShapesContext &Shapes() noexcept#
Mutable access to the owned :cpp:class:
ShapesContext, allowing callers to seed it (opset versions, custom inference functions, …) before :cpp:func:ComputeShapes.
-
const std::vector<int64_t> &ComputePeakMemory(const GraphProto &graph, Device device = Device::kUndefined)#
Computes the estimated peak scratch memory for every node of
graphusing the shapes already inferred into the owned :cpp:class:ShapesContext(via :cpp:func:ComputeShapes), storing one entry per node ingraph.node()order. Nodes whose estimate is zero keep a0entry.- Parameters:
graph – Graph whose nodes are analysed, in topological order.
device – Logical device passed to the peak-memory dispatch function.
- Returns:
A reference to the stored per-node peak-memory vector.
-
inline const std::vector<int64_t> &PeakMemory() const noexcept#
Read-only access to the per-node peak-memory estimates computed by :cpp:func:
ComputePeakMemory. Empty before it has been called.
-
inline int64_t NodePeakMemory(std::size_t node_index) const#
Peak-memory estimate for the node at
node_index.- Throws:
std::out_of_range – when
node_indexis out of bounds.
-
void Compute(const GraphProto &graph, Device device = Device::kUndefined, bool allow_input_overwrite = false)#
Runs every analysis on
graphin order and stores all results in*this: shape inference (:cpp:func:ComputeShapes), value / node tagging (:cpp:func:ComputeValueAndNodeTags), in-place reuse together with the release-after and shape-tag classification (:cpp:func:ComputeInPlaceReuseGraph) and per-node peak memory (:cpp:func:ComputePeakMemory).- Parameters:
graph – Graph whose nodes are analysed, in topological order.
device – Logical device passed to the peak-memory dispatch function.
allow_input_overwrite – Forwarded to :cpp:func:
ComputeInPlaceReuseGraph.
-
void Compute(const ModelProto &model, Device device = Device::kUndefined, bool allow_input_overwrite = false, bool prefill_with_value_info_output = false)#
Same as :cpp:func:
Compute(const GraphProto&, ...)but seeds shape inference frommodel(opset versions and local functions) before analysingmodel.graph().
-
void WriteToGraph(GraphProto &graph) const#
Pushes every computed result into
graph: the inferred shapes are written intograph(value_info / outputs, via :cpp:func:ShapesContext::ApplyInferredShapesToGraph), the in-place / release / shape-tag information into nodemetadata_props(via :cpp:func:WriteToMetadata) and the per-node peak-memory estimates under :cpp:var:kNodePeakMemoryMetadataKey.- Parameters:
graph – Graph whose value_info and node metadata are mutated in place; must be the same graph passed to :cpp:func:
Compute/ :cpp:func:ComputeInPlaceReuseGraph.
-
void WriteToModel(ModelProto &model) const#
Same as :cpp:func:
WriteToGraph(GraphProto&)applied tomodel.graph().
-
runtime::ExecutionPlan BuildExecutionPlan(GraphProto &graph) const#
Creates the :cpp:class:
runtime::ExecutionPlanderived from every result stored in*this. It first pushes the information intograph(see :cpp:func:WriteToGraph) and then builds the plan from the annotated graph, so the schedule is driven entirely by the analyses held by this context.
-
runtime::ExecutionPlan BuildExecutionPlan(ModelProto &model) const#
Same as :cpp:func:
BuildExecutionPlan(GraphProto&, ...)applied tomodel.graph().
-
inline void set_events_enabled(bool enabled) noexcept#
-
inline bool events_enabled() const noexcept#
-
inline const ComputeEventLog &Events() const noexcept#
Append-only log of decisions made by :cpp:func:
ComputeInPlaceReuseGraph.
-
inline ComputeEventLog &Events() noexcept#
-
inline void ClearEvents() noexcept#
Empties the decision log without touching computed results.
-
void WriteToMetadata(GraphProto &graph) const#
Records the computed opportunities into each node’s
metadata_propsofgraphunder :cpp:var:kInPlaceReuseMetadataKey, :cpp:var:kReleaseAfterMetadataKey, :cpp:var:kNotUsedAfterMetadataKey, and (when :cpp:func:ComputeInPlaceReuseGraphwas called with value tags) :cpp:var:kReleaseAfterShapeTagMetadataKey.For every node that has at least one in-place opportunity, a single metadata entry is added (or updated in place if the key already exists) whose value lists the opportunities as
output_index:input_index:kindtriplets separated by;(kindbeingequalorgreater).For every node that has releasable last-use inputs, one metadata entry is added (or updated in place) under :cpp:var:
kReleaseAfterMetadataKey; the value is a;-separated list of releasable names.For every node that has declared graph inputs / initializers reaching their last use, one metadata entry is added (or updated in place) under :cpp:var:
kNotUsedAfterMetadataKey; the value is a;-separated list of those names.When shape-tag information was provided to :cpp:func:
ComputeInPlaceReuseGraph, a further metadata entry is added under :cpp:var:kReleaseAfterShapeTagMetadataKeyfor every node that has at least one shape-tagged releasable value; the value is a;-separated list of those names.Nodes without in-place opportunities, without releasable names, and without last-use input/initializer names are left untouched.
graphmust be the same graph passed to :cpp:func:ComputeInPlaceReuseGraph, so that node indices line up with the stored result.
-
inline void Clear() noexcept#
Empties the stored result.
Private Members
-
std::vector<ConstantInfo> node_constant_#
-
bool custom_value_tags_changed_ = false#
-
CustomValueTagMap custom_value_tags_#
-
std::vector<std::vector<InPlaceReuse>> reuse_#
-
std::vector<NodeMemoryProfile> memory_#
-
ShapesContext shapes_#
-
ComputeEventLog events_#
-
bool events_enabled_ = false#
-
expressions::SimplifiedExpressionCache incr_simplified_dim_cache_#
-
using CustomValueTagFn = std::function<void(ComputeContext&, const NodeProto&, std::size_t node_index)>#
-
struct ComputeEvent#
- #include <compute_context.h>
One entry of the optional :cpp:class:
ComputeContextdecision log.Public Members
-
ComputeEventAction action = ComputeEventAction::kInPlace#
Decision kind.
-
int64_t output_index = -1#
Output index for
kInPlacedecisions;-1otherwise.
-
int64_t input_index = -1#
Input index for
kInPlacedecisions;-1otherwise.
-
InPlaceReuseKind kind = InPlaceReuseKind::kEqual#
Match kind for
kInPlacedecisions.
-
ComputeEventAction action = ComputeEventAction::kInPlace#
-
using ComputeEventLog = std::vector<ComputeEvent>#
-
namespace compute#
-
namespace core