Open-Source Wikis

/

PyTorch

/

Systems

/

c10

pytorch/pytorch

c10

Active contributors: ezyang, malfet

Purpose

c10/ is PyTorch's lowest-level core: header-only and .cpp files defining the fundamental types every other layer uses — Tensor, Storage, TensorImpl, allocators, dispatch keys, devices, scalar types, and a small number of utilities like c10::SmallVector, c10::ArrayRef, and c10::optional (now a re-export of std::optional). The name comes from "Caffe2 Core 10" — c10 was extracted as the merger glue between Caffe2 and ATen, and survived the deprecation of the rest of Caffe2.

c10 exists so that ATen and Caffe2 historically (and now ATen, the dispatcher, and the JIT) could share the same Tensor plumbing. It deliberately has no dependencies on ATen.

Directory layout

Path Contents
c10/core/ TensorImpl, Storage, Allocator, Device, ScalarType, DispatchKey, DispatchKeySet, Layout
c10/util/ SmallVector, ArrayRef, intrusive_ptr, Logging, Exception, Half/BFloat16/Float8 types
c10/macros/ Compiler/platform macros, export annotations
c10/cuda/ CUDA-specific shared facilities: CUDACachingAllocator, CUDAStream, CUDAGuard
c10/hip/ ROCm/HIP equivalents (mostly mirrors c10/cuda/)
c10/xpu/ Intel XPU shared facilities
c10/metal/ Apple MPS / Metal shared facilities
c10/mobile/ Mobile-specific bits (PyTorch Mobile uses a stripped c10)
c10/test/ Unit tests for c10 internals
c10/benchmark/ Microbenchmarks for c10 hot paths

The README at c10/README.md is short — c10 documents itself by header.

Key abstractions

Type File Purpose
c10::TensorImpl c10/core/TensorImpl.h The actual tensor object: shape, strides, storage_offset, dtype, device, keyset
c10::Storage / StorageImpl c10/core/Storage.h, StorageImpl.h Reference-counted device memory wrapper
c10::Allocator c10/core/Allocator.h Per-device allocator interface
c10::Device c10/core/Device.h (DeviceType, DeviceIndex) pair
c10::DispatchKey c10/core/DispatchKey.h Enum of all dispatch keys
c10::DispatchKeySet c10/core/DispatchKeySet.h Bitmap of dispatch keys
c10::ScalarType c10/core/ScalarType.h dtype enum + traits
c10::Scalar c10/core/Scalar.h Type-erased scalar (int / double / complex / bool)
c10::SymInt, c10::SymBool c10/core/SymInt.h, SymBool.h Symbolic integer/bool used by dynamic shapes
c10::intrusive_ptr<T> c10/util/intrusive_ptr.h Reference counting smart pointer, used for everything
c10::cuda::CUDACachingAllocator c10/cuda/CUDACachingAllocator.h The well-known caching allocator that every CUDA tensor allocates from

How it works

c10 is mostly a headers + traits library; the action happens elsewhere. There are two structural ideas worth understanding.

Intrusive reference counting

Almost every shared type in c10 (TensorImpl, StorageImpl, Generator, FunctionSchema, OperatorEntry, …) is held via c10::intrusive_ptr<T>. The refcount lives inside the object instead of in a control block (as std::shared_ptr would). This saves an allocation and one indirection on every refcount bump — meaningful given that millions of tensors and storages exist at runtime.

intrusive_ptr requires the held type to inherit from c10::intrusive_ptr_target. Tensor (the user-facing C++ type in ATen) is itself just an intrusive_ptr<TensorImpl> with a richer API. See aten/src/ATen/templates/TensorBody.h for the wrapper.

DispatchKeySet on every tensor

Each TensorImpl carries a DispatchKeySet (c10/core/DispatchKeySet.h). At op call time, the dispatcher takes the union of (input tensors' keysets, ambient TLS keysets) and selects the highest-priority key with a registered kernel. The whole compiler stack, autograd, autocast, vmap, and functionalization plug into the system by registering kernels for specific dispatch keys; see Dispatcher.

Caching allocator

c10::cuda::CUDACachingAllocator (c10/cuda/CUDACachingAllocator.cpp is ~5K lines) is the centerpiece of CUDA memory management. It holds onto freed blocks in size-bucketed pools rather than calling cudaFree, which would synchronize the device. This is also where features like expandable_segments, memory snapshots, allocator hooks, and the OOM debugging APIs live. The allocator is configurable via PYTORCH_CUDA_ALLOC_CONF.

Integration points

  • Upwards into ATen. Every header under aten/src/ATen/ includes pieces of c10 (Tensor.h, Scalar.h, Device.h, …).
  • Upwards into the dispatcher. c10/core/DispatchKey.h and DispatchKeySet.h are the foundation of aten/src/ATen/core/dispatch/Dispatcher.h.
  • Sideways into backends. c10/cuda/, c10/hip/, c10/xpu/, c10/metal/ are the per-device runtime helpers (streams, events, guards, allocators) shared by both ATen kernels and Python bindings.
  • Mobile build. c10/mobile/ is selectively included in the mobile build; the rest of c10 is small enough that it survives mobile linking.

Entry points for modification

If you need a new dispatch key, edit c10/core/DispatchKey.h and update the priority ordering in DispatchKeySet.cpp. If you need a new dtype, edit c10/core/ScalarType.h and the helpers in c10/util/Half.h (or add a new Float8_* header alongside the existing ones). For allocator behaviour changes the surface is c10/cuda/CUDACachingAllocator.cpp.

c10 is intentionally conservative — most contributors should not need to touch it. When you do, expect to update many call sites in ATen and the generated code under aten/src/ATen/Operators_*.cpp.

Key source files

File Purpose
c10/core/TensorImpl.h The actual tensor object
c10/core/Storage.h Reference-counted memory wrapper
c10/core/DispatchKey.h Enum of dispatch keys
c10/core/DispatchKeySet.h KeySet bitmap
c10/core/Allocator.h Allocator interface
c10/core/ScalarType.h Dtype enum and traits
c10/core/SymInt.h Symbolic integer for dynamic shapes
c10/util/intrusive_ptr.h Refcount smart pointer
c10/cuda/CUDACachingAllocator.cpp CUDA caching allocator
c10/cuda/CUDAStream.h CUDA stream wrapper
c10/macros/Macros.h Cross-platform macros

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

c10 – PyTorch wiki | Factory