torch.foreach#
Created On: Aug 20, 2026 | Last Updated On: Aug 20, 2026
Operations over lists of tensors.
Warning
torch.foreach is a beta API. Its signatures may change based on user
feedback. Existing private torch._foreach_* functions remain available
for compatibility during migration.
Each function applies the corresponding ordinary PyTorch operation to every position in one or more tensor lists.
The functions will use an accelerated multi-tensor implementation when their inputs meet its requirements. Otherwise they use a semantically equivalent per-tensor fallback. Calling a function in this module does not guarantee a single or fused kernel.
torch.foreach applies familiar PyTorch operations across lists of tensors. For
example, torch.foreach.add(inputs, other) is semantically equivalent to a
Python loop that applies torch.add() at every list position. When
available on an accelerator and certain conditions are met, a foreach operation will use a horizontally fused multi-tensor kernel to improve
runtime. On CUDA, common eligibility requirements include strided,
non-overlapping dense tensors on the same device, compatible dtypes, and
matching sizes and strides for corresponding tensors.
inputs = [torch.ones(2), torch.ones(3)]
result = torch.foreach.add(inputs, 2)
# Equivalent to tuple(torch.add(tensor, 2) for tensor in inputs)
torch.foreach.mul_(inputs, 3)
# Mutates each tensor and returns `inputs`.
API Coverage#
A foreach API lifts an ordinary tensor operation over a list of inputs. This creates a combinatorial space of possible signatures. Depending on the operation, a tensor argument could be shared as a Tensor or supplied elementwise as a TensorList, while a scalar argument could be a Scalar, a ScalarList, a shared 0-D Tensor, or a packed 1-D CPU Tensor.
You can then imagine that one operation may take on various forms such as TensorList/TensorList, TensorList/Tensor, TensorList/ScalarList, TensorList/Scalar, etc. Operations with more parameters would have more combinations. The public foreach APIs support a subset of these combinations based on usage. If you would like to see an implementation of a missing combination, please file an issue!
Across the supported signatures, we maintain constraints that TensorList and ScalarList arguments must be non-empty, and corresponding tensor and scalar lists must have the same length.
Only signatures that explicitly list Tensor include it in the supported typed
surface. A 0-D Tensor that does not require gradients may sometimes be accepted
for a Scalar parameter through implicit scalar conversion. Converting an
accelerator Tensor this way reads its value on the host, which may be expensive. On CUDA, this synchronizes eager execution and is unsupported during CUDA graph capture, so it should not be relied upon as a Tensor overload.
The public foreach API also does not support out= variants and may have a higher memory footprint than looping through the non-foreach original API, as multiple intermediates can be alive simultaneously.
Migrating from the private API#
You may be familiar with the private spellings of foreach APIs, e.g., for torch.add():
torch._foreach_add(inputs, other) # Private spelling
torch.foreach.add(inputs, other) # Public beta spelling
The private spellings remain available with unchanged signatures for backward compatibility. Public functions call the same ATen operators but improve API consistency in two ways:
All required operands are positional-only, and all optional parameters are keyword-only.
Parameter names align with the corresponding ordinary operation.
The primary tensor-list argument that the foreach API applies over is named inputs, and other
arguments retain the ordinary operation’s logical name, even when the currently supported form
requires a list. This keeps signatures descriptive as operand forms evolve.
Unary operations#
abs |
Applies |
abs_ |
Applies |
acos |
Applies |
acos_ |
Applies |
asin |
Applies |
asin_ |
Applies |
atan |
Applies |
atan_ |
Applies |
ceil |
Applies |
ceil_ |
Applies |
clone |
Clones every tensor in |
cos |
Applies |
cos_ |
Applies |
cosh |
Applies |
cosh_ |
Applies |
erf |
Applies |
erf_ |
Applies |
erfc |
Applies |
erfc_ |
Applies |
exp |
Applies |
exp_ |
Applies |
expm1 |
Applies |
expm1_ |
Applies |
floor |
Applies |
floor_ |
Applies |
frac |
Applies |
frac_ |
Applies |
lgamma |
Applies |
lgamma_ |
Applies |
log |
Applies |
log_ |
Applies |
log10 |
Applies |
log10_ |
Applies |
log1p |
Applies |
log1p_ |
Applies |
log2 |
Applies |
log2_ |
Applies |
neg |
Applies |
neg_ |
Applies |
reciprocal |
Applies |
reciprocal_ |
Applies |
round |
Applies |
round_ |
Applies |
rsqrt |
Applies |
rsqrt_ |
Applies |
sigmoid |
Applies |
sigmoid_ |
Applies |
sign |
Applies |
sign_ |
Applies |
sin |
Applies |
sin_ |
Applies |
sinh |
Applies |
sinh_ |
Applies |
sqrt |
Applies |
sqrt_ |
Applies |
tan |
Applies |
tan_ |
Applies |
tanh |
Applies |
tanh_ |
Applies |
trunc |
Applies |
trunc_ |
Applies |
zero_ |
Fills every tensor in |
Binary operations#
add |
Applies |
add_ |
Applies |
sub |
Applies |
sub_ |
Applies |
mul |
Applies |
mul_ |
Applies |
div |
Applies |
div_ |
Applies |
clamp_min |
Applies |
clamp_min_ |
Applies |
clamp_max |
Applies |
clamp_max_ |
Applies |
minimum |
Applies |
minimum_ |
Applies |
maximum |
Applies |
maximum_ |
Applies |
pow |
Applies |
pow_ |
In-place version of |
copy_ |
Copies each tensor in |
Pointwise operations#
addcmul |
Applies |
addcmul_ |
Applies |
addcdiv |
Applies |
addcdiv_ |
Applies |
lerp |
Applies |
lerp_ |
In-place version of |
Reductions and matrix operations#
max |
Returns the maximum value of each tensor in |
norm |
Returns the vector norm of each tensor in |
mm |
Multiplies corresponding matrices from |