C++ 前端#
PyTorch C++ 前端是一個 C++17 庫,用於 CPU 和 GPU 的張量計算,具有自動微分功能和用於最先進的機器學習應用程式的高階構建塊。
描述#
PyTorch C++ 前端可以被認為是 PyTorch Python 前端的 C++ 版本,它提供了自動微分以及用於機器學習和神經網路的各種更高級別的抽象。具體來說,它包含以下元件:
元件 |
描述 |
|---|---|
|
自動微分、高效的 CPU 和 GPU 啟用的張量 |
|
用於神經網路建模的可組合模組集合 |
|
用於訓練模型的最佳化演算法,如 SGD、Adam 或 RMSprop |
|
資料集、資料管道以及多執行緒、非同步資料載入器 |
|
用於儲存和載入模型檢查點的序列化 API |
|
將您的 C++ 模型繫結到 Python 的粘合劑 |
|
純 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。