|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801 |
- /**
- * \file src/serialization/test/serializer_oss.cpp
- * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
- *
- * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- */
- #if MGB_ENABLE_FBS_SERIALIZATION
-
- #include "megbrain/serialization/serializer.h"
- #include "megbrain/opr/io.h"
- #include "megbrain/opr/tensor_manip.h"
- #include "megbrain/opr/utility.h"
- #include "megbrain/opr/basic_arith_wrapper.h"
- #include "megbrain/opr/dnn/convolution.h"
- #include "megbrain/test/helper.h"
-
- using namespace mgb;
- using namespace serialization;
-
- #define GET_OUTPUT_FILE() output_file(ssprintf("TestSerializer2.%d", __LINE__))
-
- TEST(TestSerializer2, GraphDumpLoad) {
- auto fname = GET_OUTPUT_FILE();
-
- auto orig_id = -1;
- auto dump = [&]() {
- auto cn = CompNode::load("cpu0");
- auto graph = ComputingGraph::make();
- auto x = opr::ImmutableTensor::make(*graph, 1926.0817f, {cn});
- x.rename("varz");
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = dumper->dump({x});
- ASSERT_EQ(rst.nr_opr, 1);
- ASSERT_EQ(rst.inputs.size(), 0);
- ASSERT_EQ(rst.outputs.size(), 1);
- ASSERT_EQ(rst.params.size(), 0);
- orig_id = x.node()->id();
- mgb_log("%zu of %zu", rst.tensor_value_bytes, rst.tot_bytes);
- };
- auto load = [&]() {
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- ASSERT_EQ(rst.tensor_map.size(), 0);
- ASSERT_EQ(rst.output_var_list.size(), 1);
- ASSERT_EQ(rst.output_var_map.size(), 1);
- ASSERT_EQ(rst.output_var_map_id.size(), 1);
- ASSERT_EQ(rst.output_var_map.count("varz"), 1);
- ASSERT_EQ(rst.output_var_map_id.count(orig_id), 1);
-
- HostTensorND host_x;
-
- auto func = rst.graph_compile(
- {make_callback_copy(rst.output_var_list[0], host_x)});
- func->execute().wait();
- EXPECT_NEAR(*host_x.ptr<float>(), 1926.0817f, 1e-6);
- };
- dump();
- load();
- }
-
- TEST(TestSerializer2, MultiGraphDumpLoad) {
- auto fname = GET_OUTPUT_FILE();
-
- auto dump = [&]() {
- auto cn = CompNode::load("cpu0");
- auto graph = ComputingGraph::make();
- auto x = opr::ImmutableTensor::make(*graph, 1926.0817f, {cn});
- x.rename("varz");
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- // dump twice
- dumper->dump({x});
- dumper->dump({x});
- };
- auto load = [&]() {
- GraphLoader::LoadConfig load_config = {};
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- // load twice
- loader->load(load_config, false);
- loader = GraphLoader::make(loader->reset_file(), loader->format());
- loader->load(load_config, false);
- };
-
- dump();
- load();
- }
-
- TEST(TestSerializer2, APlusB) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
-
- auto dump = [&]() {
- auto cn = CompNode::load("xpu0");
- auto host_x = std::make_shared<HostTensorND>(cn, shape),
- host_y = std::make_shared<HostTensorND>(cn, shape);
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"}),
- y = opr::Host2DeviceCopy::make(*graph, host_y, {"y"});
-
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- // test dump duplicated
- auto rst = dumper->dump({(x + y).rename("z"), x + y});
- ASSERT_EQ(2u, rst.outputs.size());
- };
-
- auto load = [&]() {
- HostTensorGenerator<> gen;
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- auto xv = rst.tensor_map.at("x");
- auto yv = rst.tensor_map.at("y");
- ASSERT_EQ(shape, xv->shape());
- ASSERT_EQ(shape, yv->shape());
- *xv = *gen(shape);
- *yv = *gen(shape);
- HostTensorND host_z, host_z_expect;
- host_z_expect.copy_from(*xv);
- for (size_t i = 0, it = shape.total_nr_elems(); i < it; ++ i)
- host_z_expect.ptr<float>()[i] += yv->ptr<float>()[i];
- auto func = rst.graph_compile(
- {make_callback_copy(rst.output_var_map.at("z"), host_z)});
- func->execute();
- MGB_ASSERT_TENSOR_EQ(host_z_expect, host_z);
- };
-
- dump();
- load();
- }
-
- TEST(TestSerializer2, APlusBParam) {
- auto cns = load_multiple_xpus(2);
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
-
- HostTensorGenerator<> gen;
- auto bias = std::make_shared<DeviceTensorND>();
- auto bias_hv = gen(shape, cns[0]);
- bias->copy_from(*bias_hv);
-
- {
- // dump
- auto host_x = std::make_shared<HostTensorND>(cns[0], shape);
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"}),
- y = opr::SharedDeviceTensor::make(*graph, bias, {"y"});
-
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- GraphDumper::DumpConfig config;
- config.keep_param_name = true;
- dumper->dump({(x + y).rename("z")}, config);
- }
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
-
- auto load = [&](CompNode dest_cn) {
- auto dest_cn_loc = dest_cn.locator_logical();
- auto rst = loader->load({
- [&](CompNode::Locator &loc){ loc = dest_cn_loc;}});
- auto xv = rst.tensor_map.at("x");
- ASSERT_EQ(1u, rst.tensor_map.size());
- ASSERT_EQ(shape, xv->shape());
- *xv = *gen(shape, cns[0]);
- HostTensorND host_z, host_z_expect;
- host_z_expect.copy_from(*xv);
- for (size_t i = 0, it = shape.total_nr_elems(); i < it; ++ i)
- host_z_expect.ptr<float>()[i] += bias_hv->ptr<float>()[i];
- auto func = rst.graph_compile(
- {make_callback_copy(rst.output_var_map.at("z"), host_z)});
- func->execute();
- MGB_ASSERT_TENSOR_EQ(host_z_expect, host_z);
- };
-
- load(cns[0]);
- auto &&shmap = loader->shared_tensor_name_map();
- ASSERT_EQ(1u, shmap.at("y")->size());
- load(cns[0].change_stream(1));
- ASSERT_EQ(1u, shmap.at("y")->size());
- load(cns[1]);
- ASSERT_EQ(1u + (cns[1].mem_node() != cns[0].mem_node()),
- shmap.at("y")->size());
- }
-
- TEST(TestSerializer2, Immutable) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
-
- auto dump = [&]() {
- auto cn = CompNode::load("xpu0");
- auto host_x = std::make_shared<HostTensorND>(cn, shape);
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"});
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- dumper->dump({(x + 1.f).rename("y")});
- };
-
- auto load = [&]() {
- HostTensorGenerator<> gen;
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- auto xv = rst.tensor_map.at("x");
- ASSERT_EQ(shape, xv->shape());
- *xv = *gen(shape);
- HostTensorND host_y, host_y_expect;
- host_y_expect.copy_from(*xv);
- for (size_t i = 0, it = shape.total_nr_elems(); i < it; ++ i)
- host_y_expect.ptr<float>()[i] += 1;
- auto func = rst.graph_compile(
- {make_callback_copy(rst.output_var_map.at("y"), host_y)});
- func->execute();
- MGB_ASSERT_TENSOR_EQ(host_y_expect, host_y);
- };
-
- dump();
- load();
- }
-
- TEST(TestSerializer2, CustomLoader) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
-
- int load_nr_null_ptr = 0, load_nr_call = 0;
- std::vector<HostTensorND> saved_val;
-
- auto tensor_value_dumper = [&saved_val](
- OutputFile &fout, const cg::OperatorNodeBase &opr,
- const HostTensorND &tensor) {
- size_t idx = saved_val.size();
- saved_val.emplace_back();
- saved_val.back().copy_from(tensor);
- fout.write(&idx, sizeof(idx));
- };
- auto tensor_value_loader = [&saved_val, &load_nr_null_ptr, &load_nr_call](
- void *ptr, const TensorLayout &layout, InputFile &fin) {
- ++ load_nr_call;
- size_t idx;
- if (!ptr) {
- load_nr_null_ptr ++;
- fin.skip(sizeof(idx));
- return;
- }
- fin.read(&idx, sizeof(idx));
- auto &&val = saved_val.at(idx);
- ASSERT_TRUE(val.layout().eq_layout(layout));
- memcpy(ptr, val.raw_ptr(), layout.span().high_byte);
- };
-
- auto dump = [&]() {
- auto cn = CompNode::load("xpu0");
- auto host_x = std::make_shared<HostTensorND>(cn, shape);
- HostTensorND y_val(cn, {1});
- y_val.ptr<float>()[0] = 2.3f;
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"}),
- y = opr::SharedDeviceTensor::make(*graph, y_val),
- z = ((x + 1.f) * y).rename("z");
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- GraphDumpConfig config;
- config.tensor_value_dumper = tensor_value_dumper;
- dumper->dump({z}, config);
- };
- dump();
-
- GraphLoadConfig config;
- config.tensor_value_loader = tensor_value_loader;
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto load = [&]() {
- HostTensorGenerator<> gen;
- auto rst = loader->load(config);
- auto xv = rst.tensor_map.at("x");
- ASSERT_EQ(shape, xv->shape());
- *xv = *gen(shape);
- HostTensorND host_y, host_y_expect;
- host_y_expect.copy_from(*xv);
- auto py = host_y_expect.ptr<float>();
- for (size_t i = 0, it = shape.total_nr_elems(); i < it; ++ i) {
- py[i] = (py[i] + 1.f) * 2.3f;
- }
- auto func = rst.graph_compile(
- {make_callback_copy(rst.output_var_map.at("z"), host_y)});
- func->execute();
- MGB_ASSERT_TENSOR_EQ(host_y_expect, host_y);
- };
-
- load();
- load();
- ASSERT_EQ(2u, saved_val.size());
- ASSERT_EQ(1, load_nr_null_ptr); // immutable tensor is not shared
- ASSERT_EQ(4, load_nr_call);
- }
-
- TEST(TestSerializer2, ManyIOVars) {
- auto fname = GET_OUTPUT_FILE();
- constexpr size_t NR_VARS = 32;
- auto dump = [&]() {
- auto graph = ComputingGraph::make();
- SymbolVarArray xs;
- cg::OperatorNodeConfig::CompNodeArray y_comp_nodes;
- for (size_t i = 0; i < NR_VARS; ++ i) {
- CompNode::Locator loc;
- loc.type = CompNode::DeviceType::CPU;
- loc.device = 0;
- loc.stream = i;
- auto cn = CompNode::load(loc);
- auto host_x = std::make_shared<HostTensorND>(cn, TensorShape{1});
- xs.push_back(opr::Host2DeviceCopy::make(
- *graph, host_x, std::to_string(i)));
-
- loc.device = 1;
- y_comp_nodes.push_back(CompNode::load(loc));
- }
- auto con = opr::Concat::make(xs, 0, CompNode::load("cpu2")) * 2 + 1;
- auto ys = opr::Split::make(con,
- opr::Split::Options::make_partition(
- con, 0, std::vector<size_t>(NR_VARS, 1)),
- OperatorNodeConfig{}.comp_node_arr(y_comp_nodes));
-
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = dumper->dump(ys);
- };
-
- auto load = [&]() {
- HostTensorGenerator<> gen;
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- ASSERT_EQ(NR_VARS, rst.output_var_list.size());
- ComputingGraph::OutputSpec out_spec(NR_VARS);
- std::vector<HostTensorND> host_ys(NR_VARS);
- for (size_t i = 0; i < NR_VARS; ++ i) {
- auto y = rst.output_var_list[i];
- auto loc = y.node()->comp_node().locator_logical();
- ASSERT_EQ(1, loc.device);
- ASSERT_EQ(static_cast<int>(i), loc.stream);
- out_spec[i] = make_callback_copy(y, host_ys[i]);
-
- auto &&inp = rst.tensor_map.at(std::to_string(i));
- inp->resize({1}).ptr<float>()[0] = i;
- }
- auto func = rst.graph_compile(out_spec);
- func->execute();
- for (size_t i = 0; i < NR_VARS; ++ i) {
- auto &&val = host_ys[i];
- ASSERT_EQ(TensorShape{1}, val.shape());
- ASSERT_EQ(static_cast<float>(i * 2 + 1), val.ptr<float>()[0]);
- }
- };
-
- dump();
- load();
- }
-
- TEST(TestSerializer2, RemoveSetGrad) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
-
- auto dump = [&]() {
- auto cn = CompNode::load("xpu0");
- auto host_x = std::make_shared<HostTensorND>(cn, shape),
- host_y = std::make_shared<HostTensorND>(cn, shape);
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"}),
- y = opr::Host2DeviceCopy::make(*graph, host_y, {"y"});
-
- auto sg = [](SymbolVar var) {
- return opr::SetGrad::make(var, opr::SetGrad::zero_grad);
- };
-
- // SetGrad as output
- auto z0 = sg(x + y);
- // SetGrad as internal
- auto z1 = sg(x) + sg(sg(y));
-
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- dumper->dump({z0, z1});
- };
-
- auto load = [&]() {
- HostTensorGenerator<> gen;
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- auto xv = rst.tensor_map.at("x");
- auto yv = rst.tensor_map.at("y");
- ASSERT_EQ(shape, xv->shape());
- ASSERT_EQ(shape, yv->shape());
- *xv = *gen(shape);
- *yv = *gen(shape);
- HostTensorND host_z0, host_z1, host_z_expect;
- host_z_expect.copy_from(*xv);
- for (size_t i = 0, it = shape.total_nr_elems(); i < it; ++ i)
- host_z_expect.ptr<float>()[i] += yv->ptr<float>()[i];
- ASSERT_EQ(2u, rst.output_var_list.size());
- auto func = rst.graph_compile({
- {make_callback_copy(rst.output_var_list[0], host_z0)},
- {make_callback_copy(rst.output_var_list[1], host_z1)}});
- func->execute();
- MGB_ASSERT_TENSOR_EQ(host_z_expect, host_z0);
- MGB_ASSERT_TENSOR_EQ(host_z_expect, host_z1);
- };
-
- dump();
- load();
- }
-
- TEST(TestSerializer2, MultipleParamNDIMDTypeCompNode) {
- auto fname = GET_OUTPUT_FILE();
- std::vector<std::shared_ptr<DeviceTensorND>> values;
- auto add_value = [&](int stream, int ndim, DType dtype) {
- CompNode::Locator loc;
- loc.type = CompNode::DeviceType::CPU;
- loc.device = 0;
- loc.stream = stream;
- auto cn = CompNode::load(loc);
-
- TensorShape shp;
- shp.ndim = ndim;
- for (int i = 0; i < ndim; ++ i)
- shp[i] = i + 1;
-
- auto cur = std::make_shared<DeviceTensorND>(cn, shp, dtype);
- uint8_t *ptr = reinterpret_cast<uint8_t*>(cur->raw_ptr());
- for (size_t i = 0, it = cur->layout().span().dist_byte();
- i < it; ++ i) {
- ptr[i] = i;
- }
-
- values.push_back(cur);
- return cur;
- };
- auto dump = [&]() {
- auto graph = ComputingGraph::make();
- int stream = 0;
- auto mkvar = [&](int ndim, DType dtype) {
- auto dv = add_value(stream ++, ndim, dtype);
- auto var = opr::SharedDeviceTensor::make(*graph, dv);
- var = opr::TypeCvt::make(
- opr::reduce_sum(var, var.make_scalar(1)),
- dtype::Int32());
- var = opr::Copy::make(var, CompNode::load("cpu1"));
- return var;
- };
- auto x = mkvar(1, dtype::Float32());
- for (size_t ndim = 1; ndim <= TensorShape::MAX_NDIM; ++ ndim) {
- #define cb(_dt) x = x + mkvar(ndim, _dt());
- MEGDNN_FOREACH_COMPUTING_DTYPE(cb)
- #undef cb
- }
- ASSERT_GT(values.size(), 8u);
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- dumper->dump({x});
- };
-
- auto load = [&]() {
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- ASSERT_THROW(loader->shared_tensor_id_map(), MegBrainError);
- loader->load();
- auto &&got = loader->shared_tensor_id_map();
- ASSERT_EQ(values.size(), got.size());
- for (size_t i = 0; i < values.size(); ++ i) {
- ASSERT_EQ(1u, got[i].second.size());
- auto &&vi = *values[i], &&gi = *got[i].second.begin()->second;
- ASSERT_EQ(vi.shape(), gi.shape());
- ASSERT_EQ(vi.comp_node(), gi.comp_node());
- ASSERT_EQ(vi.dtype(), gi.dtype());
- ASSERT_EQ(0, memcmp(vi.raw_ptr(), gi.raw_ptr(),
- vi.layout().span().dist_byte()));
- }
- };
-
- dump();
- load();
- }
-
- TEST(TestSerializer2, ConstVarShape) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
- HostTensorGenerator<> gen;
- auto host_x = gen({2, 3});
-
- {
- // dump
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"});
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- dumper->dump({x + 1.f});
- }
-
- auto run_and_check = [&](const GraphLoadConfig& config) {
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load(config);
- rst.tensor_map.at("x")->copy_from(*host_x);
- auto y = rst.output_var_list[0];
- ASSERT_EQ(shape, y.shape());
- auto infer_type = y.node()->owner_graph()->static_infer_manager().
- get_infer_type(y.node()).shape;
- if (config.const_var_shape) {
- ASSERT_EQ(cg::static_infer::InferType::CONST, infer_type);
- } else {
- ASSERT_EQ(cg::static_infer::InferType::RT_STATIC, infer_type);
- }
- HostTensorND host_y, host_y_expect;
- host_y_expect.copy_from(*host_x);
- for (size_t i = 0, it = shape.total_nr_elems(); i < it; ++ i)
- host_y_expect.ptr<float>()[i] += 1;
- auto func = rst.graph_compile({make_callback_copy(y, host_y)});
- func->execute();
- MGB_ASSERT_TENSOR_EQ(host_y_expect, host_y);
-
- if (config.const_var_shape) {
- rst.tensor_map.at("x")->resize({4, 5});
- ASSERT_THROW(func->execute(), MegBrainError);
- }
- };
-
- for (bool const_shape: {false, true}) {
- GraphLoadConfig config;
- config.const_var_shape = const_shape;
- run_and_check(config);
- };
-
- // test const shape with tensor modifier
- {
- int nr_tensor = 0, nr_mod = 0;
- shape = {7, 6};
- *host_x = *gen(shape);
- GraphLoadConfig config;
- config.const_var_shape = true;
- config.tensor_modifier = [&](const std::string& name, bool has_value,
- HostTensorND& tensor) {
- ++nr_tensor;
- if (!has_value) {
- ASSERT_EQ("x", name);
- tensor.resize(shape);
- ++nr_mod;
- }
- };
- run_and_check(config);
- ASSERT_EQ(2, nr_tensor);
- ASSERT_EQ(1, nr_mod);
- }
- }
-
- TEST(TestSerializer2, ConstVarShapeOutputName) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
- HostTensorGenerator<> gen;
- auto host_x = gen({2, 3});
-
- {
- // dump
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"}),
- y = opr::GetVarShape::make(x) + 1;
- y.rename("out");
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- dumper->dump({y});
- }
-
- {
- // load
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- GraphLoadConfig config;
- config.const_var_shape = true;
- auto rst = loader->load(config);
- ASSERT_EQ(1u, rst.tensor_map.count("x"));
- auto y = rst.output_var_map.at("out");
- ASSERT_TRUE(y.node()->owner_opr()->same_type<opr::ImmutableTensor>());
- }
- }
-
- TEST(TestSerializer2, Priority) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
-
- auto dump = [&](bool keep_pri) {
- auto cn = CompNode::load("xpu0");
- auto host_x = std::make_shared<HostTensorND>(cn, shape),
- host_y = std::make_shared<HostTensorND>(cn, shape);
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"}) + 1,
- y = opr::Host2DeviceCopy::make(*graph, host_y, {"y"}) + 1;
-
- set_priority(x, 1);
- set_priority(y, 2);
-
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- GraphDumper::DumpConfig config;
- if (keep_pri) {
- config.keep_opr_priority = true;
- }
- dumper->dump({x * y}, config);
- };
-
- auto load = [&](bool has_pri) {
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- VarNode* x, *y;
- unpack_vector(rst.output_var_list.front().node()->owner_opr()->input(),
- x, y);
- auto get_pri = [](VarNode *var) {
- return var->owner_opr()->node_prop().attribute().priority;
- };
- int xpri = get_pri(x), ypri = get_pri(y);
- if (has_pri) {
- ASSERT_EQ(1, xpri);
- ASSERT_EQ(2, ypri);
- } else {
- ASSERT_EQ(0, xpri);
- ASSERT_EQ(0, ypri);
- }
- };
-
- dump(false);
- load(false);
-
- dump(true);
- load(true);
- }
-
- TEST(TestSerializer2, MultipleParams) {
- auto fname = GET_OUTPUT_FILE();
- HostTensorGenerator<> gen;
- std::vector<std::shared_ptr<HostTensorND>> tensors{
- gen({2, 3}), gen({1}), gen({3, 2}), gen({1, 1})};
-
- auto dump = [&]() {
- auto graph = ComputingGraph::make();
- SymbolVarArray outputs;
- for (auto&& i : tensors) {
- outputs.push_back(opr::SharedDeviceTensor::make(*graph, *i));
- }
- GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS)
- ->dump(outputs);
- };
-
- auto load = [&]() {
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- ASSERT_EQ(tensors.size(), rst.output_var_list.size());
- for (size_t i = 0; i < tensors.size(); ++i) {
- HostTensorND got;
- got.copy_from(rst.output_var_list[i]
- .node()
- ->owner_opr()
- ->cast_final_safe<opr::SharedDeviceTensor>()
- .get_dev_tensor())
- .sync();
- MGB_ASSERT_TENSOR_EQ(*tensors[i], got);
- }
- };
-
- dump();
- load();
- }
-
- TEST(TestSerializer2, ParamerizedDType) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3, 3};
- dtype::Quantized8Asymm dtype(0.01f, (uint8_t) 123);
-
- auto dump = [&]() {
- auto cn = CompNode::load("cpu0");
- auto host_x = std::make_shared<HostTensorND>(cn, shape, dtype);
- for (size_t i = 0; i < host_x->layout().span().dist_elem(); i++) {
- host_x->ptr<dt_quint8>()[i] =
- dt_quint8(static_cast<uint8_t>(i & 255));
- }
- auto graph = ComputingGraph::make();
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"});
- auto rst = opr::Dimshuffle::make(x, {1, 2, 0});
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- dumper->dump({rst});
- };
-
- auto load = [&]() {
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- ASSERT_EQ(rst.output_var_list.size(), 1u);
- EXPECT_EQ(rst.output_var_list.front().node()->dtype(), dtype);
- };
-
- dump();
- load();
- }
-
-
- TEST(TestSerializer2, HasOutputDtype) {
- auto fname = GET_OUTPUT_FILE();
-
- HostTensorGenerator<> gen;
-
- auto graph = ComputingGraph::make();
-
- auto gen_tensor = [&](const TensorShape& shape, const DType& dtype) {
- return opr::TypeCvt::make(
- opr::Host2DeviceCopy::make(*graph, gen(shape)), dtype);
- };
-
- auto dump = [&]() {
- auto x = gen_tensor({20, 4, 56, 56}, dtype::QuantizedS8(0.5f));
- auto w = gen_tensor({4, 4, 1, 1}, dtype::QuantizedS8(0.1f));
- auto b = gen_tensor({1, 4, 1, 1}, dtype::QuantizedS32(0.05f));
- opr::ConvBias::Param param;
- auto y0 = opr::ConvBias::make(
- x, w, b, param, {},
- OperatorNodeConfig{dtype::QuantizedS32(0.05f)});
- auto y1 = opr::ConvBias::make(
- x, w, b, param, {},
- OperatorNodeConfig{dtype::QuantizedS8(0.3f)});
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- dumper->dump({y0, y1});
- };
-
- auto check = [](const serialization::GraphLoader::LoadResult& rst,
- size_t idx, const DType& expected_dtype) {
- auto&& dtype = rst.output_var_list[idx]
- .node()->owner_opr()->config().output_dtype();
- ASSERT_TRUE(dtype.valid());
- ASSERT_EQ(dtype, expected_dtype);
- };
-
- auto load = [&]() {
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- ASSERT_EQ(rst.output_var_list.size(), 2u);
- check(rst, 0, dtype::QuantizedS32(0.05f));
- check(rst, 1, dtype::QuantizedS8(0.3f));
- };
-
- dump();
- load();
- }
-
- TEST(TestSerializer2, LOGEXP) {
- auto fname = GET_OUTPUT_FILE();
- TensorShape shape{2, 3};
- using Mode = opr::Elemwise::Mode;
- bool inplace_opt = true;
- auto dump = [&]() {
- auto cn = CompNode::load("xpu0");
- auto host_x = std::make_shared<HostTensorND>(cn, shape);
- for (size_t i = 0, it = shape.total_nr_elems(); i < it; ++i)
- host_x->ptr<float>()[i] = 0.0; // To avoid NAN
- auto graph = ComputingGraph::make();
- if (!inplace_opt)
- graph->options().graph_opt_level = 0;
- auto x = opr::Host2DeviceCopy::make(*graph, host_x, {"x"});
- auto y = opr::Elemwise::make({x}, Mode::EXP);
- auto z = opr::Elemwise::make({y}, Mode::LOG);
-
- auto dumper = GraphDumper::make(OutputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = dumper->dump({z.rename("z"), z});
- size_t expected_nr_opr = inplace_opt? 1: 3;
- ASSERT_EQ(expected_nr_opr, rst.nr_opr);
- };
-
- auto load = [&]() {
- auto loader = GraphLoader::make(InputFile::make_fs(fname.c_str()),
- GraphDumpFormat::FLATBUFFERS);
- auto rst = loader->load();
- };
-
- dump();
- load();
-
- inplace_opt = !inplace_opt;
- dump();
- load();
- }
- #endif
|