The four PyTorch primitives you actually use
- Tensor — n-dimensional array on a device, with a dtype, shape, and optional gradient tracking. The atomic unit.
- Module — a stateful piece of the network that holds parameters and defines a forward pass. Composed via attributes (
self.conv = nn.Conv2d(...)) and discovered automatically bystate_dict()andparameters(). - Optimizer — knows about a list of parameters and updates them given their gradients.
- Autograd engine — builds a computation graph during forward, walks it backward to compute gradients.
Every PyTorch program you read is one of: defining a Module, putting tensors through it, computing a scalar loss, calling .backward(), calling opt.step(). Once you internalize that loop, the rest is library knowledge.
Modules compose like Lego
A Module can contain other Modules. state_dict() recursively flattens all parameters, to(device) recursively moves them. The hierarchy is the API — you don't have to register parameters manually as long as you assign them as attributes.
The 2026 torch.compile detail
Wrap any Module in torch.compile(model) and PyTorch traces the forward pass into a fused graph that runs significantly faster on modern accelerators. First call is slower (compilation); subsequent calls are 1.3-3x faster. Pure win on CUDA; smaller win on CPU/MPS.