LibTorch (PyTorch C++ Frontend)
LibTorch is the official C++ frontend for Pytorch. However, due to its lack of documentation, I encountered lots of confusions during its use. Some useful tips/tricks are listed here just FYI.
As of July 2021, this documentation is written based on my experience with libtorch v1.9
Performance: slower than Pythonâ
It is repeatedly reported that inference using LibTorch is much slower than that in Python. See discussions in #19106.
There is also a ZhiHu article (in Chinese) that attempts to analyze this issue in-depth. The solution it proposed was to recompile libtorch by linking to libraries used by pytorch.
Cross-Save/Load Tensors in Pythonâ
This section documents how to save tensors in C++ and load them into Python, and vice versa. It is often done for more friendly debugging experience offered by the Python frontend.
Save tensor in C++ and load in Pythonâ
In C++, call torch::save()
to save.
#include <torch/torch.h>
// save one tensor
torch::save(tensor, "tensor.pt");
// save multiple tensors
torch::save({tensora, tensorb, tensorc}, "tensors.pt");
In Python, use torch.jit.load()
to load.
import torch
# Load one tensor
tensor_model = torch.jit.load("tensor.pt")
tensor = list(tensor_model.parameters())[0]
# Load multiple tensors
tensors_model = torch.jit.load("tensors.pt")
tensora = list(tensors_model.parameters())[0]
tensorb = list(tensors_model.parameters())[1]
tensorc = list(tensors_model.parameters())[2]
Save tensor in Python and load in C++â
The following codes are adapted from pytorch/pytorch#20356 (comment) and updated for the v1.8+ API (get_attribute
=> attr
).
Save tensors in Python: to do so, you have to create a model and include all tensors into this TorchScript module.
import torch
class Container(torch.nn.Module):
def __init__(self, my_values):
super().__init__()
for key in my_values:
setattr(self, key, my_values[key])
my_values = {
'a': torch.ones(2, 2),
'b': torch.ones(2, 2) + 10,
'c': 'hello',
'd': 6
}
# Save arbitrary values supported by TorchScript
# https://pytorch.org/docs/master/jit.html#supported-type
container = torch.jit.script(Container(my_values))
container.save("container.pt")
Load tensors in C++
#include <torch/script.h>
torch::jit::script::Module container = torch::jit::load("container.pt");
torch::Tensor a = container.attr("a").toTensor();
torch::Tensor b = container.attr("b").toTensor();
std::string c = container.attr("c").toStringRef();
int64_t d = container.attr("d").toInt();
Alternative: use pickleâ
An alternative is to use pickle_save
and pickle_load
(source). See this comment in pytorch/pytorch#20356 for usage.
Multiple Input/Output for Inferenceâ
Suppose we have loaded a model named module
and want to use it for inference. However, the model requires multiple inputs/outputs.
The codes are adapted from pytorch/pytorch#18337.
std::vector<torch::jit::IValue> inputs;
inputs.push_back(tensora);
inputs.push_back(tensorb);
auto outputs = module->forward(inputs).toTuple();
torch::Tensor out1 = outputs->elements()[0].toTensor();
torch::Tensor out2 = outputs->elements()[1].toTensor();
Note: if you only have one output, you can directly call toTensor()
on the output of forward()
.