评价本页

MaybeOwned<Tensor>#

MaybeOwned<Tensor> 是一个 C++ 智能指针类,它动态编码一个 Tensor 是自有 (owned) 还是借用 (borrowed) 的。它在某些对性能敏感的情况下使用,以避免不必要地增加 Tensor 的引用计数(额外的间接访问会带来少量开销)。

警告

使用 MaybeOwned 务必极其谨慎。关于(非)所有权的声明不会进行静态检查,错误可能导致引用计数不足 (reference undercounting) 和释放后使用 (use-after-free) 崩溃。

由于缺乏安全保障,我们不鼓励在已知非高度性能敏感的代码路径之外使用 MaybeOwned。但是,如果您在想要修改的代码中遇到 MaybeOwned 的现有用法,理解如何正确使用它至关重要。

MaybeOwned<Tensor> 的主要用例是函数或方法动态地选择返回其某个参数(通常来自直通 (passthrough) 或“无操作 (no-op)”代码路径)或返回一个新构造的 Tensor。在这种情况下,此类函数会返回一个 MaybeOwned<Tensor>,前者通过调用 MaybeOwned<Tensor>::borrowed() 以“借用 (borrowed)”状态返回,后者通过调用 MaybeOwned<Tensor>::owned() 以“自有 (owned)”状态返回。

典型的例子是 Tensorexpect_contiguous 方法,当 Tensor 已经连续 (contiguous) 时,该方法会走捷径并返回一个借用的自引用

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));
  }
}

使用生命周期 (lifetimes) 的术语,借用的基本安全要求是:一个借用的 Tensor 必须比任何引用它的借用引用 (borrowing references) 寿命更长。例如,在这里我们可以安全地借用 *this,但 __dispatch_contiguous() 返回的 Tensor 是新创建的,借用一个引用实际上会使它处于无主 (ownerless) 状态。

所以,一般经验法则

  • 如有疑问,完全不要使用 MaybeOwned<Tensor> - 特别是,在尚未使用它的代码中避免使用它。只有当带来关键(且可证明)的性能提升时,才应引入新的用法。

  • 在修改或调用已使用 MaybeOwned<Tensor> 的代码时,请记住通过调用 MaybeOwned<Tensor>::owned() 从现有 Tensor 生成一个 MaybeOwned<Tensor> 总是安全的。这可能会导致不必要的引用计数增加,但绝不会导致错误行为 (misbehavior) - 因此这总是更安全的做法,除非你想要包装的 Tensor 的生命周期水晶般清晰 (crystal clear)。

更多详细信息和实现代码可在 <pytorch/pytorch> 和 <pytorch/pytorch> 中找到。