In many use cases for deep learning, such as neural network inference and deployment, we would like to load and save the numpy files generated by Python in C++ and vice versa for debugging and testing purposes. xtensor is a well-maintained C++ library that provides a convenient way to load and save numpy files in C++.
In this blog post, I will introduce how to load and save numpy files in C++ using the xtensor library.
C++ Load and Save Npy File Load Using xtensor
The examples demonstrated how to load and save numpy files in C++ using the xtensor library and how to load and save numpy files in Python using the numpy library. The examples are available on GitHub.
intmain(int argc, char* argv[]) { // Print the usage of the program. if (argc != 2) { std::cerr << "Usage: " << argv[0] << " <npy_file_path>" << std::endl; return1; } std::string const npy_file_path{argv[1]};
// Load the 4D array from the npy file. xt::xarray<float> const float_array{xt::load_npy<float>(npy_file_path)};
// Get the shape of the array. autoconst shape = float_array.shape(); assert(shape.size() == 4); assert(shape[0] == 2); assert(shape[1] == 3); assert(shape[2] == 4); assert(shape[3] == 5);
// Access the elements of the array using a pointer. floatconst* const ptr{float_array.data()}; for (size_t i{0}; i < float_array.size(); ++i) { assert(ptr[i] == static_cast<float>(i)); }
# Create argument parser that allows the user to specify the path to the npy file. parser = argparse.ArgumentParser() parser.add_argument("--npy_file_path", type=str, required=True) args = parser.parse_args() npy_file_path = args.npy_file_path
# Load the data tensor = np.load(npy_file_path)
assert tensor.shape == (2, 3, 4, 5)
for i inrange(2): for j inrange(3): for k inrange(4): for l inrange(5): assert tensor[i, j, k, l] == i * 3 * 4 * 5 + j * 4 * 5 + k * 5 + l
assert tensor.dtype == np.float32
Save Numpy File In Python
save_npy.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import argparse import numpy as np
if __name__ == "__main__":
# Create argument parser that allows the user to specify the path to the npy file. parser = argparse.ArgumentParser() parser.add_argument("--npy_file_path", type=str, required=True) args = parser.parse_args() npy_file_path = args.npy_file_path
# Create a 4D numpy float array of linear layout. tensor_shape = (2, 3, 4, 5) tensor = np.arange(np.prod(tensor_shape)).reshape(tensor_shape).astype( np.float32)
# Save the data np.save(npy_file_path, tensor)
Build and Run the Examples
The examples could be built using CMake in a Docker container by following the instructions on the README.
Once the examples are built, the examples could be run using the following commands.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$ mkdir -p data
# Save npy file from Python $ python python/save_npy.py --npy_file_path data/npy_data_from_python.npy # Verify npy file from Python $ python python/load_npy.py --npy_file_path data/npy_data_from_python.npy # Verify npy file from C++ $ ./build/src/load_npy data/npy_data_from_python.npy
# Save npy file from C++ $ ./build/src/save_npy data/npy_data_from_cpp.npy # Verify npy file from Python $ python python/load_npy.py --npy_file_path data/npy_data_from_cpp.npy # Verify npy file from C++ $ ./build/src/load_npy data/npy_data_from_cpp.npy