MaybeOwned<Tensor>#
MaybeOwned<Tensor> is a C++ smart pointer class that dynamicallyencodes whether a Tensor isowned orborrowed. It is used incertain performance-sensitive situations to avoid unnecessarilyincrementing a Tensor’s reference count (at a small cost inoverhead from the extra indirection).
Warning
MaybeOwned must be used withextreme care. Claims of (non-)ownershipare not statically checked, and mistakes can cause reference undercountingand use-after-free crashes.
Due to this lack of safety net, we discourage the use of MaybeOwnedoutside code paths that are known to be highly performance sensitive.However, if you encounter pre-existing uses of MaybeOwned in code thatyou want to modify, it’s critical to understand how to use it correctly.
The primary use case forMaybeOwned<Tensor> is a function or method thatdynamically chooses between returning one of its arguments (typicallyfrom a passthrough or “no-op” code path) and returning a freshly constructedTensor. Such a function would return aMaybeOwned<Tensor> in both cases,the former in a “borrowed” state via a call toMaybeOwned<Tensor>::borrowed(),and the latter in an “owned” state via a call toMaybeOwned<Tensor>::owned().
The canonical example isTensor’sexpect_contiguous method, which shortcutsand returns a borrowed self-reference when already contiguous:
inlinec10::MaybeOwned<Tensor>Tensor::expect_contiguous(MemoryFormatmemory_format)const&{if(is_contiguous(memory_format)){returnc10::MaybeOwned<Tensor>::borrowed(*this);}else{returnc10::MaybeOwned<Tensor>::owned(__dispatch_contiguous(memory_format));}}
Using the vocabulary of lifetimes, the essential safety requirement for borrowingis that a borrowed Tensor must outlive any borrowing references to it. Here, forexample, we can safely borrow*this, but the Tensor returned by__dispatch_contiguous() is freshly created, and borrowing a reference wouldeffectively leave it ownerless.
So, general rules of thumb:
When in doubt, don’t use
MaybeOwned<Tensor>at all - in particular, preferavoiding using it in code that doesn’t use it already. New usage should only beintroduced when critical (and demonstrable) performance gains result.When modifying or calling code that already uses
MaybeOwned<Tensor>, rememberthat it’s always safe to produce aMaybeOwned<Tensor>from a Tensor in handvia a call toMaybeOwned<Tensor>::owned(). This may result in an unnecessaryreference count, but never in misbehavior - so it’s always the safer bet, unlessthe lifetime of the Tensor you’re looking to wrap is crystal clear.
More details and implementation code can be found at <pytorch/pytorch> and<pytorch/pytorch>.