benchmark.cpp 7.58 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.
//*****************************************************************************
16

17
#include <random>
18

Ashok Emani's avatar
Ashok Emani committed
19
#include "benchmark.hpp"
20
#include "ngraph/file_util.hpp"
Ashok Emani's avatar
Ashok Emani committed
21
#include "ngraph/runtime/backend.hpp"
22
#include "ngraph/runtime/host_tensor_view.hpp"
Ashok Emani's avatar
Ashok Emani committed
23
#include "ngraph/runtime/tensor_view.hpp"
24
#include "ngraph/runtime/tensor_view.hpp"
Ashok Emani's avatar
Ashok Emani committed
25
#include "ngraph/serializer.hpp"
26
#include "ngraph/util.hpp"
Ashok Emani's avatar
Ashok Emani committed
27

28 29 30
using namespace std;
using namespace ngraph;

31 32 33 34 35
static default_random_engine s_random_engine;

template <typename T>
void init_int_tv(shared_ptr<runtime::TensorView> tv, T min, T max)
{
36
    size_t size = tv->get_element_count();
37
    uniform_int_distribution<T> dist(min, max);
38
    vector<T> vec(size);
39 40 41 42
    for (T& element : vec)
    {
        element = dist(s_random_engine);
    }
43
    tv->write(vec.data(), 0, vec.size() * sizeof(T));
44 45
}

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
template <>
void init_int_tv<char>(shared_ptr<runtime::TensorView> tv, char min, char max)
{
    size_t size = tv->get_element_count();
    uniform_int_distribution<int16_t> dist(static_cast<short>(min), static_cast<short>(max));
    vector<char> vec(size);
    for (char& element : vec)
    {
        element = static_cast<char>(dist(s_random_engine));
    }
    tv->write(vec.data(), 0, vec.size() * sizeof(char));
}

template <>
void init_int_tv<int8_t>(shared_ptr<runtime::TensorView> tv, int8_t min, int8_t max)
{
    size_t size = tv->get_element_count();
    uniform_int_distribution<int16_t> dist(static_cast<short>(min), static_cast<short>(max));
    vector<int8_t> vec(size);
    for (int8_t& element : vec)
    {
        element = static_cast<int8_t>(dist(s_random_engine));
    }
    tv->write(vec.data(), 0, vec.size() * sizeof(int8_t));
}

template <>
void init_int_tv<uint8_t>(shared_ptr<runtime::TensorView> tv, uint8_t min, uint8_t max)
{
    size_t size = tv->get_element_count();
    uniform_int_distribution<int16_t> dist(static_cast<short>(min), static_cast<short>(max));
    vector<uint8_t> vec(size);
    for (uint8_t& element : vec)
    {
        element = static_cast<uint8_t>(dist(s_random_engine));
    }
    tv->write(vec.data(), 0, vec.size() * sizeof(uint8_t));
}

85 86 87
template <typename T>
void init_real_tv(shared_ptr<runtime::TensorView> tv, T min, T max)
{
88
    size_t size = tv->get_element_count();
89
    uniform_real_distribution<T> dist(min, max);
90
    vector<T> vec(size);
91 92 93 94
    for (T& element : vec)
    {
        element = dist(s_random_engine);
    }
95
    tv->write(vec.data(), 0, vec.size() * sizeof(T));
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
}

static void random_init(shared_ptr<runtime::TensorView> tv)
{
    element::Type et = tv->get_tensor().get_element_type();
    if (et == element::boolean)
    {
        init_int_tv<char>(tv, 0, 1);
    }
    else if (et == element::f32)
    {
        init_real_tv<float>(tv, -1, 1);
    }
    else if (et == element::f64)
    {
        init_real_tv<double>(tv, -1, 1);
    }
    else if (et == element::i8)
    {
        init_int_tv<int8_t>(tv, -1, 1);
    }
    else if (et == element::i16)
    {
        init_int_tv<int16_t>(tv, -1, 1);
    }
    else if (et == element::i32)
    {
        init_int_tv<int32_t>(tv, -1, 1);
    }
    else if (et == element::i64)
    {
        init_int_tv<int64_t>(tv, -1, 1);
    }
    else if (et == element::u8)
    {
        init_int_tv<uint8_t>(tv, 0, 1);
    }
    else if (et == element::u16)
    {
        init_int_tv<uint16_t>(tv, 0, 1);
    }
    else if (et == element::u32)
    {
        init_int_tv<uint32_t>(tv, 0, 1);
    }
    else if (et == element::u64)
    {
        init_int_tv<uint64_t>(tv, 0, 1);
    }
    else
    {
        throw runtime_error("unsupported type");
    }
}

