serialize.cpp 4.89 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*******************************************************************************
* Copyright 2017-2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
Robert Kimball's avatar
Robert Kimball committed
16

Robert Kimball's avatar
Robert Kimball committed
17 18 19
#include <fstream>
#include <sstream>

Robert Kimball's avatar
Robert Kimball committed
20
#include "gtest/gtest.h"
Robert Kimball's avatar
Robert Kimball committed
21

22
#include "ngraph/file_util.hpp"
Robert Kimball's avatar
Robert Kimball committed
23 24 25 26
#include "ngraph/json.hpp"
#include "ngraph/ngraph.hpp"
#include "ngraph/serializer.hpp"
#include "ngraph/util.hpp"
27
#include "util/test_tools.hpp"
Robert Kimball's avatar
Robert Kimball committed
28 29 30

using namespace std;
using namespace ngraph;
31
using json = nlohmann::json;
Robert Kimball's avatar
Robert Kimball committed
32 33 34 35

TEST(serialize, main)
{
    // First create "f(A,B,C) = (A+B)*C".
36
    Shape shape{2, 2};
37 38 39
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto C = make_shared<op::Parameter>(element::f32, shape);
40
    auto f = make_shared<Function>((A + B) * C, op::Parameters{A, B, C}, "f");
Robert Kimball's avatar
Robert Kimball committed
41 42

    // Now make "g(X,Y,Z) = f(X,Y,Z) + f(X,Y,Z)"
43 44 45
    auto X = make_shared<op::Parameter>(element::f32, shape);
    auto Y = make_shared<op::Parameter>(element::f32, shape);
    auto Z = make_shared<op::Parameter>(element::f32, shape);
Robert Kimball's avatar
Robert Kimball committed
46 47 48 49 50 51
    auto g = make_shared<Function>(make_shared<op::FunctionCall>(f, Nodes{X, Y, Z}) +
                                       make_shared<op::FunctionCall>(f, Nodes{X, Y, Z}),
                                   op::Parameters{X, Y, Z},
                                   "g");

    // Now make "h(X,Y,Z) = g(X,Y,Z) + g(X,Y,Z)"
52 53 54
    auto X1 = make_shared<op::Parameter>(element::f32, shape);
    auto Y1 = make_shared<op::Parameter>(element::f32, shape);
    auto Z1 = make_shared<op::Parameter>(element::f32, shape);
Robert Kimball's avatar
Robert Kimball committed
55 56 57 58 59
    auto h = make_shared<Function>(make_shared<op::FunctionCall>(g, Nodes{X1, Y1, Z1}) +
                                       make_shared<op::FunctionCall>(g, Nodes{X1, Y1, Z1}),
                                   op::Parameters{X1, Y1, Z1},
                                   "h");

60
    string js = serialize(h, 4);
Robert Kimball's avatar
Robert Kimball committed
61 62 63 64 65 66 67 68 69

    {
        ofstream f("serialize_function.js");
        f << js;
    }

    istringstream in(js);
    shared_ptr<Function> sfunc = deserialize(in);

70
    // Now call h on some test vectors.
71
    auto manager = runtime::Manager::get("INTERPRETER");
Robert Kimball's avatar
Robert Kimball committed
72 73 74 75
    auto external = manager->compile(sfunc);
    auto backend = manager->allocate_backend();
    auto cf = backend->make_call_frame(external);

76
    auto x = backend->make_primary_tensor_view(element::f32, shape);
Robert Kimball's avatar
Robert Kimball committed
77
    copy_data(x, vector<float>{1, 2, 3, 4});
78
    auto y = backend->make_primary_tensor_view(element::f32, shape);
Robert Kimball's avatar
Robert Kimball committed
79
    copy_data(y, vector<float>{5, 6, 7, 8});
80
    auto z = backend->make_primary_tensor_view(element::f32, shape);
Robert Kimball's avatar
Robert Kimball committed
81
    copy_data(z, vector<float>{9, 10, 11, 12});
82
    auto result = backend->make_primary_tensor_view(element::f32, shape);
Robert Kimball's avatar
Robert Kimball committed
83 84

    cf->call({x, y, z}, {result});
85
    EXPECT_EQ((vector<float>{216, 320, 440, 576}), read_vector<float>(result));
Robert Kimball's avatar
Robert Kimball committed
86 87

    cf->call({y, x, z}, {result});
88
    EXPECT_EQ((vector<float>{216, 320, 440, 576}), read_vector<float>(result));
Robert Kimball's avatar
Robert Kimball committed
89 90

    cf->call({x, z, y}, {result});
91
    EXPECT_EQ((vector<float>{200, 288, 392, 512}), read_vector<float>(result));
Robert Kimball's avatar
Robert Kimball committed
92
}
93 94 95

TEST(serialize, existing_models)
{
96 97 98 99
    vector<string> models = {"mxnet/mnist_mlp_forward.json",
                             "mxnet/10_bucket_LSTM.json",
                             "mxnet/LSTM_backward.json",
                             "mxnet/LSTM_forward.json"};
100 101 102 103 104

    for (const string& model : models)
    {
        const string json_path = file_util::path_join(SERIALIZED_ZOO, model);
        const string json_string = file_util::read_file_to_string(json_path);
105
        shared_ptr<Function> f = ngraph::deserialize(json_string);
106 107
    }
}
108

109 110 111 112 113 114 115 116 117 118 119 120
TEST(serialize, default_value)
{
    json j = {{"test1", 1}, {"test2", 2}};

    int x1 = j.at("test1").get<int>();
    EXPECT_EQ(x1, 1);
    int x2 = get_or_default<int>(j, "test2", 0);
    EXPECT_EQ(x2, 2);
    int x3 = get_or_default<int>(j, "test3", 3);
    EXPECT_EQ(x3, 3);
}

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
TEST(benchmark, serialize)
{
    stopwatch timer;
    string model = "mxnet/LSTM_backward.json";

    const string json_path = file_util::path_join(SERIALIZED_ZOO, model);
    timer.start();
    const string json_string = file_util::read_file_to_string(json_path);
    timer.stop();
    cout << "file read took " << timer.get_milliseconds() << "ms\n";
    timer.start();
    shared_ptr<Function> f = ngraph::deserialize(json_string);
    timer.stop();
    cout << "deserialize took " << timer.get_milliseconds() << "ms\n";
}