评价此页

C++ 前端#

PyTorch C++ 前端是一个 C++17 库,用于 CPU 和 GPU 的张量计算,具有自动微分功能和用于最先进的机器学习应用程序的高级构建块。

描述#

PyTorch C++ 前端可以被认为是 PyTorch Python 前端的 C++ 版本,它提供了自动微分以及用于机器学习和神经网络的各种更高级别的抽象。具体来说,它包含以下组件:

组件

描述

torch::Tensor

自动微分、高效的 CPU 和 GPU 启用的张量

torch::nn

用于神经网络建模的可组合模块集合

torch::optim

用于训练模型的优化算法,如 SGD、Adam 或 RMSprop

torch::data

数据集、数据管道以及多线程、异步数据加载器

torch::serialize

用于存储和加载模型检查点的序列化 API

torch::python

将您的 C++ 模型绑定到 Python 的粘合剂

torch::jit

纯 C++ 访问 TorchScript JIT 编译器

端到端示例#

以下是一个在 MNIST 数据集上定义和训练简单神经网络的简单端到端示例。

#include <torch/torch.h>

// Define a new Module.
struct Net : torch::nn::Module {
  Net() {
    // Construct and register two Linear submodules.
    fc1 = register_module("fc1", torch::nn::Linear(784, 64));
    fc2 = register_module("fc2", torch::nn::Linear(64, 32));
    fc3 = register_module("fc3", torch::nn::Linear(32, 10));
  }

  // Implement the Net's algorithm.
  torch::Tensor forward(torch::Tensor x) {
    // Use one of many tensor manipulation functions.
    x = torch::relu(fc1->forward(x.reshape({x.size(0), 784})));
    x = torch::dropout(x, /*p=*/0.5, /*train=*/is_training());
    x = torch::relu(fc2->forward(x));
    x = torch::log_softmax(fc3->forward(x), /*dim=*/1);
    return x;
  }

  // Use one of many "standard library" modules.
  torch::nn::Linear fc1{nullptr}, fc2{nullptr}, fc3{nullptr};
};

int main() {
  // Create a new Net.
  auto net = std::make_shared<Net>();

  // Create a multi-threaded data loader for the MNIST dataset.
  auto data_loader = torch::data::make_data_loader(
      torch::data::datasets::MNIST("./data").map(
          torch::data::transforms::Stack<>()),
      /*batch_size=*/64);

  // Instantiate an SGD optimization algorithm to update our Net's parameters.
  torch::optim::SGD optimizer(net->parameters(), /*lr=*/0.01);

  for (size_t epoch = 1; epoch <= 10; ++epoch) {
    size_t batch_index = 0;
    // Iterate the data loader to yield batches from the dataset.
    for (auto& batch : *data_loader) {
      // Reset gradients.
      optimizer.zero_grad();
      // Execute the model on the input data.
      torch::Tensor prediction = net->forward(batch.data);
      // Compute a loss value to judge the prediction of our model.
      torch::Tensor loss = torch::nll_loss(prediction, batch.target);
      // Compute gradients of the loss w.r.t. the parameters of our model.
      loss.backward();
      // Update the parameters based on the calculated gradients.
      optimizer.step();
      // Output the loss and checkpoint every 100 batches.
      if (++batch_index % 100 == 0) {
        std::cout << "Epoch: " << epoch << " | Batch: " << batch_index
                  << " | Loss: " << loss.item<float>() << std::endl;
        // Serialize your model periodically as a checkpoint.
        torch::save(net, "net.pt");
      }
    }
  }
}

要查看更多使用 PyTorch C++ 前端的完整示例,请参阅示例仓库

理念#

PyTorch 的 C++ 前端的设计理念是,Python 前端非常出色,应尽可能使用;但在某些情况下,性能和可移植性要求使得使用 Python 解释器不可行。例如,Python 在低延迟、高性能或多线程环境(如视频游戏或生产服务器)中表现不佳。C++ 前端的目标是解决这些用例,同时又不牺牲 Python 前端对用户体验的友好性。

因此,C++ 前端在设计时考虑了以下几个理念:

  • 在设计、命名、约定和功能上紧密模仿 Python 前端。虽然两个前端之间可能会有偶尔的差异(例如,我们删除了已弃用的功能或修复了 Python 前端的“痛点”),但我们保证将 Python 模型移植到 C++ 的工作量应仅限于语言特性的翻译,而不是修改功能或行为。

  • 优先考虑灵活性和用户友好性,而非微优化。 在 C++ 中,您通常可以获得最佳代码,但代价是用户体验极差。灵活性和动态性是 PyTorch 的核心,C++ 前端力求保留这种体验,在某些情况下牺牲性能(或“隐藏”性能调优选项)以保持 API 的简洁和易于理解。我们希望那些不以 C++ 为生的研究人员也能使用我们的 API。

一个警告:Python 不一定比 C++ 慢!Python 前端几乎所有的计算密集型操作(尤其是任何类型的数值运算)都调用 C++,这些操作将占据程序运行的大部分时间。如果您更喜欢用 Python 编写,并且能够承担用 Python 编写的成本,我们建议使用 PyTorch 的 Python 接口。然而,如果您更喜欢用 C++ 编写,或者需要用 C++ 编写(因为多线程、延迟或部署要求),PyTorch 的 C++ 前端提供了一个 API,它在便利性、灵活性、友好性和直观性方面几乎与 Python 版本相当。这两个前端服务于不同的用例,协同工作, neither is meant to unconditionally replace the other。

安装#

有关如何安装 C++ 前端库分发版的说明,包括如何构建依赖于 LibTorch 的最小应用程序的示例,可通过链接找到。