PyTorch C++ API에서 torch::from_blob()을 사용해 참조 기반 텐서를 만들면, CPU에서는 지역 변수 소멸로 인한 dangling pointer 문제가 자주 발생합니다. 하지만 CUDA나 MPS 환경에서는 비교적 안전해 보일 수 있습니다. 이유는 다음과 같습니다.
std::vector<float> data = {1, 2, 3, 4};
auto cpu_tensor = torch::from_blob(data.data(), {2, 2}, torch::kFloat);
// GPU/MPS로 이동 시 새로운 메모리 생성
auto cuda_tensor = cpu_tensor.to(torch::kCUDA);
auto mps_tensor = cpu_tensor.to(torch::kMPS);
.to(device) 호출 시 원본 CPU 메모리와 독립된 GPU 메모리에 복사됩니다.
GPU 복사 전 CPU 연산을 수행하면 여전히 위험합니다.
auto tensor = torch::from_blob(data.data(), {2, 2}, torch::kFloat);
auto result = tensor + 1.0; // data 유효해야 함
tensor = tensor.to(torch::kCUDA); // 그 이후에야 안전
auto tensor = torch::from_blob(data.data(), {2, 2}, torch::kFloat)
.to(torch::kCUDA);
auto tensor = torch::zeros({2, 2}, torch::device(torch::kCUDA));
auto safe_tensor = torch::from_blob(data.data(), {2, 2}, torch::kFloat).clone();
auto safe_tensor = torch::tensor(data); // 복사 생성
.to(torch::kCPU) 주의사항즉, 참조 기반 CPU 텐서를 .to(torch::kCPU)로 반환해도 메모리 안전성이 보장되지 않습니다.
from_blob() 사용 시 여전히 위험auto tensor = torch::from_blob(data.data(), {1, 4}, torch::kFloat)
.to(torch::kCUDA); // GPU 복사로 안전
재사용 가능한 버퍼를 만들어 매번 메모리 할당을 피하면 성능과 안전성을 모두 확보할 수 있습니다.
class InferenceEngine {
torch::Tensor buffer_;
public:
torch::Tensor inference(const std::vector<float>& data) {
if (buffer_.numel() != data.size())
buffer_ = torch::zeros({1, (int)data.size()}, torch::kFloat);
std::memcpy(buffer_.data_ptr<float>(), data.data(), data.size() * sizeof(float));
return model.forward({buffer_}).toTensor();
}
};
CUDA/MPS 환경에서는 GPU 메모리 복사 덕분에 참조 오류가 덜 발생
그러나 CPU에서 연산하거나 .to(torch::kCPU)를 사용할 때는 여전히 위험
가장 안전한 방법:
torch::tensor()로 생성.clone() 명시적 호출.to(GPU) 즉시 이동참조 + clone()은 성능과 안전성을 동시에 확보하는 실전 추천 패턴입니다.