pytorch/pytorch
ATen
Active contributors: ezyang, mruberry, albanD
Purpose
ATen ("A Tensor Library") is the C++ tensor library that exposes everything torch.* does at the math level. It owns the operator definitions, the dispatcher, the in-tree native kernels, and the per-backend specializations. If you call a + b in Python, the Python binding eventually calls at::add(a, b) from ATen.
ATen lives at aten/src/ATen/. The namespace is at::.
Directory layout
| Path | Contents |
|---|---|
aten/src/ATen/ |
Public ATen headers and core sources |
aten/src/ATen/core/ |
The dispatcher, op registry, schema parser, IValue, Library |
aten/src/ATen/native/ |
The vast majority of CPU op implementations (and a few cross-cutting ones) |
aten/src/ATen/native/native_functions.yaml |
The op registry — the single source of truth for op schemas |
aten/src/ATen/native/cpu/ |
Vectorized CPU kernels (AVX2, AVX512, NEON, …) |
aten/src/ATen/native/cuda/ |
CUDA kernels |
aten/src/ATen/native/cudnn/ |
cuDNN bindings (convolutions, RNNs) |
aten/src/ATen/native/mkldnn/ |
oneDNN/MKL-DNN integration |
aten/src/ATen/native/mps/ |
Apple Metal Performance Shaders kernels |
aten/src/ATen/native/xpu/ |
Intel XPU stubs (real kernels live in intel-xpu submodule) |
aten/src/ATen/native/sparse/ |
Sparse tensor ops |
aten/src/ATen/native/quantized/ |
Quantized ops |
aten/src/ATen/native/nested/ |
Nested tensor ops |
aten/src/ATen/cuda/ |
CUDA runtime helpers (Blas, Solver, etc.) shared across kernels |
aten/src/ATen/templates/ |
Mustache templates that torchgen renders |
aten/src/ATen/test/ |
Gtest-based C++ unit tests |
The directory is roughly 21K files and far too large to itemize.
Key abstractions
| Type | File | Purpose |
|---|---|---|
at::Tensor |
aten/src/ATen/templates/TensorBody.h |
Public C++ tensor type (intrusive_ptr |
at::TensorIterator |
aten/src/ATen/TensorIterator.h |
The shared loop driver for elementwise/reduction ops |
at::Context |
aten/src/ATen/Context.h |
Global context: backend toggles, deterministic mode, BLAS choice |
c10::Dispatcher |
aten/src/ATen/core/dispatch/Dispatcher.h |
The op routing table |
at::OperatorHandle |
aten/src/ATen/core/dispatch/Dispatcher.h |
Handle to a registered operator |
c10::FunctionSchema |
aten/src/ATen/core/function_schema.h |
Parsed op schema |
at::native::* |
aten/src/ATen/native/ |
Where most leaf op CPU implementations live |
at::AutogradMeta |
aten/src/ATen/core/Variable.h |
Per-tensor autograd metadata (grad_fn, hooks, version counter) |
The Context singleton (at::globalContext()) holds toggles like userEnabledCuDNN(), deterministicAlgorithms(), blasPreferredBackend(), etc.; this is the C++ side of torch.backends.*.
How it works
ATen has three logical pieces: the dispatcher (covered in Dispatcher), the op declaration system (in native_functions.yaml and core/), and the kernel implementations (native/).
Op declaration
Every operator is described by a YAML entry like:
- func: add.Tensor(Tensor self, Tensor other, *, Scalar alpha=1) -> Tensor
device_check: NoCheck
structured_delegate: add.out
variants: function, method
dispatch:
SparseCPU, SparseCUDA: add_sparse
SparseCsrCPU, SparseCsrCUDA: add_sparse_csr
MkldnnCPU: mkldnn_add
ZeroTensor: add_zerotensor
tags: [pointwise, canonical]Reading top-down: the schema, behavioural flags, the structured "delegate" that sub-kernels share, where it appears (function and/or method), the per-key dispatch table, and tags. torchgen consumes these and emits:
- a header in
build/aten/src/ATen/Operators.hdeclaringat::add(...); - generated registrations in
RegisterCPU.cpp,RegisterCUDA.cpp, etc. that wire eachdispatch:entry into the dispatcher; - generated stubs for autograd's
derivatives.yamlentries.
For "structured" kernels (the modern style for elementwise ops), torchgen also emits a meta function (shape inference) and an iter-driven base; the kernel author only writes the inner loop. See aten/src/ATen/native/README.md for the canonical guide.
TensorIterator
TensorIterator (TensorIterator.h/.cpp, ~100K lines combined) is the heart of pointwise and reduction kernels. It computes broadcasting, dtype promotion, output allocation, and an iteration order that yields contiguous strided loops. CPU and CUDA both build a TensorIterator and then call vectorised loops on it; the bulk of CPU kernels in aten/src/ATen/native/cpu/*Kernel.cpp are short loops over an iter.
Op call sequence
A simplified eager-mode at::add(a, b):
sequenceDiagram
participant Caller
participant OpsH as Operators.h<br/>(generated)
participant Disp as Dispatcher
participant Reg as RegisterCUDA.cpp<br/>(generated)
participant Kernel as native::add_kernel_cuda
Caller->>OpsH: at::add(a, b)
OpsH->>Disp: redispatch using a.key_set() | b.key_set()
Disp->>Disp: pick highest-priority key with kernel
Disp->>Reg: jump to wrapper for AutogradCUDA / CUDA
Reg->>Kernel: native::add_kernel_cuda
Kernel-->>Caller: returns TensorBackend layering
aten/src/ATen/native/ is where almost all in-tree kernels live. Backend-specific kernels nest under cpu/, cuda/, mps/, cudnn/, mkldnn/, quantized/, sparse/, nested/, nnapi/, vulkan/. Files in aten/src/ATen/cuda/, aten/src/ATen/mps/, etc. provide runtime helpers (BLAS handles, kernel launch utilities) but not op kernels.
External backends (XLA, MTIA, lazy) register their own kernels through TORCH_LIBRARY_IMPL from out-of-tree code.
Integration points
- Generated code consumers.
Operators.h,Functions.h,RedispatchFunctions.h, theRegisterX.cppfiles, and Python bindings undertorch/csrc/autograd/generated/python_*.cppare all produced fromnative_functions.yaml. See torchgen. - Autograd. Forward kernels are wrapped by autograd's per-op codegen; see Autograd.
- Compile. AOT autograd traces through ATen ops symbolically (using FakeTensor); decompositions in
torch/_decomp/rewrite ATen ops in terms of simpler ops; see Tensor subclasses and AOT Autograd. - JIT / TorchScript. Reuses the same dispatcher and operator registry. JIT IR ops are ATen ops.
- C API stable.
torch/csrc/stable/exposes a small ABI-stable subset of ATen for out-of-tree extensions; see C API stable.
Entry points for modification
To add an op:
- Add a
func:entry inaten/src/ATen/native/native_functions.yamlwith a schema and dispatch table. - Implement the kernel(s) under
aten/src/ATen/native/. For CPU pointwise ops put the inner loop inaten/src/ATen/native/cpu/<your>Kernel.cppand a TensorIterator setup inaten/src/ATen/native/<your>.cpp. - If differentiable, add a derivative to
tools/autograd/derivatives.yaml. - Add a Python binding entry if you need a non-default name (otherwise it's automatic).
- Write tests in
test/test_ops.pyviaOpInfo(torch/testing/_internal/common_methods_invocations.py) to get the suite of correctness tests for free.
To change an existing op's behaviour, find its entry in native_functions.yaml, follow the dispatch: table to the implementation, and remember to update structured kernel meta functions if the shape rule changes.
Key source files
| File | Purpose |
|---|---|
aten/src/ATen/native/native_functions.yaml |
The op schema registry (single source of truth for ATen ops) |
aten/src/ATen/native/README.md |
Canonical guide to writing native functions |
aten/src/ATen/TensorIterator.h, TensorIterator.cpp |
Loop driver for elementwise/reduction ops |
aten/src/ATen/Context.h, Context.cpp |
Global toggles and backend selection |
aten/src/ATen/core/dispatch/Dispatcher.h |
The dispatcher |
aten/src/ATen/core/op_registration/op_registration.h |
Programmatic op registration |
aten/src/ATen/templates/TensorBody.h |
Public Tensor C++ class |
aten/src/ATen/FunctionalTensorWrapper.h |
Functionalization wrapper |
aten/src/ATen/autocast_mode.h |
Autocast (mixed-precision) dispatch |
aten/src/ATen/native/cuda/ |
CUDA kernels |
aten/src/ATen/native/cudnn/ |
cuDNN-backed convolutions, RNNs, attention |
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.