Add extra files

./code/extra-files/test.py
 1#!/usr/bin/env python3
 2
 3import torch
 4import numpy as np
 5
 6
 7class Foo(torch.nn.Module):
 8    def __init__(self):
 9        super().__init__()
10        self.x = torch.nn.Parameter(torch.tensor([2.5]))
11
12    def forward(self, y: torch.Tensor):
13        return self.x + y
14
15
16@torch.inference_mode()
17def main():
18    f = Foo()
19    print(f(torch.tensor([3.5, 2.0])))
20
21    mean = np.array([1.5, 2.25, -3.8], dtype=np.float32)
22    inv_std = np.array([2.5, 225, 380], dtype=np.float32)
23
24    extra_files = dict()
25    extra_files["window_size"] = "20"
26    extra_files["window_shift"] = "64"
27    extra_files["cmvn_dim"] = f"{mean.shape[0]}"
28    extra_files["cmvn_mean"] = mean.tobytes()
29    extra_files["cmvn_inv_std"] = inv_std.tobytes()
30
31    m = torch.jit.script(f)
32    m.save("m.pt", _extra_files=extra_files)
33
34    saved = dict()
35    saved["window_size"] = ""
36    saved["window_shift"] = ""
37
38    saved["cmvn_dim"] = ""
39    saved["cmvn_mean"] = ""
40    saved["cmvn_inv_std"] = ""
41
42    m2 = torch.jit.load("m.pt", _extra_files=saved)
43    saved["cmvn_mean"] = np.frombuffer(saved["cmvn_mean"], dtype=np.float32)
44    saved["cmvn_inv_std"] = np.frombuffer(saved["cmvn_inv_std"], dtype=np.float32)
45    print(saved)
46    print(type(saved["window_shift"]))  # <class 'bytes'>
47
48
49"""
50tensor([6.0000, 4.5000])
51{'window_size': b'20', 'window_shift': b'64', 'cmvn_dim': b'3', 'cmvn_mean': array([ 1.5 ,  2.25, -3.8 ], dtype=float32), 'cmvn_inv_std': array([  2.5, 225. , 380. ], dtype=float32)}
52<class 'bytes'>
53"""
54
55
56if __name__ == "__main__":
57    main()
./code/extra-files/main.cc
 1#include "torch/script.h"
 2
 3std::vector<float> ToFloat(const std::string &s) {
 4  const float *p = reinterpret_cast<const float *>(s.data());
 5  int32_t n = s.size() / 4;
 6
 7  // assume little endian
 8  return {p, p + n};
 9}
10
11int main() {
12  // see torch/csrc/jit/module.h
13  // see
14  // https://github.com/pytorch/pytorch/blob/main/test/cpp/jit/test_save_load.cpp#L76
15  torch::jit::ExtraFilesMap extra_files{{"window_size", ""},
16                                        {"cmvn_mean", ""},
17                                        {"cmvn_inv_std", ""},
18                                        {"cmvn_dim", ""}};
19  torch::jit::Module m = torch::jit::load("./m.pt", torch::kCPU, extra_files);
20
21  int32_t dim = atoi(extra_files["cmvn_dim"].c_str());
22  if (dim != extra_files["cmvn_mean"].size() / 4 ||
23      dim != extra_files["cmvn_inv_std"].size() / 4) {
24    std::cout << "corrupted data!\n";
25    return -1;
26  }
27
28  auto cmvn_mean = ToFloat(extra_files["cmvn_mean"]);
29  auto cmvn_inv_std = ToFloat(extra_files["cmvn_inv_std"]);
30  int32_t window_size = atoi(extra_files["window_size"].c_str());
31  std::cout << "int window size: " << window_size << "\n";
32
33  for (const auto &p : extra_files) {
34    std::cout << p.first << ": " << p.second << "\n";
35  }
36  std::cout << "cmvn_mean: ";
37  for (auto f : cmvn_mean) {
38    std::cout << f << " ";
39  }
40  std::cout << "\n";
41
42  std::cout << "cmvn_inv_std: ";
43  for (auto f : cmvn_inv_std) {
44    std::cout << f << " ";
45  }
46  std::cout << "\n";
47
48  std::cout << "is training: " << m.is_training() << "\n";
49  m.eval();
50  std::cout << "after m.eval(): is training: " << m.is_training() << "\n";
51  torch::Tensor x = torch::tensor({1, 2, 3}, torch::kFloat);
52  torch::Tensor y = m.run_method("forward", x).toTensor();
53  std::cout << y << "\n";
54
55  return 0;
56}
57/*
58int window size: 20
59cmvn_inv_std:  @aCC
60cmvn_mean: ?@33s
61cmvn_dim: 3
62window_size: 20
63cmvn_mean: 1.5 2.25 -3.8
64cmvn_inv_std: 2.5 225 380
65is training: 1
66after m.eval(): is training: 0
67 3.5000
68 4.5000
69 5.5000
70[ CPUFloatType{3} ]
71 */