【问题标题】:libtorch (PyTorch C++) weird class syntaxlibtorch (PyTorch C++) 奇怪的类语法
【发布时间】:2020-04-20 03:49:59
【问题描述】:

在 GitHub 上的官方 PyTorch C++ 示例中Here 你可以看到一个奇怪的类定义:

class CustomDataset : public torch::data::datasets::Dataset<CustomDataset> {...}

我的理解是,这定义了一个类CustomDataset,它“继承自”或“扩展”torch::data::datasets::Dataset&lt;CustomDataset&gt;。这对我来说很奇怪,因为我们正在创建的类是从另一个由我们正在创建的类参数化的类继承的......这甚至是如何工作的?这是什么意思?这在我看来就像是继承自 vector&lt;Integer&gt;Integer 类,这似乎很荒谬。

【问题讨论】:

    标签: c++ pytorch libtorch


    【解决方案1】:

    这是curiously-recurring template pattern,简称 CRTP。这种技术的一个主要优点是它启用了所谓的静态多态性,这意味着torch::data::datasets::Dataset 中的函数可以调用CustomDataset 的函数,而无需使这些函数虚拟化(从而处理虚拟方法调度的运行时混乱等等)。您还可以根据自定义数据集类型的属性执行编译时元编程,例如编译时enable_ifs。

    对于 PyTorch,BaseDatasetDataset 的超类)大量使用这种技术来支持映射和过滤等操作:

      template <typename TransformType>
      MapDataset<Self, TransformType> map(TransformType transform) & {
        return datasets::map(static_cast<Self&>(*this), std::move(transform));
      }
    

    注意this 到派生类型的静态转换(只要正确应用 CRTP 就合法); datasets::map 构造了一个MapDataset 对象,该对象也由数据集类型参数化,允许MapDataset 实现静态调用诸如get_batch 之类的方法(或者如果它们遇到编译时错误不存在)。

    此外,由于MapDataset 接收自定义数据集类型作为类型参数,因此可以进行编译时元编程:

      /// The implementation of `get_batch()` for the stateless case, which simply
      /// applies the transform to the output of `get_batch()` from the dataset.
      template <
          typename D = SourceDataset,
          typename = torch::disable_if_t<D::is_stateful>>
      OutputBatchType get_batch_impl(BatchRequestType indices) {
        return transform_.apply_batch(dataset_.get_batch(std::move(indices)));
      }
    
      /// The implementation of `get_batch()` for the stateful case. Here, we follow
      /// the semantics of `Optional.map()` in many functional languages, which
      /// applies a transformation to the optional's content when the optional
      /// contains a value, and returns a new optional (of a different type)  if the
      /// original optional returned by `get_batch()` was empty.
      template <typename D = SourceDataset>
      torch::enable_if_t<D::is_stateful, OutputBatchType> get_batch_impl(
          BatchRequestType indices) {
        if (auto batch = dataset_.get_batch(std::move(indices))) {
          return transform_.apply_batch(std::move(*batch));
        }
        return nullopt;
      }
    

    请注意,条件启用取决于SourceDataset,我们之所以拥有它,是因为数据集是使用此 CRTP 模式参数化的。

    【讨论】:

    • 非常感谢!我整天都盯着这个,想知道这是不是一个愚蠢的问题。来自 Python 的 C++ 让我很困惑。我希望能够写出快速的代码,但我也希望能够看到代码中的美。我想我还没有完全掌握 C++。
    • 别担心!我很高兴我能提供帮助,并希望我的解释足够清楚(恐怕我可能混淆了特定于 pytorch 的内容)
    • 即使我没有完全理解你所说的一切,但我现在至少有一些想法,并且有一个关键字可以google。有时这是最难的部分......
    猜你喜欢
    • 2017-12-06
    • 1970-01-01
    • 1970-01-01
    • 2016-08-26
    • 2020-12-09
    • 2012-03-14
    • 2012-12-17
    • 2012-10-12
    • 2010-11-24
    相关资源
    最近更新 更多