151 152 153 154
vector<runtime::PerformanceCounter> run_benchmark(shared_ptr<Function> f,
                                                  const string& backend_name,
                                                  size_t iterations,
                                                  bool timing_detail,
155 156
                                                  int warmup_iterations,
                                                  bool copy_data)
157 158 159
{
    stopwatch timer;
    timer.start();
160 161 162
    auto backend = runtime::Backend::create(backend_name);
    backend->enable_performance_data(f, timing_detail);
    backend->compile(f);
163 164 165
    timer.stop();
    cout.imbue(locale(""));
    cout << "compile time: " << timer.get_milliseconds() << "ms" << endl;
Ashok Emani's avatar
Ashok Emani committed
166

167
    vector<shared_ptr<runtime::HostTensorView>> arg_data;
Ashok Emani's avatar
Ashok Emani committed
168
    vector<shared_ptr<runtime::TensorView>> args;
169
    vector<bool> args_cacheable;
Ashok Emani's avatar
Ashok Emani committed
170 171
    for (shared_ptr<op::Parameter> param : f->get_parameters())
    {
172
        auto tensor = backend->create_tensor(param->get_element_type(), param->get_shape());
173 174
        auto tensor_data =
            make_shared<runtime::HostTensorView>(param->get_element_type(), param->get_shape());
175
        random_init(tensor);
Ashok Emani's avatar
Ashok Emani committed
176
        args.push_back(tensor);
177
        arg_data.push_back(tensor_data);
178
        args_cacheable.push_back(param->get_cacheable());
Ashok Emani's avatar
Ashok Emani committed
179
    }
180
    vector<shared_ptr<runtime::HostTensorView>> result_data;
Ashok Emani's avatar
Ashok Emani committed
181 182 183
    vector<shared_ptr<runtime::TensorView>> results;
    for (shared_ptr<Node> out : f->get_results())
    {
184
        auto result = backend->create_tensor(out->get_element_type(), out->get_shape());
185 186
        auto tensor_data =
            make_shared<runtime::HostTensorView>(out->get_element_type(), out->get_shape());
Ashok Emani's avatar
Ashok Emani committed
187
        results.push_back(result);
188
        result_data.push_back(tensor_data);
Ashok Emani's avatar
Ashok Emani committed
189 190
    }

191 192 193 194 195 196 197
    for (size_t i = 0; i < args.size(); i++)
    {
        if (args_cacheable[i])
        {
            args[i]->set_stale(false);
        }
    }
198 199 200 201 202 203 204 205 206

    if (warmup_iterations)
    {
        for (int i = 0; i < warmup_iterations; i++)
        {
            backend->call(f, results, args);
        }
    }

Ashok Emani's avatar
Ashok Emani committed
207 208
    stopwatch t1;
    t1.start();
209
    for (size_t i = 0; i < iterations; i++)
Ashok Emani's avatar
Ashok Emani committed
210
    {
211 212 213 214 215 216 217 218 219 220 221 222 223 224
        if (copy_data)
        {
            for (size_t arg_index = 0; arg_index < args.size(); arg_index++)
            {
                const shared_ptr<runtime::TensorView>& arg = args[arg_index];
                if (arg->get_stale())
                {
                    const shared_ptr<runtime::HostTensorView>& data = arg_data[arg_index];
                    arg->write(data->get_data_ptr(),
                               0,
                               data->get_size() * data->get_element_type().size());
                }
            }
        }
225
        backend->call(f, results, args);
226 227 228 229 230 231 232 233 234 235
        if (copy_data)
        {
            for (size_t result_index = 0; result_index < results.size(); result_index++)
            {
                const shared_ptr<runtime::HostTensorView>& data = result_data[result_index];
                const shared_ptr<runtime::TensorView>& result = results[result_index];
                result->read(
                    data->get_data_ptr(), 0, data->get_size() * data->get_element_type().size());
            }
        }
Ashok Emani's avatar
Ashok Emani committed
236 237 238 239 240
    }
    t1.stop();
    float time = t1.get_milliseconds();
    cout << time / iterations << "ms per iteration" << endl;

241
    vector<runtime::PerformanceCounter> perf_data = backend->get_performance_data(f);
242
    return perf_data;
Ashok Emani's avatar
Ashok Emani committed
243
}