评价此页

MaybeOwned<Tensor>#

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

警告

必须极其谨慎地使用 MaybeOwned。对(非)所有权的声明不受静态检查,错误可能导致引用计数不足和使用后释放(use-after-free)崩溃。

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

MaybeOwned<Tensor> 的主要用例是某个函数或方法,它动态地在返回其参数之一(通常来自直通或“无操作”代码路径)和返回新构造的 Tensor 之间进行选择。这样的函数将在这两种情况下都返回一个 MaybeOwned<Tensor>,前者通过调用 MaybeOwned<Tensor>::borrowed() 以“借用”状态返回,后者通过调用 MaybeOwned<Tensor>::owned() 以“拥有”状态返回。

典型示例是 Tensorexpect_contiguous 方法,该方法在 Tensor 已是连续的时会进行捷径处理并返回一个借用的自引用。

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 必须在其任何借用引用存在之前存在。例如,在这里,我们可以安全地借用 *this,但由 __dispatch_contiguous() 返回的 Tensor 是新创建的,借用一个引用实际上会使其无主。

因此,总的经验法则:

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

  • 修改或调用已使用 MaybeOwned<Tensor> 的代码时,请记住,通过调用 MaybeOwned<Tensor>::owned() 从手中拥有的 Tensor 产生一个 MaybeOwned<Tensor> 始终是安全的。这可能会导致不必要的引用计数,但绝不会导致误行为——因此,它始终是更安全的选择,除非您要包装的 Tensor 的生命周期非常清晰。

有关更多详细信息和实现代码,请参阅 <pytorch/pytorch> 和 <pytorch/pytorch>。