When the built-in ops aren't enough
For 99% of model code, the built-in differentiable operations are all you need — autograd composes their derivatives via chain rule, and you never write a backward by hand. The remaining 1% is where you reach for torch.autograd.Function:
- You're implementing an op whose forward isn't built from existing differentiable ops (e.g. you wrote a custom CUDA kernel).
- You want to redefine the gradient (the straight-through estimator, used in quantization-aware training and discrete-output models, is the textbook example).
- You want to save memory by recomputing instead of storing — though for that,
torch.utils.checkpointis usually a better fit.
The contract
A custom Function has two static methods:
forward(ctx, *inputs)— runs the forward computation. Usectx.save_for_backward(...)to stash anything backward will need.backward(ctx, *grad_outputs)— runs the backward computation. Returns one gradient per input to forward (or None for inputs that don't require grad).
You don't call forward or backward directly — you call MyFunction.apply(...), which sets up the graph node properly.