mirror of
https://github.com/pytorch/pytorch.git
synced 2025-10-25 16:14:55 +08:00
Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/63450 Brief guide to understanding `MaybeOwned<Tensor>`, aimed at C++ PT devs who are obliged to interact with existing uses of it, rather than encouraging new usage. For reviewers: I haven't yet added a link to this page from anywhere. I'm thinking the right place is the [dev wiki main page C++ section](https://github.com/pytorch/pytorch/wiki#c) but happy to put it wherever makes sense, suggestions welcome. Test Plan: Imported from OSS Reviewed By: navahgar Differential Revision: D30402313 Pulled By: bhosmer fbshipit-source-id: 69b15909ecafcd8d88e44f664f88c3ad4eb26d84
60 lines
2.9 KiB
ReStructuredText
60 lines
2.9 KiB
ReStructuredText
MaybeOwned<Tensor>
|
||
==================
|
||
|
||
``MaybeOwned<Tensor>`` is a C++ smart pointer class that dynamically
|
||
encodes whether a Tensor is *owned* or *borrowed*. It is used in
|
||
certain performance-sensitive situations to avoid unnecessarily
|
||
incrementing a Tensor’s reference count (at a small cost in
|
||
overhead from the extra indirection).
|
||
|
||
.. warning::
|
||
MaybeOwned must be used with **extreme** care. Claims of (non-)ownership
|
||
are not statically checked, and mistakes can cause reference undercounting
|
||
and use-after-free crashes.
|
||
|
||
Due to this lack of safety net, we discourage the use of MaybeOwned
|
||
outside code paths that are known to be highly performance sensitive.
|
||
However, if you encounter pre-existing uses of MaybeOwned in code that
|
||
you want to modify, it’s critical to understand how to use it correctly.
|
||
|
||
The primary use case for ``MaybeOwned<Tensor>`` is a function or method that
|
||
dynamically chooses between returning one of its arguments (typically
|
||
from a passthrough or “no-op” code path) and returning a freshly constructed
|
||
Tensor. Such a function would return a ``MaybeOwned<Tensor>`` in both cases,
|
||
the former in a "borrowed" state via a call to ``MaybeOwned<Tensor>::borrowed()``,
|
||
and the latter in an "owned" state via a call to ``MaybeOwned<Tensor>::owned()``.
|
||
|
||
The canonical example is ``Tensor``'s ``expect_contiguous`` method, which shortcuts
|
||
and returns a borrowed self-reference when already contiguous:
|
||
|
||
.. code-block:: cpp
|
||
|
||
inline c10::MaybeOwned<Tensor> Tensor::expect_contiguous(MemoryFormat memory_format) const & {
|
||
if (is_contiguous(memory_format)) {
|
||
return c10::MaybeOwned<Tensor>::borrowed(*this);
|
||
} else {
|
||
return c10::MaybeOwned<Tensor>::owned(__dispatch_contiguous(memory_format));
|
||
}
|
||
}
|
||
|
||
Using the vocabulary of lifetimes, the essential safety requirement for borrowing
|
||
is that a borrowed Tensor must outlive any borrowing references to it. Here, for
|
||
example, we can safely borrow ``*this``, but the Tensor returned by
|
||
``__dispatch_contiguous()`` is freshly created, and borrowing a reference would
|
||
effectively leave it ownerless.
|
||
|
||
So, general rules of thumb:
|
||
|
||
- When in doubt, don’t use ``MaybeOwned<Tensor>`` at all - in particular, prefer
|
||
avoiding using it in code that doesn’t use it already. New usage should only be
|
||
introduced when critical (and demonstrable) performance gains result.
|
||
|
||
- When modifying or calling code that already uses ``MaybeOwned<Tensor>``, remember
|
||
that it's always safe to produce a ``MaybeOwned<Tensor>`` from a Tensor in hand
|
||
via a call to ``MaybeOwned<Tensor>::owned()``. This may result in an unnecessary
|
||
reference count, but never in misbehavior - so it's always the safer bet, unless
|
||
the lifetime of the Tensor you're looking to wrap is crystal clear.
|
||
|
||
More details and implementation code can be found at <https://github.com/pytorch/pytorch/blob/master/c10/util/MaybeOwned.h> and
|
||
<https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/templates/TensorBody.h>.
|