Unrecognized data format using libtorch when loading TorchScript exported model (Python) in C++ context

Hi :slight_smile:

Setup: Win10, Visual Studio 2017, libtorch 1.12.1 (release, tried CPU and CUDA versions), CMake 3.12 (integrated in VS2017)

Goal: Export model from PyTorch (Python) to file using TorchScript and load it using libtorch (C++).

Issue:

When loading any exported module I am getting an error (see below). The actual file here is not important (although I have provided the Python code to show how I am doing it) since the error occurs with any trained model I tried (PT/PTH files downloaded from the internet). The issue is therefore probably not in the way I am saving the file but rather either the serialization or de-serialization of it.

Unrecognized data format
Exception raised from load at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\torch\csrc\jit\serialization\import.cpp:449 (most recent call first):
00007FFEBEDADA2200007FFEBEDAD9C0 c10.dll!c10::Error::Error [<unknown file> @ <unknown line number>]
00007FFEBEDAD43E00007FFEBEDAD3F0 c10.dll!c10::detail::torchCheckFail [<unknown file> @ <unknown line number>]
00007FFE4FF2B54700007FFE4FF2B4E0 torch_cpu.dll!torch::jit::load [<unknown file> @ <unknown line number>]
00007FFE4FF2B42A00007FFE4FF2B380 torch_cpu.dll!torch::jit::load [<unknown file> @ <unknown line number>]
00007FF64CF2682B00007FF64CF266E0 pytroch_load_model.exe!main [c:\users\USER\projects\cmake dx cuda pytorch\cmake_integration_examples\pytorch\src\pytroch_load_model.cpp @ 17]
00007FF64CF51C2400007FF64CF51BF0 pytroch_load_model.exe!invoke_main [d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79]
00007FF64CF51ACE00007FF64CF519A0 pytroch_load_model.exe!__scrt_common_main_seh [d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
00007FF64CF5198E00007FF64CF51980 pytroch_load_model.exe!__scrt_common_main [d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331]
00007FF64CF51CB900007FF64CF51CB0 pytroch_load_model.exe!mainCRTStartup [d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17]
00007FFEDD72703400007FFEDD727020 KERNEL32.DLL!BaseThreadInitThunk [<unknown file> @ <unknown line number>]
00007FFEDDA0265100007FFEDDA02630 ntdll.dll!RtlUserThreadStart [<unknown file> @ <unknown line number>]

Steps to reproduce:

I am using the following code:

Python

Currently I just create some modules and try to export those. Training/Evaluation as well as the actual purpose of the modules is of no importance. All of it is directly taken either from the official documentation on TorchScript or the PyTorch forums.

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
def init(self):
super(Net, self).init()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)

def forward(self, x):
    x = self.pool(F.relu(self.conv1(x)))
    x = self.pool(F.relu(self.conv2(x)))
    x = x.view(-1, 16 * 5 * 5)
    x = F.relu(self.fc1(x))
    x = F.relu(self.fc2(x))
    x = self.fc3(x)
    return x

class TestModel(nn.Module):
def init(self):
super(TestModel, self).init()
self.x = 2

def forward(self, x):
    return self.x

class TensorContainer(nn.Module):
def init(self, tensor_dict):
super().init()
for key,value in tensor_dict.items():
setattr(self, key, value)

test_net = Net()
print(test_net)
test_net = torch.jit.script(test_net)
torch.jit.save(test_net, ‘test_net.pt’)

test_module = TestModel()
print(test_module)
test_module = torch.jit.script(test_module)
torch.jit.save(test_module, ‘test_module.pt’)

prior = torch.ones(3, 3)
tensor_dict = {‘prior’: prior}
print(tensor_dict)
tensors = TensorContainer(tensor_dict)
print(tensors.dict)
tensors = torch.jit.script(tensors)
tensors.save(‘values.pt’)

C++

The loaded model (C++ context) is currently not used at all. The main point here is to just load the thing from a file. I tried both relative path (e.g. the EXE and the exported modules are in the same directory and I can just do binary.exe module.pt) and absolute path (just in case that libtorch doesn’t deal properly with relative paths; path does not contain any Unicode).

#include <torch/script.h>
#include <iostream>
#include <memory>

int main(int argc, const char* argv[]) {
	if (argc != 2) {
		std::cerr << "Usage: pytroch_load_model <path-to-exported-script-module>\n";
		return -1;
	}

	torch::jit::script::Module module;
	try {
		std::cout << "Trying to load model..." << std::endl;
		module = torch::jit::load(argv[1]);
	}
	catch (const c10::Error& e) {
		std::cerr << "Loading failed" << std::endl;
		std::cerr << e.what() << std::endl;
		return -1;
	}

	std::cout << "Loading successful" << std::endl;
}

CMakeLists.txt

The project is a subdirectory (sub-project). The Torch libraries, headers etc. are located in the top-level directory of the main project (hence the ${CMAKE_SOURCE_DIR} call). All required libraries are linked properly (no errors during link stage) and DLLs are accordingly copied to the directory where the final EXE is located.

cmake_minimum_required (VERSION 3.12 FATAL_ERROR)

project(pytroch
  DESCRIPTION "CMake example for PyTorch (libtorch C++) integration"
  LANGUAGES CXX
)

set(CMAKE_CXX_STANDARD 14)

set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/deps/libtorch/1.12.1/release/cpu/share/cmake/Torch")
find_package(Torch REQUIRED)
if(TORCH_FOUND)
	message(STATUS "Found Torch")
else()
	message(CRITICAL_ERROR "Unable to find Torch")
endif(TORCH_FOUND)

add_executable(pytroch_load_model
	"${SRC_DIR}/pytroch_load_model.cpp"
)
target_include_directories(pytroch_load_model PUBLIC ${TORCH_INCLUDE_DIRS})
target_link_libraries(pytroch_load_model PRIVATE ${TORCH_LIBRARIES})

file(GLOB LIBTORCH_DLLS
  "${CMAKE_SOURCE_DIR}/deps/libtorch/1.12.1/release/cpu/lib/*.dll"
)
file(COPY
	${LIBTORCH_DLLS}
	DESTINATION "${CMAKE_BINARY_DIR}/bin/"
)
1 Like