테크매니아
libtorch example : Pytroch to C++ sample code 본문
개요
Pytorch는 딥러닝 모델 개발에 널리 사용되는 프레임워크 입니다.
Pytorch에서 개발된 모델을 배포 할 때 배포되는 패키지에 딥러닝 개발 프레임워크인 Pytorch를 몽땅 포함해서 배포 하는게 바람직한 일이 아닙니다.
개발된 모델을 onnx로 바꾸거나 CPU, GPU, DSP, NPU에서 제공되는 SDK가 있다면 그것을 이용해서 배포할 수도 있습니다.
이 글에서는 libtorch에 대해서 알아보겠습니다.
libtorch 설치
libtorch를 설치하는 방법에 대해서 설명합니다.
libtorch는 이미 빌드된 바이너리가 공개되어 있기 때문에 일반적인 환경에서 바로 압축파일을 다운을수 있습니다.
링크를 통해 GPU에서 빌드된 버전의 바이너리나 소스코드를 직접 받아서 빌드할 수 있습니다.
wget https://download.pytorch.org/libtorch/nightly/cpu/libtorch-shared-with-deps-latest.zip
unzip libtorch-shared-with-deps-latest.zip
위 스크립트대로 이미 빌드된 libtorch를 다운받아 보겠습니다.
환경은 x64 Ubuntu20.04 버전입니다.
Pytorch에서 모델 export
Pytorch에서 개발된 모델을 torch.jit.trace
를 통해 Torch Script로 변환합니다.
torchvision에 있는 resnet18를 그대로 사용합니다.
입출력 텐서의 shape을 잘 확인하고 traced_resnet_model.pt
이름으로 저장합니다.
import torch
import torchvision
# An instance of your model.
model = torchvision.models.resnet18()
# An example input you would normally provide to your model's forward() method.
example = torch.rand(1, 3, 224, 224)
# Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing.
traced_script_module = torch.jit.trace(model, example)
output = traced_script_module(torch.ones(1, 3, 224, 224))
traced_script_module.save("traced_resnet_model.pt")
C++ 샘플 작성
Pytorch에서 저장한 모델을 로드하는 샘플 C++ 코드를 작성합니다.
파일 이름은 main.cpp
으로 합니다.
파라미터로 받은 모델을 읽고 오류를 체크 합니다.
#include <torch/script.h> // One-stop header.
#include <iostream>
#include <memory>
int main(int argc, const char* argv[]) {
if (argc != 2) {
std::cerr << "usage: example-app <path-to-exported-script-module>\n";
return -1;
}
torch::jit::script::Module module;
try {
// Deserialize the ScriptModule from a file using torch::jit::load().
module = torch::jit::load(argv[1]);
}
catch (const c10::Error& e) {
std::cerr << "error loading the model\n";
return -1;
}
std::cout << "ok\n";
}
CMakeLists 작성
위에서 작성한 C++ 파일을 빌드하기 위해 main.cpp
와 같은 디렉토리에 CMakeLists.txt
파일을 작성합니다.
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(example-app)
find_package(Torch REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
add_executable(example-app main.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)
Build
cmake에서 CMAKE_PREFIX_PATH
를 libtorch의 경로로 설정합니다.
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=/home/.../pytorch2cpp/libtorch ..
make -j4
Test
빌드된 바이너리 example-app를 실행합니다.
./example-app
usage: example-app <path-to-exported-script-module>
./example-app ../traced_resnet_model.pt
ok
파라미터로 Pytorch에서 저장한 파일을 넣어주면 정상 작동을 확인합니다.
C++에서 Script Module을 실행하기 위해서 다시 main.cpp
파일 하단에 아래 코드를 추가 합니다.
입력 shape에 맞게 tensor를 생성하고 forward합니다.
// Create a vector of inputs.
std::vector<torch::jit::IValue> inputs;
inputs.push_back(torch::ones({1, 3, 224, 224}));
// Execute the model and turn its output into a tensor.
at::Tensor output = module.forward(inputs).toTensor();
std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
다시 코드를 build하고 실행하면 추론 결과를 확인 할 수 있습니다.
./example-app ../traced_resnet_model.pt
-0.9616 -0.6217 -0.1954 0.3419 -0.3290
[ CPUFloatType{1,5} ]
ok
전체 코드
참고자료
- https://pytorch.org/tutorials/advanced/cpp_export.html
- https://pytorch.org/tutorials/advanced/cpp_export.html
- https://ys-cs17.tistory.com/45
- https://blog.fearcat.in/a?ID=01750-d33c2495-08e6-4ccb-89a3-866eec3eab1e
- https://colab.research.google.com/github/pytorch/pytorch.github.io/blob/master/assets/hub/pytorch_vision_resnet.ipynb#scrollTo=pretty-feelings