Files
pytorch/docs/cpp/source/notes/maybe_owned.rst
Basil Hosmer 11fbd3958c MaybeOwned page for dev wiki (#63450)
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
2021-08-18 12:08:58 -07:00

60 lines
2.9 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 Tensors 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, its 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, dont use ``MaybeOwned<Tensor>`` at all - in particular, prefer
avoiding using it in code that doesnt 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>.