Bytecode export flow (#25187)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/25187
The bytecode export flow: dump the bytecode format for the light weighted interpreter.
* The bytecode is generated without input spec optimization. It would be more generic (input independent) with no obvious performance degradation (to be tested).
* Main API: torch::jit::script::Module::save(filename, extra_files, bool *bytecode_format* = false).
* Both bytecode and module object are exported in pickle format.
* The module object (in data.pkl) is the same as the original JIT model.
* The serializer is dependent on pickle only (no protobuf or Json).
* The major functionality is forked in ScriptModuleSerializer2::serialize().
* The test loader is test_bc_export.cpp.
* Simple APIs are added in Code and its implementation to get necessary information (instructions, operators and constants).
* Since there's no dependency on graph/node, GetAttr is promoted from an operator to first-class instruction (https://github.com/pytorch/pytorch/pull/25151) .
* Some definitions (instructions, writeArchive, etc) that are shared by full JIT and bytecode are pulled out of the local namespace (https://github.com/pytorch/pytorch/pull/25148).
The output layout looks like:
* folders of methods.
* In each method folder (for example, forward/):
* bytecode.pkl: instructions and operators
* constants{.pkl,/}: constant list in constants.pkl. If there are tensors in constants, the binary tensor files in constants/ folder.
* data{.pkl,/}: the module object, with binary tensor files in data/ folder. The same as in torchscript.
Test Plan: Imported from OSS
Differential Revision: D17076411
fbshipit-source-id: 46eb298e7320d1e585b0101effc0fcfd09219046
2019-09-25 23:34:05 +00:00
|
|
|
#include <test/cpp/jit/test_base.h>
|
2020-02-27 20:18:24 +00:00
|
|
|
#include <torch/csrc/jit/api/module.h>
|
Bytecode export flow (#25187)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/25187
The bytecode export flow: dump the bytecode format for the light weighted interpreter.
* The bytecode is generated without input spec optimization. It would be more generic (input independent) with no obvious performance degradation (to be tested).
* Main API: torch::jit::script::Module::save(filename, extra_files, bool *bytecode_format* = false).
* Both bytecode and module object are exported in pickle format.
* The module object (in data.pkl) is the same as the original JIT model.
* The serializer is dependent on pickle only (no protobuf or Json).
* The major functionality is forked in ScriptModuleSerializer2::serialize().
* The test loader is test_bc_export.cpp.
* Simple APIs are added in Code and its implementation to get necessary information (instructions, operators and constants).
* Since there's no dependency on graph/node, GetAttr is promoted from an operator to first-class instruction (https://github.com/pytorch/pytorch/pull/25151) .
* Some definitions (instructions, writeArchive, etc) that are shared by full JIT and bytecode are pulled out of the local namespace (https://github.com/pytorch/pytorch/pull/25148).
The output layout looks like:
* folders of methods.
* In each method folder (for example, forward/):
* bytecode.pkl: instructions and operators
* constants{.pkl,/}: constant list in constants.pkl. If there are tensors in constants, the binary tensor files in constants/ folder.
* data{.pkl,/}: the module object, with binary tensor files in data/ folder. The same as in torchscript.
Test Plan: Imported from OSS
Differential Revision: D17076411
fbshipit-source-id: 46eb298e7320d1e585b0101effc0fcfd09219046
2019-09-25 23:34:05 +00:00
|
|
|
#include <torch/csrc/autograd/generated/variable_factories.h>
|
|
|
|
|
#include <torch/csrc/jit/mobile/import.h>
|
|
|
|
|
#include <torch/csrc/jit/mobile/module.h>
|
2020-02-27 20:18:24 +00:00
|
|
|
#include <torch/csrc/jit/serialization/import.h>
|
Bytecode export flow (#25187)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/25187
The bytecode export flow: dump the bytecode format for the light weighted interpreter.
* The bytecode is generated without input spec optimization. It would be more generic (input independent) with no obvious performance degradation (to be tested).
* Main API: torch::jit::script::Module::save(filename, extra_files, bool *bytecode_format* = false).
* Both bytecode and module object are exported in pickle format.
* The module object (in data.pkl) is the same as the original JIT model.
* The serializer is dependent on pickle only (no protobuf or Json).
* The major functionality is forked in ScriptModuleSerializer2::serialize().
* The test loader is test_bc_export.cpp.
* Simple APIs are added in Code and its implementation to get necessary information (instructions, operators and constants).
* Since there's no dependency on graph/node, GetAttr is promoted from an operator to first-class instruction (https://github.com/pytorch/pytorch/pull/25151) .
* Some definitions (instructions, writeArchive, etc) that are shared by full JIT and bytecode are pulled out of the local namespace (https://github.com/pytorch/pytorch/pull/25148).
The output layout looks like:
* folders of methods.
* In each method folder (for example, forward/):
* bytecode.pkl: instructions and operators
* constants{.pkl,/}: constant list in constants.pkl. If there are tensors in constants, the binary tensor files in constants/ folder.
* data{.pkl,/}: the module object, with binary tensor files in data/ folder. The same as in torchscript.
Test Plan: Imported from OSS
Differential Revision: D17076411
fbshipit-source-id: 46eb298e7320d1e585b0101effc0fcfd09219046
2019-09-25 23:34:05 +00:00
|
|
|
|
|
|
|
|
// Tests go in torch::jit
|
|
|
|
|
namespace torch {
|
|
|
|
|
namespace jit {
|
|
|
|
|
|
2020-02-04 15:56:47 +00:00
|
|
|
void testLiteInterpreterUpsampleNearest2d() {
|
|
|
|
|
script::Module m("m");
|
|
|
|
|
m.define(R"(
|
|
|
|
|
def forward(self, input: Tensor, scale:float):
|
|
|
|
|
return torch.upsample_nearest2d(input, [1, 1], float(scale), float(scale))
|
|
|
|
|
)");
|
|
|
|
|
|
|
|
|
|
std::vector<IValue> inputs;
|
|
|
|
|
inputs.emplace_back(torch::rand({1, 3, 128, 128}));
|
|
|
|
|
inputs.emplace_back(at::Scalar(2.0));
|
|
|
|
|
auto ref = m.forward(inputs);
|
|
|
|
|
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
m._save_for_mobile(ss);
|
|
|
|
|
mobile::Module bc = _load_for_mobile(ss);
|
|
|
|
|
IValue res;
|
|
|
|
|
res = bc.forward(inputs);
|
|
|
|
|
|
|
|
|
|
auto resd = res.toTensor();
|
|
|
|
|
auto refd = ref.toTensor();
|
|
|
|
|
ASSERT_TRUE(resd.equal(refd));
|
|
|
|
|
}
|
|
|
|
|
|
Add OPN instruction and vararg operator table (#27104)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/27104
* The use case here is to replace prim::ListConstruct, which requires Node, but Node is not available in mobile lite interpreter.
* (OPN, X, N), X is the index to the vararg operator-name and operator tables. N is number of inputs. For ListConstruct example, operator name can be "aten::listconstruct" and the overloaded name is the output type ("int", "float", "bool", "tensor" and "generic").
* A vararg operator table is built with void(int input_size, Stack& stack) functions.
## Unit test
LiteInterpreterConv covers OPN instruction and conv operator.
Test Plan: Imported from OSS
Differential Revision: D17762853
fbshipit-source-id: 475aa0c6678e3760cec805862a78510913a89c83
2019-10-04 16:34:21 +00:00
|
|
|
void testLiteInterpreterAdd() {
|
Bytecode export flow (#25187)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/25187
The bytecode export flow: dump the bytecode format for the light weighted interpreter.
* The bytecode is generated without input spec optimization. It would be more generic (input independent) with no obvious performance degradation (to be tested).
* Main API: torch::jit::script::Module::save(filename, extra_files, bool *bytecode_format* = false).
* Both bytecode and module object are exported in pickle format.
* The module object (in data.pkl) is the same as the original JIT model.
* The serializer is dependent on pickle only (no protobuf or Json).
* The major functionality is forked in ScriptModuleSerializer2::serialize().
* The test loader is test_bc_export.cpp.
* Simple APIs are added in Code and its implementation to get necessary information (instructions, operators and constants).
* Since there's no dependency on graph/node, GetAttr is promoted from an operator to first-class instruction (https://github.com/pytorch/pytorch/pull/25151) .
* Some definitions (instructions, writeArchive, etc) that are shared by full JIT and bytecode are pulled out of the local namespace (https://github.com/pytorch/pytorch/pull/25148).
The output layout looks like:
* folders of methods.
* In each method folder (for example, forward/):
* bytecode.pkl: instructions and operators
* constants{.pkl,/}: constant list in constants.pkl. If there are tensors in constants, the binary tensor files in constants/ folder.
* data{.pkl,/}: the module object, with binary tensor files in data/ folder. The same as in torchscript.
Test Plan: Imported from OSS
Differential Revision: D17076411
fbshipit-source-id: 46eb298e7320d1e585b0101effc0fcfd09219046
2019-09-25 23:34:05 +00:00
|
|
|
script::Module m("m");
|
|
|
|
|
m.register_parameter("foo", torch::ones({}), false);
|
|
|
|
|
// TODO: support default param val, which was pushed in
|
|
|
|
|
// function schema's checkAndNormalizeInputs()
|
|
|
|
|
// m.define(R"(
|
|
|
|
|
// def add_it(self, x, b : int = 4):
|
|
|
|
|
// return self.foo + x + b
|
|
|
|
|
// )");
|
|
|
|
|
m.define(R"(
|
|
|
|
|
def add_it(self, x):
|
|
|
|
|
b = 4
|
|
|
|
|
return self.foo + x + b
|
|
|
|
|
)");
|
|
|
|
|
|
|
|
|
|
std::vector<IValue> inputs;
|
|
|
|
|
auto minput = 5 * torch::ones({});
|
|
|
|
|
inputs.emplace_back(minput);
|
|
|
|
|
auto ref = m.run_method("add_it", minput);
|
|
|
|
|
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
m._save_for_mobile(ss);
|
|
|
|
|
mobile::Module bc = _load_for_mobile(ss);
|
|
|
|
|
IValue res;
|
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
|
|
|
auto bcinputs = inputs;
|
|
|
|
|
res = bc.run_method("add_it", bcinputs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto resd = res.toTensor().item<float>();
|
|
|
|
|
auto refd = ref.toTensor().item<float>();
|
|
|
|
|
AT_ASSERT(resd == refd);
|
|
|
|
|
}
|
|
|
|
|
|
Add OPN instruction and vararg operator table (#27104)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/27104
* The use case here is to replace prim::ListConstruct, which requires Node, but Node is not available in mobile lite interpreter.
* (OPN, X, N), X is the index to the vararg operator-name and operator tables. N is number of inputs. For ListConstruct example, operator name can be "aten::listconstruct" and the overloaded name is the output type ("int", "float", "bool", "tensor" and "generic").
* A vararg operator table is built with void(int input_size, Stack& stack) functions.
## Unit test
LiteInterpreterConv covers OPN instruction and conv operator.
Test Plan: Imported from OSS
Differential Revision: D17762853
fbshipit-source-id: 475aa0c6678e3760cec805862a78510913a89c83
2019-10-04 16:34:21 +00:00
|
|
|
void testLiteInterpreterConv() {
|
2019-10-11 21:03:55 +00:00
|
|
|
auto s = std::getenv("PYTORCH_TEST_WITH_TSAN");
|
|
|
|
|
if (s && strcmp(s, "1") == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
Add OPN instruction and vararg operator table (#27104)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/27104
* The use case here is to replace prim::ListConstruct, which requires Node, but Node is not available in mobile lite interpreter.
* (OPN, X, N), X is the index to the vararg operator-name and operator tables. N is number of inputs. For ListConstruct example, operator name can be "aten::listconstruct" and the overloaded name is the output type ("int", "float", "bool", "tensor" and "generic").
* A vararg operator table is built with void(int input_size, Stack& stack) functions.
## Unit test
LiteInterpreterConv covers OPN instruction and conv operator.
Test Plan: Imported from OSS
Differential Revision: D17762853
fbshipit-source-id: 475aa0c6678e3760cec805862a78510913a89c83
2019-10-04 16:34:21 +00:00
|
|
|
std::vector<torch::jit::IValue> inputs;
|
|
|
|
|
|
|
|
|
|
script::Module m("m");
|
|
|
|
|
m.register_parameter("weight", torch::ones({20, 1, 5, 5}), false);
|
|
|
|
|
m.register_parameter("bias", torch::ones({20}), false);
|
|
|
|
|
m.define(R"(
|
|
|
|
|
def forward(self, input):
|
|
|
|
|
return torch._convolution(input, self.weight, self.bias, [1, 1], [0, 0], [1, 1], False, [0, 0], 1, False, False, True)
|
|
|
|
|
)");
|
|
|
|
|
|
|
|
|
|
inputs.push_back(torch::ones({1, 1, 28, 28}));
|
|
|
|
|
|
|
|
|
|
auto outputref = m.forward(inputs).toTensor();
|
|
|
|
|
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
m._save_for_mobile(ss);
|
|
|
|
|
mobile::Module bc = _load_for_mobile(ss);
|
|
|
|
|
IValue res;
|
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
2019-11-19 06:31:52 +00:00
|
|
|
res = bc.run_method("forward", inputs);
|
Add OPN instruction and vararg operator table (#27104)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/27104
* The use case here is to replace prim::ListConstruct, which requires Node, but Node is not available in mobile lite interpreter.
* (OPN, X, N), X is the index to the vararg operator-name and operator tables. N is number of inputs. For ListConstruct example, operator name can be "aten::listconstruct" and the overloaded name is the output type ("int", "float", "bool", "tensor" and "generic").
* A vararg operator table is built with void(int input_size, Stack& stack) functions.
## Unit test
LiteInterpreterConv covers OPN instruction and conv operator.
Test Plan: Imported from OSS
Differential Revision: D17762853
fbshipit-source-id: 475aa0c6678e3760cec805862a78510913a89c83
2019-10-04 16:34:21 +00:00
|
|
|
}
|
|
|
|
|
auto output = res.toTensor();
|
|
|
|
|
AT_ASSERT(outputref.dim() == output.dim());
|
|
|
|
|
AT_ASSERT(outputref[0][0][0][0].item<int>() == output[0][0][0][0].item<int>());
|
|
|
|
|
}
|
2019-11-08 21:21:55 +00:00
|
|
|
|
|
|
|
|
void testLiteInterpreterInline() {
|
|
|
|
|
script::Module m("m");
|
|
|
|
|
m.define(R"JIT(
|
|
|
|
|
def foo1(self, x):
|
|
|
|
|
return x + 1
|
|
|
|
|
|
|
|
|
|
def foo2(self, x):
|
|
|
|
|
return self.foo1(x) + 2
|
|
|
|
|
|
|
|
|
|
def foo3(self, x):
|
|
|
|
|
return self.foo2(x) + 3
|
|
|
|
|
)JIT");
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
m._save_for_mobile(ss);
|
|
|
|
|
mobile::Module bc = _load_for_mobile(ss);
|
|
|
|
|
std::vector<torch::jit::IValue> inputs({torch::ones({})});
|
|
|
|
|
auto output = bc.run_method("foo3", inputs);
|
|
|
|
|
AT_ASSERT(output.toTensor().item<float>() == 7.0);
|
|
|
|
|
}
|
2019-11-16 00:14:53 +00:00
|
|
|
|
|
|
|
|
void testLiteInterpreterTuple() {
|
|
|
|
|
script::Module m("m");
|
|
|
|
|
m.define(R"JIT(
|
|
|
|
|
def foo(self, x):
|
|
|
|
|
return (1, 2, x + 3)
|
|
|
|
|
|
|
|
|
|
def forward(self, x):
|
|
|
|
|
tuple = self.foo(x)
|
|
|
|
|
return tuple
|
|
|
|
|
)JIT");
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
m._save_for_mobile(ss);
|
|
|
|
|
mobile::Module bc = _load_for_mobile(ss);
|
|
|
|
|
std::vector<torch::jit::IValue> inputs({torch::ones({})});
|
|
|
|
|
auto output = bc.run_method("forward", inputs);
|
|
|
|
|
AT_ASSERT(output.toTuple()->elements()[1].toInt() == 2);
|
|
|
|
|
}
|
2019-11-17 07:55:53 +00:00
|
|
|
|
|
|
|
|
void testLiteInterpreterPrimOverload() {
|
|
|
|
|
script::Module m("m");
|
|
|
|
|
m.define(R"JIT(
|
|
|
|
|
def forward(self, x):
|
|
|
|
|
result = [1, 2]
|
|
|
|
|
result.append(3)
|
|
|
|
|
return result
|
|
|
|
|
)JIT");
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
m._save_for_mobile(ss);
|
|
|
|
|
mobile::Module bc = _load_for_mobile(ss);
|
|
|
|
|
std::vector<torch::jit::IValue> inputs({torch::ones({})});
|
|
|
|
|
auto output = bc.run_method("forward", inputs);
|
|
|
|
|
AT_ASSERT(output.toIntList()[2] == 3);
|
|
|
|
|
}
|
2020-01-04 21:46:05 +00:00
|
|
|
|
|
|
|
|
void testLiteInterpreterPrim() {
|
|
|
|
|
script::Module m("m");
|
|
|
|
|
m.define(R"JIT(
|
|
|
|
|
def forward(self, x):
|
|
|
|
|
return int(x)
|
|
|
|
|
)JIT");
|
|
|
|
|
|
|
|
|
|
std::vector<IValue> inputs;
|
|
|
|
|
auto minput = 3.5 * torch::ones({});
|
|
|
|
|
inputs.emplace_back(minput);
|
|
|
|
|
auto ref = m.run_method("forward", minput);
|
|
|
|
|
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
m._save_for_mobile(ss);
|
|
|
|
|
mobile::Module bc = _load_for_mobile(ss);
|
|
|
|
|
IValue res;
|
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
|
|
|
auto bcinputs = inputs;
|
|
|
|
|
res = bc.run_method("forward", bcinputs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto resi = res.toInt();
|
|
|
|
|
auto refi = ref.toInt();
|
|
|
|
|
AT_ASSERT(resi == refi);
|
|
|
|
|
}
|
2020-02-13 00:25:13 +00:00
|
|
|
|
|
|
|
|
void testLiteInterpreterLoadOrigJit() {
|
|
|
|
|
script::Module m("m");
|
|
|
|
|
m.register_parameter("foo", torch::ones({}), false);
|
|
|
|
|
m.define(R"(
|
|
|
|
|
def forward(self, x):
|
|
|
|
|
b = 4
|
|
|
|
|
return self.foo + x + b
|
|
|
|
|
)");
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
m.save(ss);
|
|
|
|
|
ASSERT_THROWS_WITH(_load_for_mobile(ss), "file not found");
|
|
|
|
|
}
|
|
|
|
|
|
Bytecode export flow (#25187)
Summary:
Pull Request resolved: https://github.com/pytorch/pytorch/pull/25187
The bytecode export flow: dump the bytecode format for the light weighted interpreter.
* The bytecode is generated without input spec optimization. It would be more generic (input independent) with no obvious performance degradation (to be tested).
* Main API: torch::jit::script::Module::save(filename, extra_files, bool *bytecode_format* = false).
* Both bytecode and module object are exported in pickle format.
* The module object (in data.pkl) is the same as the original JIT model.
* The serializer is dependent on pickle only (no protobuf or Json).
* The major functionality is forked in ScriptModuleSerializer2::serialize().
* The test loader is test_bc_export.cpp.
* Simple APIs are added in Code and its implementation to get necessary information (instructions, operators and constants).
* Since there's no dependency on graph/node, GetAttr is promoted from an operator to first-class instruction (https://github.com/pytorch/pytorch/pull/25151) .
* Some definitions (instructions, writeArchive, etc) that are shared by full JIT and bytecode are pulled out of the local namespace (https://github.com/pytorch/pytorch/pull/25148).
The output layout looks like:
* folders of methods.
* In each method folder (for example, forward/):
* bytecode.pkl: instructions and operators
* constants{.pkl,/}: constant list in constants.pkl. If there are tensors in constants, the binary tensor files in constants/ folder.
* data{.pkl,/}: the module object, with binary tensor files in data/ folder. The same as in torchscript.
Test Plan: Imported from OSS
Differential Revision: D17076411
fbshipit-source-id: 46eb298e7320d1e585b0101effc0fcfd09219046
2019-09-25 23:34:05 +00:00
|
|
|
} // namespace jit
|
2020-02-13 00:25:13 +00:00
|
|
|
} // namespace torch
|