| 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>. |