From 11fbd3958cb7ab69a9764d9ae9b000f24333ec40 Mon Sep 17 00:00:00 2001 From: Basil Hosmer Date: Wed, 18 Aug 2021 12:06:53 -0700 Subject: [PATCH] MaybeOwned page for dev wiki (#63450) Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/63450 Brief guide to understanding `MaybeOwned`, 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 --- docs/cpp/source/notes/maybe_owned.rst | 59 +++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/cpp/source/notes/maybe_owned.rst diff --git a/docs/cpp/source/notes/maybe_owned.rst b/docs/cpp/source/notes/maybe_owned.rst new file mode 100644 index 0000000..8fa05f1 --- /dev/null +++ b/docs/cpp/source/notes/maybe_owned.rst @@ -0,0 +1,59 @@ +MaybeOwned +================== + +``MaybeOwned`` 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`` 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`` in both cases, +the former in a "borrowed" state via a call to ``MaybeOwned::borrowed()``, +and the latter in an "owned" state via a call to ``MaybeOwned::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::expect_contiguous(MemoryFormat memory_format) const & { + if (is_contiguous(memory_format)) { + return c10::MaybeOwned::borrowed(*this); + } else { + return c10::MaybeOwned::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`` 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``, remember + that it's always safe to produce a ``MaybeOwned`` from a Tensor in hand + via a call to ``MaybeOwned::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 and +. -- 2.7.4