[GPU] Serialization of loop primitive (#14703)
This commit is contained in:
1 parent
dea5c1b06e
commit
0ce82204bb
9 files changed
+380
-104
No files matched your search
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include "buffer.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "intel_gpu/primitives/loop.hpp"
|
||||
|
||||
namespace cldnn {
|
||||
template <typename BufferType>
|
||||
class Serializer<BufferType, cldnn::loop::io_primitive_map, typename std::enable_if<std::is_base_of<OutputBuffer<BufferType>, BufferType>::value>::type> {
|
||||
public:
|
||||
static void save(BufferType& buffer, const cldnn::loop::io_primitive_map& io_primitive_map) {
|
||||
buffer << io_primitive_map.external_id;
|
||||
buffer << io_primitive_map.internal_id;
|
||||
buffer << io_primitive_map.axis;
|
||||
buffer << io_primitive_map.start;
|
||||
buffer << io_primitive_map.end;
|
||||
buffer << io_primitive_map.stride;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BufferType>
|
||||
class Serializer<BufferType, cldnn::loop::io_primitive_map, typename std::enable_if<std::is_base_of<InputBuffer<BufferType>, BufferType>::value>::type> {
|
||||
public:
|
||||
static void load(BufferType& buffer, cldnn::loop::io_primitive_map& io_primitive_map) {
|
||||
buffer >> io_primitive_map.external_id;
|
||||
buffer >> io_primitive_map.internal_id;
|
||||
buffer >> io_primitive_map.axis;
|
||||
buffer >> io_primitive_map.start;
|
||||
buffer >> io_primitive_map.end;
|
||||
buffer >> io_primitive_map.stride;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BufferType>
|
||||
class Serializer<BufferType, cldnn::loop::backedge_mapping, typename std::enable_if<std::is_base_of<OutputBuffer<BufferType>, BufferType>::value>::type> {
|
||||
public:
|
||||
static void save(BufferType& buffer, const cldnn::loop::backedge_mapping& backedge_mapping) {
|
||||
buffer << backedge_mapping.from;
|
||||
buffer << backedge_mapping.to;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename BufferType>
|
||||
class Serializer<BufferType, cldnn::loop::backedge_mapping, typename std::enable_if<std::is_base_of<InputBuffer<BufferType>, BufferType>::value>::type> {
|
||||
public:
|
||||
static void load(BufferType& buffer, cldnn::loop::backedge_mapping& backedge_mapping) {
|
||||
buffer >> backedge_mapping.from;
|
||||
buffer >> backedge_mapping.to;
|
||||
}
|
||||
};
|
||||
} // namespace cldnn
|
||||
@@ -76,6 +76,7 @@ struct loop : public primitive_base<loop> {
|
||||
end(end),
|
||||
stride(stride)
|
||||
{}
|
||||
io_primitive_map() {}
|
||||
primitive_id external_id;
|
||||
primitive_id internal_id;
|
||||
int64_t axis;
|
||||
@@ -91,6 +92,7 @@ struct loop : public primitive_base<loop> {
|
||||
/// @param to Input data primitive id of body topology
|
||||
backedge_mapping(primitive_id from, primitive_id to)
|
||||
: from(from), to(to) {}
|
||||
backedge_mapping() {}
|
||||
primitive_id from;
|
||||
primitive_id to;
|
||||
};
|
||||
|
||||
@@ -8,12 +8,16 @@
|
||||
#include "register.hpp"
|
||||
#include "mutable_data_inst.h"
|
||||
#include "input_layout_inst.h"
|
||||
#include "intel_gpu/graph/serialization/loop_serializer.hpp"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace cldnn {
|
||||
namespace common {
|
||||
struct loop_impl : typed_primitive_impl<loop> {
|
||||
using parent = typed_primitive_impl<loop>;
|
||||
using parent::parent;
|
||||
|
||||
DECLARE_OBJECT_TYPE_SERIALIZATION
|
||||
|
||||
std::unique_ptr<primitive_impl> clone() const override {
|
||||
@@ -22,6 +26,8 @@ struct loop_impl : typed_primitive_impl<loop> {
|
||||
|
||||
void init_kernels(const kernels_cache&) override {}
|
||||
|
||||
loop_impl() : parent() {}
|
||||
|
||||
loop_impl(const loop_impl& other) : typed_primitive_impl<loop>(other),
|
||||
_node_id(other._node_id),
|
||||
_current_iteration_id(other._current_iteration_id),
|
||||
@@ -191,6 +197,34 @@ struct loop_impl : typed_primitive_impl<loop> {
|
||||
return make_unique<loop_impl>(arg);
|
||||
}
|
||||
|
||||
void save(BinaryOutputBuffer& ob) const override {
|
||||
parent::save(ob);
|
||||
ob << _node_id;
|
||||
ob << _current_iteration_id;
|
||||
ob << _trip_count_id;
|
||||
ob << _initial_execution_id;
|
||||
ob << _condition_id;
|
||||
ob << _num_iteration_id;
|
||||
ob << _max_iteration;
|
||||
ob << _is_current_iteration_used;
|
||||
ob << _is_execution_condition_used;
|
||||
ob << _back_edges;
|
||||
}
|
||||
|
||||
void load(BinaryInputBuffer& ib) override {
|
||||
parent::load(ib);
|
||||
ib >> _node_id;
|
||||
ib >> _current_iteration_id;
|
||||
ib >> _trip_count_id;
|
||||
ib >> _initial_execution_id;
|
||||
ib >> _condition_id;
|
||||
ib >> _num_iteration_id;
|
||||
ib >> _max_iteration;
|
||||
ib >> _is_current_iteration_used;
|
||||
ib >> _is_execution_condition_used;
|
||||
ib >> _back_edges;
|
||||
}
|
||||
|
||||
private:
|
||||
primitive_id _node_id;
|
||||
primitive_id _current_iteration_id;
|
||||
@@ -201,7 +235,7 @@ private:
|
||||
int64_t _max_iteration;
|
||||
bool _is_current_iteration_used = false;
|
||||
bool _is_execution_condition_used = false;
|
||||
std::vector<cldnn::loop::backedge_mapping> _back_edges{};
|
||||
std::vector<cldnn::loop::backedge_mapping> _back_edges;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
@@ -213,4 +247,4 @@ attach_loop_common::attach_loop_common() {
|
||||
} // namespace common
|
||||
} // namespace cldnn
|
||||
|
||||
ASSIGN_TYPE_NAME(cldnn::common::loop_impl)
|
||||
BIND_BINARY_BUFFER_WITH_TYPE(cldnn::common::loop_impl)
|
||||
@@ -52,36 +52,6 @@ public:
|
||||
bool is_current_iteration_used() const { return use_current_iteration; }
|
||||
bool is_execution_condition_used() const { return use_execution_condition; }
|
||||
|
||||
std::vector<const loop::io_primitive_map*> find_io_primitive_maps(
|
||||
const primitive_id& prim_id,
|
||||
bool is_external) const {
|
||||
std::vector<const loop::io_primitive_map*> ret;
|
||||
if (is_external) {
|
||||
for (const auto& it : input_primitive_maps) {
|
||||
if (it.external_id == prim_id) {
|
||||
ret.push_back(&it);
|
||||
}
|
||||
}
|
||||
for (const auto& it : output_primitive_maps) {
|
||||
if (it.external_id == prim_id) {
|
||||
ret.push_back(&it);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto& it : input_primitive_maps) {
|
||||
if (it.internal_id == prim_id) {
|
||||
ret.push_back(&it);
|
||||
}
|
||||
}
|
||||
for (const auto& it : output_primitive_maps) {
|
||||
if (it.internal_id == prim_id) {
|
||||
ret.push_back(&it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t convert_to_raw_axis(size_t axis, size_t ndim) {
|
||||
// convert between bfyx, bfzyx, bfzyxw and tensor.size.raw
|
||||
if (axis >= ndim) {
|
||||
@@ -572,11 +542,22 @@ public:
|
||||
}
|
||||
return backedge_memory_mappings.at(current_iteratoin_backedge_mapping_idx);
|
||||
}
|
||||
void save(BinaryOutputBuffer& ob) const override;
|
||||
void load(BinaryInputBuffer& ib) override;
|
||||
|
||||
private:
|
||||
network::ptr body_network;
|
||||
memory::ptr get_external_memory(const primitive_id& external_id) const;
|
||||
std::vector<memory::ptr> get_sliced_mem(const primitive_id& internal_id) const;
|
||||
std::vector<loop::io_primitive_map> _input_primitive_maps;
|
||||
std::vector<loop::io_primitive_map> _output_primitive_maps;
|
||||
std::vector<loop::backedge_mapping> _back_edges;
|
||||
primitive_id _trip_count_id;
|
||||
primitive_id _initial_execution_id;
|
||||
primitive_id _current_iteration_id;
|
||||
primitive_id _condition_id;
|
||||
primitive_id _num_iteration_id;
|
||||
int64_t _max_iteration;
|
||||
};
|
||||
|
||||
using loop_inst = typed_primitive_inst<loop>;
|
||||
|
||||
@@ -45,6 +45,8 @@ public:
|
||||
typed_primitive_inst(network& network, mutable_data_node const& node);
|
||||
void set_output_memory(memory::ptr mem, bool check = true, size_t idx = 0) override;
|
||||
const std::list<primitive_id>& get_user_ids() const { return _user_ids; }
|
||||
void save(BinaryOutputBuffer& ob) const override;
|
||||
void load(BinaryInputBuffer& ib) override;
|
||||
|
||||
private:
|
||||
std::list<primitive_id> _user_ids;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "primitive_type_base.h"
|
||||
#include "intel_gpu/primitives/data.hpp"
|
||||
#include "intel_gpu/primitives/mutable_data.hpp"
|
||||
#include "intel_gpu/graph/serialization/loop_serializer.hpp"
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <algorithm>
|
||||
@@ -134,6 +135,38 @@ std::string loop_inst::to_string(const loop_node & node) {
|
||||
return primitive_description.str();
|
||||
}
|
||||
|
||||
static std::vector<const loop::io_primitive_map*> find_io_primitive_maps(
|
||||
const std::vector<loop::io_primitive_map>& input_primitive_maps,
|
||||
const std::vector<loop::io_primitive_map>& output_primitive_maps,
|
||||
const primitive_id& prim_id,
|
||||
bool is_external) {
|
||||
std::vector<const loop::io_primitive_map*> ret;
|
||||
if (is_external) {
|
||||
for (const auto& it : input_primitive_maps) {
|
||||
if (it.external_id == prim_id) {
|
||||
ret.push_back(&it);
|
||||
}
|
||||
}
|
||||
for (const auto& it : output_primitive_maps) {
|
||||
if (it.external_id == prim_id) {
|
||||
ret.push_back(&it);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto& it : input_primitive_maps) {
|
||||
if (it.internal_id == prim_id) {
|
||||
ret.push_back(&it);
|
||||
}
|
||||
}
|
||||
for (const auto& it : output_primitive_maps) {
|
||||
if (it.internal_id == prim_id) {
|
||||
ret.push_back(&it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void validate_mappings(loop_node const & node) {
|
||||
const auto outer_inputs = node.get_dependencies_ids();
|
||||
const auto& input_primitive_maps = node.get_input_primitive_maps();
|
||||
@@ -146,7 +179,8 @@ static void validate_mappings(loop_node const & node) {
|
||||
id == node.get_num_iteration_id()) {
|
||||
continue;
|
||||
}
|
||||
const auto results = node.find_io_primitive_maps(id, true);
|
||||
const auto results = find_io_primitive_maps(node.get_input_primitive_maps(),
|
||||
node.get_output_primitive_maps(), id, true);
|
||||
if (results.size() == 0) {
|
||||
std::string msg = "outer input '" + id + "' does not have primitive map";
|
||||
CLDNN_ERROR_MESSAGE(node.id(), msg.c_str());
|
||||
@@ -190,9 +224,8 @@ void loop_inst::update_mapped_memory() {
|
||||
return;
|
||||
}
|
||||
// update output memory
|
||||
const auto& output_primitive_maps = node->get_output_primitive_maps();
|
||||
for (size_t i = 0; i < output_primitive_maps.size(); ++i) {
|
||||
const auto& output_mapping = output_primitive_maps.at(i);
|
||||
for (size_t i = 0; i < _output_primitive_maps.size(); ++i) {
|
||||
const auto& output_mapping = _output_primitive_maps.at(i);
|
||||
const primitive_id& external_id = output_mapping.external_id;
|
||||
const primitive_id& internal_id = output_mapping.internal_id;
|
||||
memory::ptr to_mem = get_external_memory(external_id);
|
||||
@@ -210,10 +243,11 @@ void loop_inst::update_mapped_memory() {
|
||||
// update input memory
|
||||
for (size_t memory_num = 0; memory_num < inputs_memory_count(); memory_num++) {
|
||||
const primitive_id& input_external_id = dependencies().at(memory_num).first->id();
|
||||
auto input_map_ptrs = node->find_io_primitive_maps(input_external_id, true);
|
||||
auto input_map_ptrs = find_io_primitive_maps(_input_primitive_maps,
|
||||
_output_primitive_maps, input_external_id, true);
|
||||
if (input_map_ptrs.empty()) {
|
||||
if (input_external_id == node->get_trip_count_id() ||
|
||||
input_external_id == node->get_initial_execution_id()) {
|
||||
if (input_external_id == _trip_count_id ||
|
||||
input_external_id == _initial_execution_id) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -235,11 +269,11 @@ void loop_inst::update_mapped_memory() {
|
||||
}
|
||||
}
|
||||
//update backedges memory
|
||||
const auto& back_edges = node->get_back_edges();
|
||||
// checking if memory is a destination of a backedge
|
||||
for (const auto& back_edge : back_edges) {
|
||||
for (const auto& back_edge : _back_edges) {
|
||||
//find corresponding input of the backedge
|
||||
const auto input_map_ptrs = node->find_io_primitive_maps(back_edge.to, false);
|
||||
const auto input_map_ptrs = find_io_primitive_maps(_input_primitive_maps,
|
||||
_output_primitive_maps, back_edge.to, false);
|
||||
assert(input_map_ptrs.size() == 1);
|
||||
const auto& input_map = input_map_ptrs.front();
|
||||
auto backedged_sliced_output_mems = get_sliced_mem(back_edge.from);
|
||||
@@ -252,8 +286,8 @@ void loop_inst::update_mapped_memory() {
|
||||
backedge_mapping.to_primitive->id() == backedge_to_prim->id()) {
|
||||
if (backedged_sliced_output_mems.empty()) {
|
||||
// backedge output which does not need concatenation
|
||||
// input memory = output memory = loop output memory
|
||||
const auto output_mapping = node->find_io_primitive_maps(back_edge.from, false);
|
||||
const auto output_mapping = find_io_primitive_maps(_input_primitive_maps,
|
||||
_output_primitive_maps, back_edge.from, false);
|
||||
memory::ptr backedge_mem;
|
||||
if (output_mapping.empty()) {
|
||||
// from and to primitives in backedge are connected directly
|
||||
@@ -290,10 +324,9 @@ void loop_inst::set_output_memory(memory::ptr mem, bool check, size_t idx) {
|
||||
|
||||
void loop_inst::preprocess_output_memory() {
|
||||
auto& engine = _network.get_engine();
|
||||
const auto& output_primitive_maps = node->get_output_primitive_maps();
|
||||
concatenated_output_mem_mappings.reserve(output_primitive_maps.size());
|
||||
for (size_t i = 0; i < output_primitive_maps.size(); ++i) {
|
||||
const auto& output_mapping = output_primitive_maps.at(i);
|
||||
concatenated_output_mem_mappings.reserve(_output_primitive_maps.size());
|
||||
for (size_t i = 0; i < _output_primitive_maps.size(); ++i) {
|
||||
const auto& output_mapping = _output_primitive_maps.at(i);
|
||||
const primitive_id& external_id = output_mapping.external_id;
|
||||
const primitive_id& internal_id = output_mapping.internal_id;
|
||||
if (output_mapping.axis < 0) {
|
||||
@@ -304,7 +337,7 @@ void loop_inst::preprocess_output_memory() {
|
||||
auto output_prim = body_network->get_primitive(internal_id);
|
||||
layout sliced_layout = output_prim->output_memory().get_layout();
|
||||
|
||||
const int64_t max_iteration = node->get_max_iteration();
|
||||
const int64_t max_iteration = _max_iteration;
|
||||
std::vector<memory::ptr> sliced_mems;
|
||||
sliced_mems.reserve(max_iteration);
|
||||
for (int j=0; j < max_iteration; ++j) {
|
||||
@@ -315,7 +348,7 @@ void loop_inst::preprocess_output_memory() {
|
||||
const int64_t num_elements_batch = concatenated_memory_mapping::get_batch_size(
|
||||
sliced_layout, output_mapping.axis);
|
||||
const int64_t num_elements_iteration = sliced_layout.count() / num_elements_batch;
|
||||
const int64_t start = output_mapping.start < 0? node->get_max_iteration() - 1: output_mapping.start;
|
||||
const int64_t start = output_mapping.start < 0? _max_iteration - 1: output_mapping.start;
|
||||
concatenated_memory_mapping memory_mapping_info(
|
||||
output_mapping.axis, to_mem, sliced_mems, _network.get_stream(),
|
||||
num_elements_iteration, output_mapping.stride, start);
|
||||
@@ -330,10 +363,11 @@ void loop_inst::preprocess_input_memory() {
|
||||
auto& iteration_mem = concatenated_input_mem_mappings;
|
||||
for (size_t memory_num = 0; memory_num < inputs_memory_count(); memory_num++) {
|
||||
const primitive_id& input_external_id = dependencies().at(memory_num).first->id();
|
||||
auto input_map_ptrs = node->find_io_primitive_maps(input_external_id, true);
|
||||
auto input_map_ptrs = find_io_primitive_maps(_input_primitive_maps,
|
||||
_output_primitive_maps, input_external_id, true);
|
||||
if (input_map_ptrs.size() == 0) {
|
||||
if (input_external_id == node->get_trip_count_id() ||
|
||||
input_external_id == node->get_initial_execution_id()) {
|
||||
if (input_external_id == _trip_count_id ||
|
||||
input_external_id == _initial_execution_id) {
|
||||
continue;
|
||||
}
|
||||
CLDNN_ERROR_MESSAGE(id(), "loop primitive_map is incomplete");
|
||||
@@ -346,7 +380,7 @@ void loop_inst::preprocess_input_memory() {
|
||||
if (is_concatenated_input) {
|
||||
layout sliced_layout
|
||||
= body_network->get_primitive(input_map->internal_id)->output_memory().get_layout();
|
||||
const int64_t max_iteration = node->get_max_iteration();
|
||||
const int64_t max_iteration = _max_iteration;
|
||||
std::vector<memory::ptr> sliced_mems;
|
||||
sliced_mems.reserve(max_iteration);
|
||||
for (int j=0; j < max_iteration; ++j) {
|
||||
@@ -356,7 +390,7 @@ void loop_inst::preprocess_input_memory() {
|
||||
const int64_t num_elements_batch = concatenated_memory_mapping::get_batch_size(
|
||||
sliced_layout, input_map->axis);
|
||||
const int64_t num_elements_iteration = sliced_layout.count() / num_elements_batch;
|
||||
const int64_t start = input_map->start < 0? node->get_max_iteration() - 1: input_map->start;
|
||||
const int64_t start = input_map->start < 0? _max_iteration - 1: input_map->start;
|
||||
concatenated_memory_mapping concatenated_input_mem_mapping_info(
|
||||
input_map->axis, memory, sliced_mems, _network.get_stream(),
|
||||
num_elements_iteration, input_map->stride, start);
|
||||
@@ -373,16 +407,16 @@ void loop_inst::preprocess_input_memory() {
|
||||
}
|
||||
|
||||
void loop_inst::preprocess_backedge_memory() {
|
||||
const auto& back_edges = node->get_back_edges();
|
||||
// checking if memory is a destination of a backedge
|
||||
for (const auto& back_edge : back_edges) {
|
||||
for (const auto& back_edge : _back_edges) {
|
||||
//find corresponding input of the backedge
|
||||
const auto input_map_ptrs = node->find_io_primitive_maps(back_edge.to, false);
|
||||
const auto input_map_ptrs = find_io_primitive_maps(_input_primitive_maps,
|
||||
_output_primitive_maps, back_edge.to, false);
|
||||
const auto backedge_to_prim = body_network->get_primitive(back_edge.to);
|
||||
const auto backedge_from_prim = body_network->get_primitive(back_edge.from);
|
||||
|
||||
memory::ptr initial_mem;
|
||||
if (back_edge.to == node->get_current_iteration_id()) {
|
||||
if (back_edge.to == _current_iteration_id) {
|
||||
const layout current_iteration_layout = backedge_to_prim->output_memory().get_layout();
|
||||
initial_mem = get_network().get_engine().allocate_memory(current_iteration_layout);
|
||||
auto& stream = get_network().get_stream();
|
||||
@@ -398,8 +432,8 @@ void loop_inst::preprocess_backedge_memory() {
|
||||
auto backedged_sliced_output_mems = get_sliced_mem(back_edge.from);
|
||||
if (backedged_sliced_output_mems.empty()) {
|
||||
// backedge output which does not need concatenation
|
||||
// input memory = output memory = loop output memory
|
||||
const auto output_mapping = node->find_io_primitive_maps(back_edge.from, false);
|
||||
const auto output_mapping = find_io_primitive_maps(_input_primitive_maps,
|
||||
_output_primitive_maps, back_edge.from, false);
|
||||
memory::ptr backedge_mem;
|
||||
if (output_mapping.empty()) {
|
||||
// from and to primitives in backedge are connected directly
|
||||
@@ -458,6 +492,45 @@ loop_inst::typed_primitive_inst(network & network, loop_node const & node)
|
||||
|
||||
validate_backedges(node);
|
||||
validate_mappings(node);
|
||||
|
||||
_input_primitive_maps = node.get_input_primitive_maps();
|
||||
_output_primitive_maps = node.get_output_primitive_maps();
|
||||
_back_edges = node.get_back_edges();
|
||||
_trip_count_id = node.get_trip_count_id();
|
||||
_initial_execution_id = node.get_initial_execution_id();
|
||||
_current_iteration_id = node.get_current_iteration_id();
|
||||
_condition_id = node.get_condition_id();
|
||||
_num_iteration_id = node.get_num_iteration_id();
|
||||
_max_iteration = node.get_max_iteration();
|
||||
}
|
||||
|
||||
void loop_inst::save(BinaryOutputBuffer& ob) const {
|
||||
parent::save(ob);
|
||||
ob << _input_primitive_maps;
|
||||
ob << _output_primitive_maps;
|
||||
ob << _back_edges;
|
||||
ob << _trip_count_id;
|
||||
ob << _initial_execution_id;
|
||||
ob << _current_iteration_id;
|
||||
ob << _condition_id;
|
||||
ob << _num_iteration_id;
|
||||
ob << _max_iteration;
|
||||
body_network->save(ob);
|
||||
}
|
||||
|
||||
void loop_inst::load(BinaryInputBuffer& ib) {
|
||||
parent::load(ib);
|
||||
preproc_memories_done = false,
|
||||
ib >> _input_primitive_maps;
|
||||
ib >> _output_primitive_maps;
|
||||
ib >> _back_edges;
|
||||
ib >> _trip_count_id;
|
||||
ib >> _initial_execution_id;
|
||||
ib >> _current_iteration_id;
|
||||
ib >> _condition_id;
|
||||
ib >> _num_iteration_id;
|
||||
ib >> _max_iteration;
|
||||
body_network = std::make_shared<cldnn::network>(ib, get_network().get_stream_ptr(), get_network().get_engine());
|
||||
}
|
||||
|
||||
} // namespace cldnn
|
||||
@@ -81,4 +81,46 @@ mutable_data_inst::typed_primitive_inst(network& network, mutable_data_node cons
|
||||
}
|
||||
}
|
||||
|
||||
void mutable_data_inst::save(cldnn::BinaryOutputBuffer& ob) const {
|
||||
parent::save(ob);
|
||||
|
||||
size_t data_size = _outputs[0]->size();
|
||||
ob << make_data(&data_size, sizeof(size_t));
|
||||
|
||||
if (data_size == 0)
|
||||
return;
|
||||
|
||||
allocation_type _allocation_type = _outputs[0]->get_allocation_type();
|
||||
|
||||
if (_allocation_type == allocation_type::usm_host || _allocation_type == allocation_type::usm_shared) {
|
||||
ob << make_data(_outputs[0]->buffer_ptr(), data_size);
|
||||
} else {
|
||||
mem_lock<char, mem_lock_type::read> lock{_outputs[0], get_node().get_program().get_stream()};
|
||||
ob << make_data(lock.data(), data_size);
|
||||
}
|
||||
}
|
||||
|
||||
void mutable_data_inst::load(BinaryInputBuffer& ib) {
|
||||
parent::load(ib);
|
||||
|
||||
size_t data_size;
|
||||
ib >> make_data(&data_size, sizeof(size_t));
|
||||
|
||||
if (data_size == 0)
|
||||
return;
|
||||
|
||||
OPENVINO_ASSERT(_outputs[0] != nullptr, "Output memory should be allocated before importing data.");
|
||||
|
||||
allocation_type _allocation_type = _outputs[0]->get_allocation_type();
|
||||
|
||||
if (_allocation_type == allocation_type::usm_host || _allocation_type == allocation_type::usm_shared) {
|
||||
ib >> make_data(_outputs[0]->buffer_ptr(), data_size);
|
||||
} else {
|
||||
std::vector<uint8_t> _buf;
|
||||
_buf.resize(data_size);
|
||||
ib >> make_data(_buf.data(), data_size);
|
||||
_outputs[0]->copy_from(get_network().get_stream(), _buf.data());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cldnn
|
||||
@@ -495,6 +495,9 @@ void primitive_inst::set_arguments() {
|
||||
}
|
||||
|
||||
void primitive_inst::build_deps() {
|
||||
if (!_deps.empty())
|
||||
return;
|
||||
|
||||
OPENVINO_ASSERT(_node != nullptr, "_node should not be nullptr for build_deps.");
|
||||
|
||||
if (_deps.empty() && !_node->get_dependencies().empty()) {
|
||||
|
||||
@@ -25,7 +25,8 @@ using namespace cldnn;
|
||||
using namespace tests;
|
||||
using namespace testing;
|
||||
|
||||
TEST(loop_gpu, basic_no_concat)
|
||||
template <typename T>
|
||||
void test_loop_gpu_basic_no_concat(bool is_caching_test)
|
||||
{
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
@@ -35,11 +36,11 @@ TEST(loop_gpu, basic_no_concat)
|
||||
auto initial_condition_mem = engine.allocate_memory({ data_types::i32, format::bfyx, { 1, 1, 1, 1 } });
|
||||
auto num_iteration_mem = engine.allocate_memory({ data_types::i32, format::bfyx, { 1, 1, 1, 1 } });
|
||||
|
||||
std::vector<float> input_data{
|
||||
std::vector<T> input_data{
|
||||
1.0f, 2.0f, -15.f, 3.0f, 4.0f, -15.f, 5.0f, 6.0f, -15.f, 7.0f,
|
||||
-15.f, 0.0f, 0.0f, -15.f, 0.5f, -0.5f, -15.f, 8.0f, 1.5f, 5.2f
|
||||
};
|
||||
std::vector<float> eltwise_operand {
|
||||
std::vector<T> eltwise_operand {
|
||||
1.f, -2.f, 3.f, -4.f, 3.0f, -2.0f, 1.f, -2.f, 3.0f, -4.0f,
|
||||
3.f, -2.f, 1.f, -2.f, 3.5f, -4.5f, 5.f, -4.f, 3.5f, -2.2f
|
||||
};
|
||||
@@ -74,12 +75,30 @@ TEST(loop_gpu, basic_no_concat)
|
||||
input_primitive_maps, output_primitive_maps, back_edges, 8)
|
||||
);
|
||||
|
||||
network network(engine, topology);
|
||||
network.set_input_data("input", input_mem);
|
||||
network.set_input_data("trip_count", trip_count_mem);
|
||||
network.set_input_data("initial_condition", initial_condition_mem);
|
||||
cldnn::network::ptr network;
|
||||
|
||||
auto outputs = network.execute();
|
||||
if (is_caching_test) {
|
||||
membuf mem_buf;
|
||||
{
|
||||
cldnn::network _network(engine, topology);
|
||||
std::ostream out_mem(&mem_buf);
|
||||
BinaryOutputBuffer ob = BinaryOutputBuffer(out_mem);
|
||||
_network.save(ob);
|
||||
}
|
||||
{
|
||||
std::istream in_mem(&mem_buf);
|
||||
BinaryInputBuffer ib = BinaryInputBuffer(in_mem, engine);
|
||||
network = std::make_shared<cldnn::network>(ib, get_test_stream_ptr(), engine);
|
||||
}
|
||||
} else {
|
||||
network = std::make_shared<cldnn::network>(engine, topology);
|
||||
}
|
||||
|
||||
network->set_input_data("input", input_mem);
|
||||
network->set_input_data("trip_count", trip_count_mem);
|
||||
network->set_input_data("initial_condition", initial_condition_mem);
|
||||
|
||||
auto outputs = network->execute();
|
||||
ASSERT_EQ(outputs.size(), 1);
|
||||
auto output = outputs.begin()->second.get_memory();
|
||||
auto output_layout = output->get_layout();
|
||||
@@ -91,7 +110,7 @@ TEST(loop_gpu, basic_no_concat)
|
||||
|
||||
// value check
|
||||
{
|
||||
mem_lock<float> output_ptr{ output, get_test_stream() };
|
||||
mem_lock<T> output_ptr{ output, get_test_stream() };
|
||||
ASSERT_EQ(output_ptr.size(), input_data.size());
|
||||
for (size_t i = 0, iend = input_data.size(); i < iend; ++i) {
|
||||
ASSERT_FLOAT_EQ(output_ptr[i], input_data[i] + eltwise_operand[i] * trip_count);
|
||||
@@ -99,22 +118,22 @@ TEST(loop_gpu, basic_no_concat)
|
||||
}
|
||||
|
||||
// allocate new output memory
|
||||
layout loop_l = network.get_output_memory("loop")->get_layout();
|
||||
layout loop_l = network->get_output_memory("loop")->get_layout();
|
||||
auto output_mem = engine.allocate_memory(loop_l);
|
||||
network.set_output_memory("loop", output_mem);
|
||||
network->set_output_memory("loop", output_mem);
|
||||
|
||||
//one more execute
|
||||
set_values(input_mem, input_data);
|
||||
set_values(operand_mem, eltwise_operand);
|
||||
set_values(trip_count_mem, { trip_count });
|
||||
set_values(initial_condition_mem, { initial_condition });
|
||||
outputs = network.execute();
|
||||
outputs = network->execute();
|
||||
|
||||
// check everything once again
|
||||
ASSERT_EQ(outputs.size(), 1);
|
||||
auto output2 = outputs.begin()->second.get_memory();
|
||||
{
|
||||
mem_lock<float> output_ptr2{ output2, get_test_stream() };
|
||||
mem_lock<T> output_ptr2{ output2, get_test_stream() };
|
||||
ASSERT_EQ(output_ptr2.size(), input_data.size());
|
||||
for (size_t i = 0, iend = input_data.size(); i < iend; ++i) {
|
||||
ASSERT_FLOAT_EQ(output_ptr2[i], input_data[i] + eltwise_operand[i] * trip_count);
|
||||
@@ -122,7 +141,16 @@ TEST(loop_gpu, basic_no_concat)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(loop_gpu, basic_concat)
|
||||
TEST(loop_gpu, basic_no_concat) {
|
||||
test_loop_gpu_basic_no_concat<float>(false);
|
||||
}
|
||||
|
||||
TEST(export_import_loop_gpu, basic_no_concat) {
|
||||
test_loop_gpu_basic_no_concat<float>(true);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_loop_gpu_basic_concat(bool is_caching_test)
|
||||
{
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
@@ -132,11 +160,11 @@ TEST(loop_gpu, basic_concat)
|
||||
auto initial_condition_mem = engine.allocate_memory({ data_types::i64, format::bfyx, { 1, 1, 1, 1 } });
|
||||
auto num_iteration_mem = engine.allocate_memory({ data_types::i64, format::bfyx, { 1, 1, 1, 1 } });
|
||||
|
||||
std::vector<float> input_data{
|
||||
std::vector<T> input_data{
|
||||
1.0f, 2.0f, -15.f, 3.0f, 4.0f, -15.f, 5.0f, 6.0f, -15.f, 7.0f,
|
||||
-15.f, 0.0f, 0.0f, -15.f, 0.5f, -0.5f, -15.f, 8.0f, 1.5f, 5.2f
|
||||
};
|
||||
std::vector<float> eltwise_operand {
|
||||
std::vector<T> eltwise_operand {
|
||||
1.f, -2.f, 3.f, -4.f
|
||||
};
|
||||
size_t trip_count = input_data.size()/eltwise_operand.size();
|
||||
@@ -169,12 +197,30 @@ TEST(loop_gpu, basic_concat)
|
||||
input_primitive_maps, output_primitive_maps, back_edges, trip_count)
|
||||
);
|
||||
|
||||
network network(engine, topology);
|
||||
network.set_input_data("input", input_mem);
|
||||
network.set_input_data("trip_count", trip_count_mem);
|
||||
network.set_input_data("initial_condition", initial_condition_mem);
|
||||
cldnn::network::ptr network;
|
||||
|
||||
auto outputs = network.execute();
|
||||
if (is_caching_test) {
|
||||
membuf mem_buf;
|
||||
{
|
||||
cldnn::network _network(engine, topology);
|
||||
std::ostream out_mem(&mem_buf);
|
||||
BinaryOutputBuffer ob = BinaryOutputBuffer(out_mem);
|
||||
_network.save(ob);
|
||||
}
|
||||
{
|
||||
std::istream in_mem(&mem_buf);
|
||||
BinaryInputBuffer ib = BinaryInputBuffer(in_mem, engine);
|
||||
network = std::make_shared<cldnn::network>(ib, get_test_stream_ptr(), engine);
|
||||
}
|
||||
} else {
|
||||
network = std::make_shared<cldnn::network>(engine, topology);
|
||||
}
|
||||
|
||||
network->set_input_data("input", input_mem);
|
||||
network->set_input_data("trip_count", trip_count_mem);
|
||||
network->set_input_data("initial_condition", initial_condition_mem);
|
||||
|
||||
auto outputs = network->execute();
|
||||
ASSERT_EQ(outputs.size(), 1);
|
||||
auto output = outputs.begin()->second.get_memory();
|
||||
auto output_layout = output->get_layout();
|
||||
@@ -186,7 +232,7 @@ TEST(loop_gpu, basic_concat)
|
||||
|
||||
// value check
|
||||
{
|
||||
mem_lock<float> output_ptr{ output, get_test_stream() };
|
||||
mem_lock<T> output_ptr{ output, get_test_stream() };
|
||||
for (size_t i = 0, iend = input_data.size(); i < iend; ++i) {
|
||||
const size_t j = i % eltwise_operand.size();
|
||||
float expected = input_data[i] + eltwise_operand[j];
|
||||
@@ -195,18 +241,18 @@ TEST(loop_gpu, basic_concat)
|
||||
}
|
||||
|
||||
// allocate new output memory
|
||||
layout loop_l = network.get_output_memory("loop")->get_layout();
|
||||
layout loop_l = network->get_output_memory("loop")->get_layout();
|
||||
auto output_mem = engine.allocate_memory(loop_l);
|
||||
network.set_output_memory("loop", output_mem);
|
||||
network->set_output_memory("loop", output_mem);
|
||||
|
||||
set_values(input_mem, input_data);
|
||||
set_values(operand_mem, eltwise_operand);
|
||||
set_values(trip_count_mem, { trip_count });
|
||||
set_values(initial_condition_mem, { initial_condition });
|
||||
outputs = network.execute();
|
||||
outputs = network->execute();
|
||||
auto output2 = outputs.begin()->second.get_memory();
|
||||
{
|
||||
mem_lock<float> output_ptr2{ output2, get_test_stream() };
|
||||
mem_lock<T> output_ptr2{ output2, get_test_stream() };
|
||||
for (size_t i = 0, iend = input_data.size(); i < iend; ++i) {
|
||||
const size_t j = i % eltwise_operand.size();
|
||||
float expected = input_data[i] + eltwise_operand[j];
|
||||
@@ -215,7 +261,16 @@ TEST(loop_gpu, basic_concat)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(loop_gpu, basic_concat_nested)
|
||||
TEST(loop_gpu, basic_concat) {
|
||||
test_loop_gpu_basic_concat<float>(false);
|
||||
}
|
||||
|
||||
TEST(export_import_loop_gpu, basic_concat) {
|
||||
test_loop_gpu_basic_concat<float>(true);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_loop_gpu_basic_concat_nested(bool is_caching_test)
|
||||
{
|
||||
auto& engine = get_test_engine();
|
||||
|
||||
@@ -231,12 +286,12 @@ TEST(loop_gpu, basic_concat_nested)
|
||||
/////////////////////////////////
|
||||
// set data
|
||||
/////////////////////////////////
|
||||
std::vector<float> input_data{
|
||||
std::vector<T> input_data{
|
||||
1.0f, 2.0f, -15.f, 3.0f, 4.0f, -15.f, 5.0f, 6.0f, -15.f, 7.0f,
|
||||
-15.f, 0.0f, 0.0f, -15.f, 0.5f, -0.5f, -15.f, 8.0f, 1.5f, 5.2f
|
||||
};
|
||||
|
||||
std::vector<float> inner_eltwise_operand {
|
||||
std::vector<T> inner_eltwise_operand {
|
||||
1.f, -2.f, 3.f, -4.f
|
||||
};
|
||||
|
||||
@@ -304,14 +359,32 @@ TEST(loop_gpu, basic_concat_nested)
|
||||
/////////////////////////////////
|
||||
// network execution
|
||||
/////////////////////////////////
|
||||
network network(engine, main_topology);
|
||||
network.set_input_data("input", input_mem);
|
||||
network.set_input_data("trip_count", trip_count_mem);
|
||||
network.set_input_data("initial_condition", initial_condition_mem);
|
||||
network.set_input_data("inner_trip_count", inner_trip_count_mem);
|
||||
network.set_input_data("inner_initial_condition", inner_initial_condition_mem);
|
||||
cldnn::network::ptr network;
|
||||
|
||||
auto outputs = network.execute();
|
||||
if (is_caching_test) {
|
||||
membuf mem_buf;
|
||||
{
|
||||
cldnn::network _network(engine, main_topology);
|
||||
std::ostream out_mem(&mem_buf);
|
||||
BinaryOutputBuffer ob = BinaryOutputBuffer(out_mem);
|
||||
_network.save(ob);
|
||||
}
|
||||
{
|
||||
std::istream in_mem(&mem_buf);
|
||||
BinaryInputBuffer ib = BinaryInputBuffer(in_mem, engine);
|
||||
network = std::make_shared<cldnn::network>(ib, get_test_stream_ptr(), engine);
|
||||
}
|
||||
} else {
|
||||
network = std::make_shared<cldnn::network>(engine, main_topology);
|
||||
}
|
||||
|
||||
network->set_input_data("input", input_mem);
|
||||
network->set_input_data("trip_count", trip_count_mem);
|
||||
network->set_input_data("initial_condition", initial_condition_mem);
|
||||
network->set_input_data("inner_trip_count", inner_trip_count_mem);
|
||||
network->set_input_data("inner_initial_condition", inner_initial_condition_mem);
|
||||
|
||||
auto outputs = network->execute();
|
||||
ASSERT_EQ(outputs.size(), 1);
|
||||
auto output = outputs.begin()->second.get_memory();
|
||||
auto output_layout = output->get_layout();
|
||||
@@ -319,8 +392,8 @@ TEST(loop_gpu, basic_concat_nested)
|
||||
/////////////////////////////////
|
||||
// calculate expected output
|
||||
/////////////////////////////////
|
||||
std::vector<float> input_data2(input_data);
|
||||
std::vector<float> expected(input_data2.size());
|
||||
std::vector<T> input_data2(input_data);
|
||||
std::vector<T> expected(input_data2.size());
|
||||
for (int i=0 ; i<outer_trip_count ; ++i) {
|
||||
for (size_t i=0, iend = input_data2.size(); i<iend; ++i) {
|
||||
// eltwise sum in inner loop
|
||||
@@ -341,16 +414,16 @@ TEST(loop_gpu, basic_concat_nested)
|
||||
// check output values
|
||||
ASSERT_EQ(output_layout.count(), expected.size());
|
||||
{
|
||||
mem_lock<float> output_ptr{ output, get_test_stream() };
|
||||
mem_lock<T> output_ptr{ output, get_test_stream() };
|
||||
for (size_t i = 0; i < output_layout.count(); ++i) {
|
||||
ASSERT_FLOAT_EQ(output_ptr[i], expected.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
// allocate new output memory, run and test everything once again
|
||||
layout loop_l = network.get_output_memory("loop")->get_layout();
|
||||
layout loop_l = network->get_output_memory("loop")->get_layout();
|
||||
auto output_mem = engine.allocate_memory(loop_l);
|
||||
network.set_output_memory("loop", output_mem);
|
||||
network->set_output_memory("loop", output_mem);
|
||||
|
||||
set_values(input_mem, input_data);
|
||||
set_values(inner_operand_mem, inner_eltwise_operand);
|
||||
@@ -359,12 +432,20 @@ TEST(loop_gpu, basic_concat_nested)
|
||||
set_values(trip_count_mem, { outer_trip_count });
|
||||
set_values(initial_condition_mem, { outer_initial_condition });
|
||||
|
||||
outputs = network.execute();
|
||||
outputs = network->execute();
|
||||
auto output2 = outputs.begin()->second.get_memory();
|
||||
{
|
||||
mem_lock<float> output_ptr{ output2, get_test_stream() };
|
||||
mem_lock<T> output_ptr{ output2, get_test_stream() };
|
||||
for (size_t i = 0; i < output_layout.count(); ++i) {
|
||||
ASSERT_FLOAT_EQ(output_ptr[i], expected.at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(loop_gpu, basic_concat_nested) {
|
||||
test_loop_gpu_basic_concat_nested<float>(false);
|
||||
}
|
||||
|
||||
TEST(export_import_loop_gpu, basic_concat_nested) {
|
||||
test_loop_gpu_basic_concat_nested<float>(true);
|
||||
}
|
||||
Reference in new issue
Block a user