Introduce data accessor function for infer in IStaticShapeInfer (#15574)

* Tensor accessor for shape inference
- as functor for getting data from tensor vector or map.
- as lambda in GPU plugin on tile op

* Make tensor data adapter pure virtual
- function accessor to data returns pointer to interface

* Refactor tensor data accessor and adapter

* Extract memory adapter make it GPU graph internal
- can't be part of GPU runtime memory core dev API not visible there

* Expand IStaticShapeInfer by port map
- update factory map for new infer interface with port map information
- add bit util to generate bit mask use it in PortMask

* Pass tensor accessor as reference not fun object
- Add cldnn data adapter and accessor
- Reduce dynamic allocations in data accessors

* Fix compilation issues

* Use ov::Tensor for data accessor
- remove data adapters are they not required

* Update comments

* Fix build issues

* Fix tile shape infer test

* Add empty null tensor accessor as specialization

* Apply style formatting

* Move data accessor from dev API to shape inference

* Fix linking issues
This commit is contained in:
Pawel Raasz
2023-05-11 11:30:30 +02:00
committed by GitHub
parent 30395c3e96
commit c13423e2ca
12 changed files with 420 additions and 104 deletions

View File

@@ -0,0 +1,84 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "intel_gpu/runtime/memory.hpp"
#include "tensor_data_accessor.hpp"
namespace cldnn {
/**
* @brief CLDNN memory accessor implementing ov::ITensorAccessor to get data as tensor from CLDNN container.
*/
struct MemoryAccessor : public ov::ITensorAccessor {
using container_type = std::map<size_t, memory::ptr>; //!< Alias to cldnn memory map.
/**
* @brief Construct a new Memory Accessor without custom callback.
*
* @param ptrs Pointer to CLDNN memory container pointers.
* @param stream CLDNN stream used for memory locks.
*/
MemoryAccessor(const container_type* ptrs, const stream& stream)
: m_ptrs{ptrs},
m_stream{stream},
m_clbk{},
m_accessed_data{} {}
/**
* @brief Construct a new Memory Accessor with custom callback function.
*
* @param ptrs Pointer to CLDNN memory container pointers.
* @param stream CLDNN stream used for memory locks.
* @param clbk Function object for custom callback when accessing data and not found in CLDNN memories.
*/
MemoryAccessor(const container_type* ptrs, const stream& stream, std::function<const ov::Tensor(size_t)> clbk)
: m_ptrs{ptrs},
m_stream{stream},
m_clbk{std::move(clbk)},
m_accessed_data{} {}
~MemoryAccessor() {
unlock_current_data();
}
/**
* @brief Get data from CLDNN memory container or by custom callback function if defined.
*
* Data get from CLDNN memory are locket until this accessor will be deleted or access new data.
*
* @param port Number of operator port to access data.
* @return Tensor to data.
*/
ov::Tensor operator()(size_t port) const override {
unlock_current_data();
m_accessed_data = nullptr;
const auto t_iter = m_ptrs->find(port);
if (t_iter != m_ptrs->cend()) {
m_accessed_data = t_iter->second;
return {data_type_to_element_type(m_accessed_data->get_layout().data_type),
m_accessed_data->get_layout().get_shape(),
m_accessed_data->lock(m_stream, mem_lock_type::read)};
} else if (m_clbk) {
return m_clbk(port);
} else {
return ov::make_tensor_accessor()(port);
}
}
private:
void unlock_current_data() const {
if (m_accessed_data) {
m_accessed_data->unlock(m_stream);
}
}
const container_type* m_ptrs; //!< Pointer to CLDNN memory pointers with op data.
const stream& m_stream; //!< Current stream used for data lock.
std::function<ov::Tensor(size_t)> m_clbk; //!< Function object to get data if not in m_ptrs.
mutable memory::ptr m_accessed_data; //!< Pointer to current accessed data.
};
} // namespace cldnn

View File

@@ -6,12 +6,14 @@
#include "tile_shape_inference.hpp"
#include "primitive_type_base.h"
#include "memory_accessor.hpp"
#include "intel_gpu/runtime/memory.hpp"
#include "intel_gpu/runtime/format.hpp"
#include "json_object.h"
#include <string>
namespace cldnn {
GPU_DEFINE_PRIMITIVE_TYPE_ID(tile)
layout tile_inst::calc_output_layout(tile_node const& node, kernel_impl_params const& impl_param) {
@@ -44,36 +46,25 @@ std::vector<layout> tile_inst::calc_output_layouts(tile_node const& /*node*/, co
ShapeType repeats_shape = impl_param.input_layouts.size() == 2 ? impl_param.get_input_layout(1).get<ShapeType>()
: ov::Shape{ desc->repeats.size() };
ov::op::v0::Tile op;
std::vector<ShapeType> output_shapes;
std::vector<ShapeType> input_shapes = {
input0_layout.get<ShapeType>(),
repeats_shape
};
auto& constant_mem = impl_param.memory_deps;
if (desc->input_size() == 2) {
if (constant_mem.count(1)) {
auto repeats_mem = constant_mem.at(1);
cldnn::mem_lock<uint8_t, mem_lock_type::read> repeats_lock(repeats_mem, impl_param.get_stream());
const auto& layout = repeats_mem->get_layout();
const auto repeats_tensor =
ov::Tensor(data_type_to_element_type(layout.data_type), layout.get_shape(), repeats_lock.data());
output_shapes = ov::op::v0::shape_infer(&op, input_shapes, {{1, repeats_tensor}});
} else if (repeats_shape.size() > 0 && repeats_shape[0].is_static()) {
output_shapes = { ov::PartialShape::dynamic(std::max<size_t>(input_shapes[0].size(), repeats_shape[0].get_length())) };
} else {
output_shapes = { ov::PartialShape::dynamic() };
}
} else {
auto repeats_data = desc->repeats;
const auto repeats_tensor =
ov::Tensor(data_type_to_element_type(data_types::i64), repeats_shape.to_shape(), repeats_data.data());
output_shapes = ov::op::v0::shape_infer(&op, input_shapes, {{1, repeats_tensor}});
}
auto repeats = desc->repeats;
const auto data_accessor =
MemoryAccessor(&impl_param.memory_deps, impl_param.prog->get_stream(), [&repeats, &repeats_shape](size_t port) {
return (port == 1 && repeats.data()) ? ov::Tensor(data_type_to_element_type(data_types::i64),
repeats_shape.to_shape(),
repeats.data())
: ov::Tensor();
});
std::vector<ShapeType> output_shapes = ov::op::v0::shape_infer(&op, input_shapes, data_accessor);
format output_format = format::adjust_to_rank(input0_layout.format, output_shapes[0].size());
return { layout{output_shapes[0], output_type, output_format} };
return {layout{output_shapes[0], output_type, output_format}};
}
template std::vector<layout> tile_inst::calc_output_layouts<ov::PartialShape>(tile_node const& node, const kernel_impl_params& impl_param);