tensorflow/tensorflow
Eager execution
The default execution mode in TensorFlow 2. Each op runs immediately on the device, returning an EagerTensor. Eager runtime lives in tensorflow/core/common_runtime/eager/ (C++) and tensorflow/python/eager/ (Python).
Purpose
- Run a TF op as soon as it's called, without building a graph first.
- Match NumPy ergonomics: tensors have values, you can
printthem, you can use Python control flow. - Co-exist with graph mode via
@tf.function, which traces eager calls into aFuncGraph.
Directory layout
tensorflow/core/common_runtime/eager/
├── context.{h,cc} # EagerContext: the per-process eager state
├── execute.{h,cc} # ExecuteOp: dispatch a single op
├── kernel_and_device.{h,cc} # Cached (kernel, device) for an op invocation
├── eager_operation.{h,cc} # EagerOperation: builder for one op call
├── tensor_handle.{h,cc} # Handle to an eager tensor (may be local or remote)
├── execute_node.{h,cc} # Async execution unit
├── core.{h,cc}, core_tensor_handle.{h,cc}
└── ...
tensorflow/python/eager/
├── context.py # tf.config.* and EagerContext binding
├── def_function.py # tf.function (older path; mostly forwards to polymorphic_function)
├── polymorphic_function/ # The new tf.function implementation
├── function.py
├── execute.py # Calls into tfe_wrapper.cc
├── tape.py # GradientTape
├── pywrap_tensor.py
└── ...Key abstractions
| Type | File | Description |
|---|---|---|
EagerContext |
tensorflow/core/common_runtime/eager/context.h |
Per-process eager state: device list, function library, executors. |
EagerOperation |
tensorflow/core/common_runtime/eager/eager_operation.h |
Builder for one op call: name, attrs, input handles. |
TensorHandle |
tensorflow/core/common_runtime/eager/tensor_handle.h |
Handle to an eager tensor (local CPU/GPU or remote). |
KernelAndDevice |
tensorflow/core/common_runtime/eager/kernel_and_device.h |
Cached resolved kernel for (op, device, input dtypes). |
EagerExecutor |
tensorflow/core/common_runtime/eager/eager_executor.h |
Per-thread async queue. |
tape.GradientTape |
tensorflow/python/eager/tape.py |
Records ops for backprop. |
tf.function |
tensorflow/python/eager/polymorphic_function/ |
Traces a Python function into a FuncGraph. |
How a single eager op runs
sequenceDiagram
participant Py as Python: tf.add(a, b)
participant Gen as gen_math_ops.add
participant Pybind as tfe_wrapper.cc
participant Ctx as EagerContext
participant KAD as KernelAndDevice cache
participant Kernel as MatMulOp / AddOp / ... (OpKernel)
Py->>Gen: gen_math_ops.add(a, b)
Gen->>Pybind: TFE_Py_FastPathExecute("Add", ...)
Pybind->>Ctx: Execute EagerOperation("Add", inputs)
Ctx->>KAD: Look up cached (kernel, device)
KAD-->>Ctx: cached entry
Ctx->>Kernel: Compute(OpKernelContext)
Kernel-->>Ctx: outputs (TensorHandle)
Ctx-->>Py: EagerTensor wrapping the handleThe KernelAndDevice cache is critical for performance: each (op_name, dtypes, attrs, device) combo gets resolved once to a kernel pointer; subsequent calls bypass the registry lookup.
tf.function and eager interoperate
tf.function (tensorflow/python/eager/polymorphic_function/) traces a Python function by calling it with symbolic Tensors. Every op call inside the trace adds a node to a FuncGraph instead of executing. The traced graph is registered in the EagerContext's function library and called like any other op:
@tf.function
def f(x):
return x * x + 1
f(2.0) # First call: traces and runs
f(3.0) # Second call: re-uses the traced graph (same input signature)
f(tf.zeros([3])) # New signature: re-tracesThe polymorphic-function machinery is responsible for caching ConcreteFunctions by input signature, handling captured variables, and wiring up the AutoGraph source rewriter (see features/tf-function-and-autograph).
Gradients via tape
tf.GradientTape (tensorflow/python/eager/tape.py + tensorflow/python/eager/backprop.py) records every op + inputs/outputs in a thread-local stack while it's "watching." On tape.gradient(loss, vars) it walks the recorded graph backwards, looking up gradient functions in @RegisterGradient and applying them.
Async execution
EagerExecutor provides asynchronous mode: ops are enqueued and run on a background thread. Errors flow back as deferred status. Most production code uses sync mode; the async mode is occasionally used for overlapping host work with GPU compute.
Remote eager
TensorHandle can be a remote handle (tensorflow/core/common_runtime/eager/remote_tensor_handle_data.{h,cc}). The eager runtime can transparently send/receive across hosts via RemoteEagerExecute RPCs (tensorflow/core/distributed_runtime/eager/). This underlies multi-host eager and TPU eager execution.
Integration points
- Python frontend:
tensorflow/python/eager/andtfe_wrapper.cc. Almost every public op call goes through here. - Function library:
EagerContext::FuncLibDef— the place wheretf.function-traced graphs live. - Distributed:
tensorflow/core/distributed_runtime/eager/andtensorflow/python/distribute/. - Gradient tape:
tensorflow/python/eager/tape.py.
Entry points for modification
- Eager op dispatch —
tensorflow/core/common_runtime/eager/execute.cc. - New tape behaviour —
tensorflow/python/eager/tape.pyandbackprop.py. tf.functionsemantics —tensorflow/python/eager/polymorphic_function/.- New eager extension (e.g. dtype, device) — generally requires both new kernel registrations and updates to
EagerContext::FindFunctionByName/ device list.
Related
- core-runtime — the kernel/device machinery eager reuses.
- features/tf-function-and-autograph — how Python control flow and tracing layer on top.
- distributed-runtime — remote eager.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.