딥러닝을 개발은 주로 Python에서 이루어지지만, 실제 환경에 적용하다보면 C++에서 직접 작업할 필요가 있습니다.
이때, PyTorch의 c++ 버전인 LibTorch를 활용하는 것도 하나의 방법이 될 수 있습니다.
PyTorch 자체도 c++을 python으로 감싼 것이지만, 막상 c++ documentation이 잘 되어있지 않습니다.
본 카테고리 글들은 개발 과정에서 사용하게 된 함수들을 기록하기 위함입니다.
궁금하신 사항은 댓글로 남겨주세요.
1-1. vector -> torch::Tensor
#include <torch/torch.h>
#include <vector>
#include <iostream>
using namespace std;
using namespace torch::indexing;
int main(){
vector<double> tempVector({1, 2, 4, 3, 4, 3});
torch::Tensor tempTensor;
tempTensor = torch::from_blob(tempVector.data(), {(long) tempVector.size()}, torch::kF64);
cout << "temp Vector = (";
for (auto a : tempVector)
cout << a << ", ";
cout << ")" << endl;
cout << "temp Tensor : " << tempTensor << endl;
return 0;
}
torch::from_blob 함수를 사용하여 vector의 data를 이용한 tensor를 만들 수 있습니다.
torch::from_blob 함수 인자로는 data pointer, tensor 모양, tensor data type를 받습니다.
tesnor 모양은 {6}, {1, 6}, {2, 3}, {3, 2} 등 다양하게 {a, b, c, d, ...} 형태로 지정 가능합니다.
1-2. from_blob 사용시 주의사항
(1) vector의 data type과 torch의 data type을 동일하게 맞춰야합니다.
정상 결과(double -> torch::kF64)
temp Vector = (1, 2, 4, 3, 4, 3, )
temp Tensor : 1
2
4
3
4
3
[ CPUDoubleType{6} ]
잘못된 결과 1(float -> torch::kF64)
temp Vector = (1, 2, 4, 3, 4, 3, )
temp Tensor : 2.0000e+00
3.2000e+01
3.2000e+01
4.7924e-322
6.9499e-310
4.9407e-324
[ CPUDoubleType{6} ]
잘못된 결과 2(double -> torch::kF32)
temp Vector = (1, 2, 4, 3, 4, 3, )
temp Tensor : 0.0000
1.8750
0.0000
2.0000
0.0000
2.2500
[ CPUFloatType{6} ]
(2) 데이터 미복사 문제
from_blob을 그냥 사용하면 값이 복사되지 않고 있는 data를 참조하게 됩니다.
#include <torch/torch.h>
#include <vector>
#include <iostream>
using namespace std;
using namespace torch::indexing;
int main(){
torch::Tensor tempTensor;
{
vector<double> tempVector({1, 2, 4, 3, 4, 3});
tempTensor = torch::from_blob(tempVector.data(), {(long) tempVector.size()}, torch::kF64);
cout << "temp Vector = (";
for (auto a: tempVector)
cout << a << ", ";
cout << ")" << endl;
cout << "temp Tensor : " << tempTensor << endl;
}
cout << "temp Tensor : " << tempTensor << endl;
return 0;
}
위 코드는 tempVector가 살아있을때 tempTensor를 출력하고, tempVector가 제거됐을때 tempTensor를 출력하는 코드입니다.
실행 결과
temp Vector = (1, 2, 4, 3, 4, 3, )
temp Tensor : 1
2
4
3
4
3
[ CPUDoubleType{6} ]
temp Tensor : 4.6583e-310
4.6583e-310
4.0000e+00
3.0000e+00
4.0000e+00
3.0000e+00
[ CPUDoubleType{6} ]
tempVector가 제거되면 tempTensor의 값도 쓰레기값으로 바뀌는 것이 보입니다.
이를 해결하기 위해 from_blob 라인 뒤에 .clone()을 추가하여 복사해주시면 됩니다.
tempTensor = torch::from_blob(tempVector.data(), {(long) tempVector.size()}, torch::kF64).clone(); // add clone()
결과
temp Vector = (1, 2, 4, 3, 4, 3, )
temp Tensor : 1
2
4
3
4
3
[ CPUDoubleType{6} ]
temp Tensor : 1
2
4
3
4
3
[ CPUDoubleType{6} ]
2. Tensor -> Vector
vector<float> tempVector(tempTensor.data_ptr<float>(), tempTensor.data_ptr<float>() + tempTensor.numel());
tempTensor.data_ptr<데이터타입>()을 통해 tensor의 data 포인터를 가져올 수 있습니다.
.numel()은 데이터 개수를 반환합니다.
여기서도 vector의 data type과 data_ptr의 데이터 타입을 같도록 만드는 것을 주의하시기 바랍니다.
'LibTorch' 카테고리의 다른 글
| [LibTorch/C++] torch::Tensor indexing 방법 (0) | 2022.06.14 |
|---|