Thread-local op recorder consumed by OpScopeFull.
Constructing a Tracer is cheap — the underlying TraceGraph
starts empty. Hooks fire only between set_current_tracer
(this) and set_current_tracer (nullptr); outside that
window the tracer accumulates nothing.
Attributes
graph_TraceGraphon_op_enter and exposed read-only via graph.Notes
Non-copyable, non-movable — the active-tracer slot is a raw pointer owned by the caller; copying or moving the Tracer would either invalidate that pointer or duplicate the recording sink.
Examples
Native usage (Python binding mirrors this): Tracer t;
set_current_tracer(&t);
// ... run a forward pass — every OpScopeFull ctor records ...
set_current_tracer(nullptr);
const auto& g = t.graph(); // inspect recorded nodesConstructors
1Operators
1Methods
5Returns the id → external TensorImplPtr map populated by on_op_io when an input wasn't produced by any earlier traced op. The builder uses this to materialise an MPSGraph placeholder per external feed and to bind the corresponding input data at execution time.
The Tracer holds an owning TensorImplPtr for every
external feed so the underlying buffers cannot be released
mid-trace.
const TraceGraph & graph()Returns a read-only reference to the recorded graph.
Returns
const TraceGraph&The op DAG accumulated so far. Caller must not access this reference after the Tracer is destroyed or a subsequent on_op_enter invalidates iterators into ops.
Attach a single attribute to the most recently recorded OpNode. Used by op forwards via OpScopeFull::set_attr to thread payloads (permutation, axis, stride, padding, …) that the emitter would otherwise be unable to recover from inputs + output shapes alone.
Parameters
keystd::string_view"permutation", "stride", "padding", "axis", "keepdim", "eps", …).valueAttributeValueNotes
Calling this with an empty TraceGraph (no preceding
on_op_enter) is a no-op — defensive against ordering
mistakes at hook sites. Overwrites any prior value under
key on the same node, so duplicate calls report the last
value (matches unordered_map semantics).
Records the entry of a new op into the active scope.
Parameters
namestd::string_viewOpScopeFull. Copied into the resulting OpNode::name.deviceDeviceTensorMeta appended to outputs.dtypeDtypeshapeShapeTensorMeta.Notes
Phase 1.1 appends one OpNode per call with an empty
inputs vector and a single-element outputs vector.
Phase 1.2 backfills inputs from the autograd wiring site
and may append additional outputs for multi-output ops.
Wires the input/output TensorImpl identities of the most recently recorded OpNode into the trace IR.
Parameters
inputsconst std::vector<TensorImplPtr>&nullptr slots (e.g. an optional bias) are passed through as -1 in the resulting OpNode::inputs``. The Tracer retains a strong reference to every external feed (input not produced by an earlier traced op) so the MpsBuilder` can read its shape/dtype + the run path can bind its data buffer.outputconst TensorImplPtr&on_op_enter (stored in node.outputs[0].id) is associated with this pointer in the internal map so subsequent ops that consume this tensor can resolve it back to the same id. Only the raw pointer is kept (no strong ref) — the output's lifetime is the caller's responsibility.Notes
Phase 1.1 wires only kernel families that go through
kernel::NaryKernel or kernel::VariadicKernel's
wire_autograd boundary (Conv / Linear / BatchNorm / Norm /
Loss / …). Ops dispatched through UnaryKernel or
BinaryKernel's in-line forward() reach
on_op_enter but skip this step — their inputs slot
stays empty, marking the node "pending" for the Phase 1.2
builder, which then routes that signature to the eager path.
Calling this with an empty TraceGraph (no preceding
on_op_enter) is a no-op — defensive against ordering
mistakes at hook sites.